X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=php_http_info.c;h=905091979a70ac08159ac451bb0c561e92181e18;hp=3bde791031e12b4d8d7e28849159fd29cf6af656;hb=refs%2Fheads%2Fv2.3.x;hpb=29a54250b58e444974ae19840194e214cab80bd5 diff --git a/php_http_info.c b/php_http_info.c index 3bde791..9050919 100644 --- a/php_http_info.c +++ b/php_http_info.c @@ -6,36 +6,13 @@ | modification, are permitted provided that the conditions mentioned | | in the accompanying LICENSE file are met. | +--------------------------------------------------------------------+ - | Copyright (c) 2004-2011, Michael Wallner | + | Copyright (c) 2004-2014, Michael Wallner | +--------------------------------------------------------------------+ */ #include "php_http_api.h" -PHP_HTTP_API void php_http_info_default_callback(void **nothing, HashTable **headers, php_http_info_t *info TSRMLS_DC) -{ - zval array; - (void) nothing; - - INIT_PZVAL_ARRAY(&array, *headers); - - switch (info->type) { - case PHP_HTTP_REQUEST: - add_assoc_string(&array, "Request Method", PHP_HTTP_INFO(info).request.method, 1); - add_assoc_string(&array, "Request Url", PHP_HTTP_INFO(info).request.url, 1); - break; - - case PHP_HTTP_RESPONSE: - add_assoc_long(&array, "Response Code", (long) PHP_HTTP_INFO(info).response.code); - add_assoc_string(&array, "Response Status", PHP_HTTP_INFO(info).response.status, 1); - break; - - case PHP_HTTP_NONE: - break; - } -} - -PHP_HTTP_API php_http_info_t *php_http_info_init(php_http_info_t *i TSRMLS_DC) +php_http_info_t *php_http_info_init(php_http_info_t *i TSRMLS_DC) { if (!i) { i = emalloc(sizeof(*i)); @@ -46,16 +23,16 @@ PHP_HTTP_API php_http_info_t *php_http_info_init(php_http_info_t *i TSRMLS_DC) return i; } -PHP_HTTP_API void php_http_info_dtor(php_http_info_t *i) +void php_http_info_dtor(php_http_info_t *i) { switch (i->type) { case PHP_HTTP_REQUEST: - STR_SET(PHP_HTTP_INFO(i).request.method, NULL); - STR_SET(PHP_HTTP_INFO(i).request.url, NULL); + PTR_SET(PHP_HTTP_INFO(i).request.method, NULL); + PTR_SET(PHP_HTTP_INFO(i).request.url, NULL); break; case PHP_HTTP_RESPONSE: - STR_SET(PHP_HTTP_INFO(i).response.status, NULL); + PTR_SET(PHP_HTTP_INFO(i).response.status, NULL); break; default: @@ -63,7 +40,7 @@ PHP_HTTP_API void php_http_info_dtor(php_http_info_t *i) } } -PHP_HTTP_API void php_http_info_free(php_http_info_t **i) +void php_http_info_free(php_http_info_t **i) { if (*i) { php_http_info_dtor(*i); @@ -72,7 +49,7 @@ PHP_HTTP_API void php_http_info_free(php_http_info_t **i) } } -PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_header TSRMLS_DC) +php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_header TSRMLS_DC) { const char *end, *http; zend_bool free_info = !info; @@ -88,15 +65,15 @@ PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const c } /* there must be HTTP/1.x in the line */ - if (!(http = php_http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) { + if (!(http = php_http_locate_str(pre_header, end - pre_header, "HTTP/", lenof("HTTP/")))) { return NULL; } info = php_http_info_init(info TSRMLS_CC); - /* and nothing than SPACE or NUL after HTTP/1.x */ + /* and nothing than SPACE or NUL after HTTP/X.x */ if (!php_http_version_parse(&info->http.version, http TSRMLS_CC) - || (http[lenof("HTTP/1.1")] && (!PHP_HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) { + || (http[lenof("HTTP/X.x")] && (!PHP_HTTP_IS_CTYPE(space, http[lenof("HTTP/X.x")])))) { if (free_info) { php_http_info_free(&info); } @@ -113,13 +90,22 @@ PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const c /* is response */ if (pre_header == http) { - char *status = NULL; - const char *code = http + sizeof("HTTP/1.1"); + const char *status = NULL, *code = http + sizeof("HTTP/X.x"); info->type = PHP_HTTP_RESPONSE; while (' ' == *code) ++code; if (code && end > code) { - PHP_HTTP_INFO(info).response.code = strtol(code, &status, 10); + /* rfc7230#3.1.2 The status-code element is a 3-digit integer code */ + PHP_HTTP_INFO(info).response.code = 100*(*code++ - '0'); + PHP_HTTP_INFO(info).response.code += 10*(*code++ - '0'); + PHP_HTTP_INFO(info).response.code += *code++ - '0'; + if (PHP_HTTP_INFO(info).response.code < 100 || PHP_HTTP_INFO(info).response.code > 599) { + if (free_info) { + php_http_info_free(&info); + } + return NULL; + } + status = code; } else { PHP_HTTP_INFO(info).response.code = 0; } @@ -134,18 +120,27 @@ PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const c } /* is request */ - else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') { + else if (*(http - 1) == ' ' && (!http[lenof("HTTP/X.x")] || http[lenof("HTTP/X.x")] == '\r' || http[lenof("HTTP/X.x")] == '\n')) { const char *url = strchr(pre_header, ' '); info->type = PHP_HTTP_REQUEST; if (url && http > url) { - PHP_HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header); + size_t url_len = url - pre_header; + + PHP_HTTP_INFO(info).request.method = estrndup(pre_header, url_len); + while (' ' == *url) ++url; while (' ' == *(http-1)) --http; + if (http > url) { - PHP_HTTP_INFO(info).request.url = estrndup(url, http - url); + /* CONNECT presents an authority only */ + if (strcasecmp(PHP_HTTP_INFO(info).request.method, "CONNECT")) { + PHP_HTTP_INFO(info).request.url = php_http_url_parse(url, http - url, ~0 TSRMLS_CC); + } else { + PHP_HTTP_INFO(info).request.url = php_http_url_parse_authority(url, http - url, ~0 TSRMLS_CC); + } } else { - efree(PHP_HTTP_INFO(info).request.method); + PTR_SET(PHP_HTTP_INFO(info).request.method, NULL); return NULL; } } else { @@ -156,7 +151,7 @@ PHP_HTTP_API php_http_info_t *php_http_info_parse(php_http_info_t *info, const c return info; } - /* some darn header containing HTTP/1.x */ + /* some darn header containing HTTP/X.x */ else { if (free_info) { php_http_info_free(&info);