- move http_parse_cookie() code to an odd http_parse_key_list() function
authorMichael Wallner <mike@php.net>
Thu, 9 Jun 2005 15:23:33 +0000 (15:23 +0000)
committerMichael Wallner <mike@php.net>
Thu, 9 Jun 2005 15:23:33 +0000 (15:23 +0000)
- name basic auth function basic
- start auth digest implementation
# if anyone wants to get his hands dirty... I've already lost my head

http_api.c
http_auth_api.c
http_functions.c
http_headers_api.c
http_methods.c
http_request_object.c
php_http_api.h
php_http_auth_api.h
php_http_headers_api.h

index 18b14e2..9c587c8 100644 (file)
@@ -60,6 +60,99 @@ char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool x
 }
 /* }}} */
 
+/* {{{ */
+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, ...)
 {
index be2f744..a2c54ae 100644 (file)
  *  - 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;
@@ -77,6 +77,176 @@ PHP_HTTP_API STATUS _http_auth_credentials(char **user, char **pass TSRMLS_DC)
 /* }}} */
 
 
+/* {{{ 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
index fa9cf9c..9f76881 100644 (file)
@@ -1108,18 +1108,18 @@ PHP_FUNCTION(http_auth_basic)
                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;
        }
 
@@ -1161,8 +1161,8 @@ PHP_FUNCTION(http_auth_basic_cb)
                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;
        }
        {
@@ -1185,7 +1185,7 @@ PHP_FUNCTION(http_auth_basic_cb)
                efree(zparams[1]);
 
                if (!result) {
-                       http_auth_header("Basic", realm);
+                       http_auth_basic_header(realm);
                }
 
                RETURN_BOOL(result);
index 81181e5..96a8b66 100644 (file)
@@ -366,78 +366,6 @@ PHP_HTTP_API void _http_parse_headers_default_callback(const char *http_line, Ha
        }
 }
 
-/* {{{ */
-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)
 {
index a8f5d94..ebb892a 100644 (file)
@@ -2237,15 +2237,15 @@ PHP_METHOD(HttpRequestPool, send)
  *
  * 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)
@@ -2284,6 +2284,7 @@ PHP_METHOD(HttpRequestPool, socketRead)
 
        zend_llist_apply(&obj->pool.handles, (llist_apply_func_t) http_request_pool_responsehandler TSRMLS_CC);
 }
+/* }}} */
 
 /* }}} */
 
index 055a43e..1c99c8c 100644 (file)
@@ -208,7 +208,7 @@ void _http_request_object_free(zend_object *object TSRMLS_DC)
 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) {
@@ -283,7 +283,7 @@ STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_
                        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;
        }
index 44d8ac6..a68b5b7 100644 (file)
 #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, ...);
index 7c06980..62ffd3e 100644 (file)
 
 #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
 
index 6d6319a..d3221f5 100644 (file)
@@ -36,9 +36,6 @@ PHP_HTTP_API void _http_parse_headers_default_callback(const char *http_line, Ha
 #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);