}
/* }}} */
+/* {{{ */
+void _http_key_list_default_decoder(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
+{
+ *decoded = estrndup(encoded, encoded_len);
+ *decoded_len = (size_t) php_url_decode(*decoded, encoded_len);
+}
+/* }}} */
+
+/* {{{ */
+STATUS _http_parse_key_list(const char *list, HashTable *items, char separator, http_key_list_decode_t decode, zend_bool first_entry_is_name_value_pair TSRMLS_DC)
+{
+ const char *key = list, *val = NULL;
+ int vallen = 0, keylen = 0, done = 0;
+ zval array;
+
+ Z_ARRVAL(array) = items;
+
+ if (!(val = strchr(list, '='))) {
+ return FAILURE;
+ }
+
+#define HTTP_KEYLIST_VAL(array, k, str, len) \
+ { \
+ char *decoded; \
+ size_t decoded_len; \
+ if (decode) { \
+ decode(str, len, &decoded, &decoded_len TSRMLS_CC); \
+ } else { \
+ decoded = estrdup(str); \
+ decoded_len = len; \
+ } \
+ add_assoc_stringl(array, k, decoded, decoded_len, 0); \
+ }
+#define HTTP_KEYLIST_FIXKEY() \
+ { \
+ while (isspace(*key)) ++key; \
+ keylen = val - key; \
+ while (isspace(key[keylen - 1])) --keylen; \
+ }
+#define HTTP_KEYLIST_FIXVAL() \
+ { \
+ ++val; \
+ while (isspace(*val)) ++val; \
+ vallen = key - val; \
+ while (isspace(val[vallen - 1])) --vallen; \
+ }
+
+ HTTP_KEYLIST_FIXKEY();
+
+ if (first_entry_is_name_value_pair) {
+ HTTP_KEYLIST_VAL(&array, "name", key, keylen);
+
+ /* just one name=value */
+ if (!(key = strchr(val, separator))) {
+ key = val + strlen(val);
+ HTTP_KEYLIST_FIXVAL();
+ HTTP_KEYLIST_VAL(&array, "value", val, vallen);
+ goto list_done;
+ }
+ /* additional info appended */
+ else {
+ HTTP_KEYLIST_FIXVAL();
+ HTTP_KEYLIST_VAL(&array, "value", val, vallen);
+ }
+ }
+
+ do {
+ char *keydup = NULL;
+
+ if (!(val = strchr(key, '='))) {
+ break;
+ }
+
+ /* start at 0 if first_entry_is_name_value_pair==0 */
+ if (zend_hash_num_elements(items)) {
+ ++key;
+ }
+
+ HTTP_KEYLIST_FIXKEY();
+ keydup = estrndup(key, keylen);
+ if (!(key = strchr(val, separator))) {
+ done = 1;
+ key = val + strlen(val);
+ }
+ HTTP_KEYLIST_FIXVAL();
+ HTTP_KEYLIST_VAL(&array, keydup, val, vallen);
+ efree(keydup);
+ } while (!done);
+
+list_done:
+ return SUCCESS;
+}
+
/* {{{ void http_error(long, long, char*) */
void _http_error_ex(long type, long code, const char *format, ...)
{
* - Digest Auth
*/
-/* {{{ STATUS http_auth_header(char *, char*) */
-PHP_HTTP_API STATUS _http_auth_header(const char *type, const char *realm TSRMLS_DC)
+/* {{{ STATUS http_auth_basic_header(char*) */
+PHP_HTTP_API STATUS _http_auth_basic_header(const char *realm TSRMLS_DC)
{
char realm_header[1024] = {0};
- snprintf(realm_header, 1023, "WWW-Authenticate: %s realm=\"%s\"", type, realm);
+ snprintf(realm_header, 1023, "WWW-Authenticate: Basic realm=\"%s\"", realm);
return http_send_status_header(401, realm_header);
}
/* }}} */
/* {{{ STATUS http_auth_credentials(char **, char **) */
-PHP_HTTP_API STATUS _http_auth_credentials(char **user, char **pass TSRMLS_DC)
+PHP_HTTP_API STATUS _http_auth_basic_credentials(char **user, char **pass TSRMLS_DC)
{
if (strncmp(sapi_module.name, "isapi", 5)) {
zval *zuser, *zpass;
/* }}} */
+/* {{{ Digest * /
+
+#include "ext/standard/php_rand.h"
+#include "ext/standard/md5.h"
+
+#define DIGEST_ALGORITHM "MD5"
+#define DIGEST_SECRETLEN 20
+static unsigned char digest_secret[DIGEST_SECRETLEN];
+
+#define DIGEST_BIN_LEN 16
+typedef char http_digest_bin_t[DIGEST_BIN_LEN];
+#define DIGEST_HEX_LEN 32
+typedef char http_digest_hex_t[DIGEST_HEX_LEN+1];
+
+void _http_auth_global_init(TSRMLS_D)
+{
+ int i;
+ // XX this is pretty loose
+ for (i = 0; i < DIGEST_SECRETLEN; ++i) {
+ digest_secret[i] = (unsigned char) ((php_rand(TSRMLS_C) % 254) + 1);
+ }
+}
+
+static void http_digest_line_decoder(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
+{
+ char l = '\0';
+ size_t i;
+ phpstr s;
+
+ phpstr_init_ex(&s, encoded_len, 1);
+
+ for (i = 0; i < encoded_len; ++i) {
+ if ((encoded[i] != '\\') && (encoded[i] != '"')) {
+ phpstr_append(&s, encoded+i, 1);
+ }
+ }
+
+ phpstr_fix(&s);
+
+ *decoded = PHPSTR_VAL(&s);
+ *decoded_len = PHPSTR_LEN(&s);
+}
+
+static void http_digest_tohex(http_digest_bin_t bin, http_digest_hex_t hex)
+{
+ unsigned short i;
+ unsigned char j;
+
+ for (i = 0; i < DIGEST_BIN_LEN; i++) {
+ j = (bin[i] >> 4) & 0xf;
+ if (j <= 9) {
+ hex[i*2] = (j + '0');
+ } else {
+ hex[i*2] = (j + 'a' - 10);
+ }
+ j = bin[i] & 0xf;
+ if (j <= 9) {
+ hex[i*2+1] = (j + '0');
+ } else {
+ hex[i*2+1] = (j + 'a' - 10);
+ }
+ }
+ hex[DIGEST_HEX_LEN] = '\0';
+}
+
+static void http_digest_calc_HA1(
+ const char *alg, const char *user,
+ const char *realm, const char *pass,
+ const char *nonce, const char *cnonce,
+ http_digest_hex_t HA1)
+{
+ PHP_MD5_CTX md5;
+ http_digest_bin_t HA1_bin;
+
+ PHP_MD5Init(&md5);
+ PHP_MD5Update(&md5, user, strlen(user));
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, realm, strlen(realm));
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, pass, strlen(pass));
+ PHP_MD5Final(HA1_bin, &md5);
+
+ if (strcasecmp(alg, "md5-sess") == 0) {
+ PHP_MD5Init(&md5);
+ PHP_MD5Update(&md5, HA1_bin, DIGEST_BIN_LEN);
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, nonce, strlen(nonce));
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, cnonce, strlen(cnonce));
+ PHP_MD5Final(HA1_bin, &md5);
+ }
+ http_digest_tohex(HA1_bin, HA1);
+}
+
+static void http_digest_calc_response(
+ const http_digest_hex_t HA1,
+ const char *nonce, const char *noncecount,
+ const char *cnonce, const char *qop,
+ const char *method, const char *uri,
+ http_digest_hex_t ent,
+ http_digest_hex_t response)
+{
+ PHP_MD5_CTX md5;
+ http_digest_bin_t HA2;
+ http_digest_bin_t bin;
+ http_digest_hex_t HA2_hex;
+
+ // calculate H(A2)
+ PHP_MD5Init(&md5);
+ PHP_MD5Update(&md5, method, strlen(method));
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, uri, strlen(uri));
+ if (strcasecmp(qop, "auth-int") == 0) {
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, HEntity, DIGEST_HEX_LEN);
+ }
+ PHP_MD5Final(HA2, &md5);
+ http_digest_tohex(HA2, HA2_hex);
+
+ // calculate response
+ PHP_MD5Init(&md5);
+ PHP_MD5Update(&md5, HA1, DIGEST_HEX_LEN);
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, nonce, strlen(nonce));
+ PHP_MD5Update(&md5, ":", 1);
+ if (*qop) {
+ PHP_MD5Update(&md5, noncecount, strlen(noncecount));
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, cnonce, strlen(cnonce));
+ PHP_MD5Update(&md5, ":", 1);
+ PHP_MD5Update(&md5, qop, strlen(qop));
+ PHP_MD5Update(&md5, ":", 1);
+ }
+ PHP_MD5Update(&md5, HA2_hex, DIGEST_HEX_LEN);
+ PHP_MD5Final(bin, &md5);
+ http_digest_tohex(bin, response);
+}
+
+PHP_HTTP_API STATUS _http_auth_digest_credentials(HashTable *items TSRMLS_DC)
+{
+ char *auth;
+ zval array, *zauth = NULL;
+
+ HTTP_GSC(zauth, "HTTP_AUTHORIZATION", FAILURE);
+ auth = Z_STRVAL_P(zauth);
+
+ if (strncasecmp(auth, "Digest ", sizeof("Digest")) || (!(auth += sizeof("Digest")))) {
+ return FAILURE;
+ }
+ if (SUCCESS != http_parse_key_list(auth, items, ',', http_digest_line_decoder, 0)) {
+ return FAILURE;
+ }
+ if ( !zend_hash_exists(items, "uri", sizeof("uri")) ||
+ !zend_hash_exists(items, "realm", sizeof("realm")) ||
+ !zend_hash_exists(items, "nonce", sizeof("nonce")) ||
+ !zend_hash_exists(items, "username", sizeof("username")) ||
+ !zend_hash_exists(items, "response", sizeof("response"))) {
+ zend_hash_clean(items);
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+PHP_HTTP_API STATUS _http_auth_digest_header(const char *realm TSRMLS_DC)
+{
+ return FAILURE;
+}
+/* }}} */
+
+
/*
* Local variables:
* tab-width: 4
realm = "Restricted";
}
- if (SUCCESS != http_auth_credentials(&suser, &spass)) {
- http_auth_header("Basic", realm);
+ if (SUCCESS != http_auth_basic_credentials(&suser, &spass)) {
+ http_auth_basic_header(realm);
RETURN_FALSE;
}
if (strcasecmp(suser, user)) {
- http_auth_header("Basic", realm);
+ http_auth_basic_header(realm);
RETURN_FALSE;
}
if (strcmp(spass, pass)) {
- http_auth_header("Basic", realm);
+ http_auth_basic_header(realm);
RETURN_FALSE;
}
realm = "Restricted";
}
- if (SUCCESS != http_auth_credentials(&user, &pass)) {
- http_auth_header("Basic", realm);
+ if (SUCCESS != http_auth_basic_credentials(&user, &pass)) {
+ http_auth_basic_header(realm);
RETURN_FALSE;
}
{
efree(zparams[1]);
if (!result) {
- http_auth_header("Basic", realm);
+ http_auth_basic_header(realm);
}
RETURN_BOOL(result);
}
}
-/* {{{ */
-PHP_HTTP_API STATUS _http_parse_cookie(const char *cookie, HashTable *values TSRMLS_DC)
-{
- const char *key = cookie, *val = NULL;
- int vallen = 0, keylen = 0, done = 0;
- zval array;
-
- Z_ARRVAL(array) = values;
-
- if (!(val = strchr(cookie, '='))) {
- return FAILURE;
- }
-
-#define HTTP_COOKIE_VAL(array, k, str, len) \
- { \
- const char *encoded = str; \
- char *decoded = NULL; \
- int decoded_len = 0, encoded_len = len; \
- decoded = estrndup(encoded, encoded_len); \
- decoded_len = php_url_decode(decoded, encoded_len); \
- add_assoc_stringl(array, k, decoded, decoded_len, 0); \
- }
-#define HTTP_COOKIE_FIXKEY() \
- { \
- while (isspace(*key)) ++key; \
- keylen = val - key; \
- while (isspace(key[keylen - 1])) --keylen; \
- }
-#define HTTP_COOKIE_FIXVAL() \
- { \
- ++val; \
- while (isspace(*val)) ++val; \
- vallen = key - val; \
- while (isspace(val[vallen - 1])) --vallen; \
- }
-
- HTTP_COOKIE_FIXKEY();
- HTTP_COOKIE_VAL(&array, "name", key, keylen);
-
- /* just a name=value cookie */
- if (!(key = strchr(val, ';'))) {
- key = val + strlen(val);
- HTTP_COOKIE_FIXVAL();
- HTTP_COOKIE_VAL(&array, "value", val, vallen);
- }
- /* additional info appended */
- else {
- char *keydup = NULL;
-
- HTTP_COOKIE_FIXVAL();
- HTTP_COOKIE_VAL(&array, "value", val, vallen);
-
- do {
- if (!(val = strchr(key, '='))) {
- break;
- }
- ++key;
- HTTP_COOKIE_FIXKEY();
- keydup = estrndup(key, keylen);
- if (!(key = strchr(val, ';'))) {
- done = 1;
- key = val + strlen(val);
- }
- HTTP_COOKIE_FIXVAL();
- HTTP_COOKIE_VAL(&array, keydup, val, vallen);
- efree(keydup);
- } while (!done);
- }
- return SUCCESS;
-}
-/* }}} */
-
/* {{{ void http_get_request_headers_ex(HashTable *, zend_bool) */
PHP_HTTP_API void _http_get_request_headers_ex(HashTable *headers, zend_bool prettify TSRMLS_DC)
{
*
* Usage:
* <pre>
- * <?php
- * while ($pool->socketSend()) {
- * do_something_else();
- * if (!$pool->socketSelect()) {
- * die('Socket error');
- * }
- * }
- * $pool->socketRead();
- * ?>
+ * <?php
+ * while ($pool->socketSend()) {
+ * do_something_else();
+ * if (!$pool->socketSelect()) {
+ * die('Socket error');
+ * }
+ * }
+ * $pool->socketRead();
+ * ?>
* </pre>
*/
PHP_METHOD(HttpRequestPool, socketSend)
zend_llist_apply(&obj->pool.handles, (llist_apply_func_t) http_request_pool_responsehandler TSRMLS_CC);
}
+/* }}} */
/* }}} */
STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr, http_request_body *body TSRMLS_DC)
{
zval *meth, *URL, *qdata, *opts;
- char *request_uri, *uri;
+ char *request_uri;
STATUS status;
if (!body) {
body->data = Z_STRVAL_P(post);
body->size = Z_STRLEN_P(post);
- status = http_request_init(obj->ch, Z_LVAL_P(meth), uri, body, Z_ARRVAL_P(opts), &obj->response);
+ status = http_request_init(obj->ch, Z_LVAL_P(meth), request_uri, body, Z_ARRVAL_P(opts), &obj->response);
}
break;
}
#define pretty_key(key, key_len, uctitle, xhyphen) _http_pretty_key(key, key_len, uctitle, xhyphen)
extern char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen);
+typedef void (*http_key_list_decode_t)(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC);
+#define http_key_list_default_decoder _http_key_list_default_decoder
+extern void _http_key_list_default_decoder(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC);
+
+#define http_parse_cookie(l, i) _http_parse_key_list((l), (i), ';', http_key_list_default_decoder, 1 TSRMLS_CC)
+#define http_parse_key_list(l, i, s, d, f) _http_parse_key_list((l), (i), (s), (d), (f) TSRMLS_CC)
+extern STATUS _http_parse_key_list(const char *list, HashTable *items, char separator, http_key_list_decode_t decode, zend_bool first_entry_is_name_value_pair TSRMLS_DC);
+
#define http_error(type, code, string) _http_error_ex(type, code, "%s", string)
#define http_error_ex _http_error_ex
extern void _http_error_ex(long type, long code, const char *format, ...);
#include "php_http_std_defs.h"
-#define http_auth_credentials(u, p) _http_auth_credentials((u), (p) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_auth_credentials(char **user, char **pass TSRMLS_DC);
+#define http_auth_basic_credentials(u, p) _http_auth_basic_credentials((u), (p) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_auth_basic_credentials(char **user, char **pass TSRMLS_DC);
-#define http_auth_header(t, r) _http_auth_header((t), (r) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_auth_header(const char *type, const char *realm TSRMLS_DC);
+#define http_auth_basic_header(r) _http_auth_basic_header((r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_auth_basic_header(const char *realm TSRMLS_DC);
+
+/*
+#define http_auth_digest_credentials(i) _http_auth_digest_credentials((i) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_auth_digest_credentials(HashTable *items TSRMLS_DC);
+
+#define http_auth_digest_header(r) _http_auth_digest_header((r) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_auth_digest_header(const char *realm TSRMLS_DC);
+*/
#endif
#define http_parse_headers_cb(h, ht, p, f, d) _http_parse_headers_ex((h), (ht), (p), (f), (d) TSRMLS_CC)
PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *headers, zend_bool prettify, http_parse_headers_callback_t func, void **callback_data TSRMLS_DC);
-#define http_parse_cookie(c, ht) _http_parse_cookie((c), (ht) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_parse_cookie(const char *cookie, HashTable *values TSRMLS_DC);
-
#define http_get_request_headers(h) _http_get_request_headers_ex(Z_ARRVAL_P(h), 1 TSRMLS_CC)
#define http_get_request_headers_ex(h, p) _http_get_request_headers_ex((h), (p) TSRMLS_CC)
PHP_HTTP_API void _http_get_request_headers_ex(HashTable *headers, zend_bool prettify TSRMLS_DC);