X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_api.c;h=66d616d080be6007a694095f890442c3d1f3224a;hp=1a1dfead13c9c035a655a79d312662c90605a94f;hb=107576b154825ebac44f2cc08d97565a5349eca8;hpb=f6108ad70bc06292d0982532f82b77d6e97d7e01 diff --git a/http_api.c b/http_api.c index 1a1dfea..66d616d 100644 --- a/http_api.c +++ b/http_api.c @@ -286,7 +286,7 @@ static int check_tzone(char *tzone) char *pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen) { if (key && key_len) { - int i, wasalpha; + unsigned i, wasalpha; if (wasalpha = isalpha(key[0])) { key[0] = uctitle ? toupper(key[0]) : tolower(key[0]); } @@ -1050,7 +1050,8 @@ PHP_HTTP_API char *_http_negotiate_q(const char *entry, const HashTable *support { zval *zaccept, zdelim, zarray, zentries, **zentry, **zsupp; char *q_ptr = NULL, *key = NULL; - int i = 0, idx = 0; + int i = 0; + ulong idx = 0; double qual; HTTP_GSC(zaccept, entry, estrdup(def)); @@ -1159,7 +1160,12 @@ PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_ { /* "0-12345" */ case -10: - if (length <= end) { + /* "0-" */ + if (end == -1) { + return RANGE_NO; + } + /* "0-0" or overflow */ + if (end == -10 || length <= end) { return RANGE_ERR; } begin = 0; @@ -1167,7 +1173,8 @@ PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_ /* "-12345" */ case -1: - if (length <= end) { + /* "-", "-0" or overflow */ + if (end == -1 || end == -10 || length <= end) { return RANGE_ERR; } begin = length - end; @@ -1178,6 +1185,11 @@ PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_ default: switch (end) { + /* "12345-0" */ + case -10: + return RANGE_ERR; + break; + /* "12345-" */ case -1: if (length <= begin) { @@ -1387,7 +1399,7 @@ PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file, zend_bool close_strea /* }}} */ /* {{{ STATUS http_chunked_decode(char *, size_t, char **, size_t *) */ -PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len, +PHP_HTTP_API STATUS _http_chunked_decode(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC) { const char *e_ptr; @@ -1522,10 +1534,12 @@ PHP_HTTP_API STATUS _http_parse_headers_ex(char *header, size_t header_len, /* skip empty key */ if (header != colon) { - char *key = estrndup(header, colon - header); + zval **previous = NULL; + int keylen = colon - header; + char *key = estrndup(header, keylen); if (prettify) { - key = pretty_key(key, colon - header, 1, 1); + key = pretty_key(key, keylen, 1, 1); } value_len += line - colon - 1; @@ -1535,11 +1549,37 @@ PHP_HTTP_API STATUS _http_parse_headers_ex(char *header, size_t header_len, /* skip trailing ws */ while (isspace(colon[value_len - 1])) --value_len; - if (value_len < 1) { + /* if we already have got such a header make an array of those */ + if (SUCCESS == zend_hash_find(headers, key, keylen + 1, (void **) &previous)) { + /* already an array? - just add */ + if (Z_TYPE_PP(previous) == IS_ARRAY) { + if (value_len > 0) { + add_next_index_stringl(*previous, colon, value_len, 1); + } else { + add_next_index_stringl(*previous, "", 0, 1); + } + } else { + /* create the array */ + zval *new_array; + MAKE_STD_ZVAL(new_array); + array_init(new_array); + + add_next_index_stringl(new_array, Z_STRVAL_PP(previous), Z_STRLEN_PP(previous), 1); + if (value_len > 0) { + add_next_index_stringl(new_array, colon, value_len, 1); + } else { + add_next_index_stringl(new_array, "", 0, 1); + } + + add_assoc_zval(&array, key, new_array); + } + + previous = NULL; + } else if (value_len > 0) { + add_assoc_stringl(&array, key, colon, value_len, 1); + } else { /* hm, empty header? */ add_assoc_stringl(&array, key, "", 0, 1); - } else { - add_assoc_stringl(&array, key, colon, value_len, 1); } efree(key); } @@ -1561,6 +1601,78 @@ PHP_HTTP_API STATUS _http_parse_headers_ex(char *header, size_t header_len, } /* }}} */ +/* {{{ */ +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) { @@ -1605,12 +1717,12 @@ PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_ if (SUCCESS != http_urlencode_hash_implementation(hash, qstr, arg_sep)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data"); - phpstr_dtor(qstr); + phpstr_free(qstr); return FAILURE; } phpstr_data(qstr, encoded_data, encoded_len); - phpstr_dtor(qstr); + phpstr_free(qstr); return SUCCESS; } @@ -1674,7 +1786,7 @@ PHP_HTTP_API STATUS _http_urlencode_hash_implementation_ex( ulong idx; zval **zdata = NULL, *copyzval; - if (!ht) { + if (!ht || !formstr) { return FAILURE; } @@ -1766,7 +1878,7 @@ PHP_HTTP_API STATUS _http_urlencode_hash_implementation_ex( *p = '\0'; } ht->nApplyCount++; - http_urlencode_hash_implementation_ex(HASH_OF(*zdata), formstr, arg_sep, + http_urlencode_hash_implementation_ex(HASH_OF(*zdata), formstr, arg_sep, NULL, 0, newprefix, newprefix_len, "]", 1, (Z_TYPE_PP(zdata) == IS_OBJECT ? *zdata : NULL)); ht->nApplyCount--; efree(newprefix);