From 61067d19cf03ad876954c2644ff9e37942b2ad67 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 13 Mar 2012 22:02:13 +0000 Subject: [PATCH] add some more tests; fix leak in php_http_env_get_response_header(); honor content-type etc. headers in php_http_env_get_request_headers(); --- php_http_env.c | 14 ++++- php_http_message.c | 8 --- php_http_message_body.c | 8 ++- phpunit/MessageBodyTest.php | 4 ++ tests/data/message_r_multipart_put.txt | 65 +++++++++++++++++++++ tests/envrequestbody001.phpt | 15 +++++ tests/envrequestheader001.phpt | 30 ++++++++++ tests/envresponseheader001.phpt | 18 ++++++ tests/envresponseranges001.phpt | 49 ++++++++++++++++ tests/message002.phpt | 8 +-- tests/message003.phpt | 81 ++++++++++++++++++++++++++ tests/negotiate001.phpt | 17 ++++++ tests/response003.phpt | 25 ++++++++ 13 files changed, 326 insertions(+), 16 deletions(-) create mode 100644 tests/data/message_r_multipart_put.txt create mode 100644 tests/envrequestbody001.phpt create mode 100644 tests/envrequestheader001.phpt create mode 100644 tests/envresponseranges001.phpt create mode 100644 tests/message003.phpt create mode 100644 tests/response003.phpt diff --git a/php_http_env.c b/php_http_env.c index d2fe620..96c757b 100644 --- a/php_http_env.c +++ b/php_http_env.c @@ -52,7 +52,7 @@ PHP_HTTP_API void php_http_env_get_request_headers(HashTable *headers TSRMLS_DC) if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) { FOREACH_KEY(pos, *hsv, key) { - if (key.type == HASH_KEY_IS_STRING && key.len > 6 && !strncmp(key.str, "HTTP_", 5)) { + if (key.type == HASH_KEY_IS_STRING && key.len > 6 && *key.str == 'H' && !strncmp(key.str, "HTTP_", 5)) { key.len -= 5; key.str = php_http_pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1); @@ -60,6 +60,14 @@ PHP_HTTP_API void php_http_env_get_request_headers(HashTable *headers TSRMLS_DC) Z_ADDREF_P(*header); zend_symtable_update(PHP_HTTP_G->env.request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL); + efree(key.str); + } else if (key.type == HASH_KEY_IS_STRING && key.len > 9 && *key.str == 'C' && !strncmp(key.str, "CONTENT_", 8)) { + key.str = php_http_pretty_key(estrndup(key.str, key.len - 1), key.len - 1, 1, 1); + + zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos); + Z_ADDREF_P(*header); + zend_symtable_update(PHP_HTTP_G->env.request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL); + efree(key.str); } } @@ -360,7 +368,7 @@ PHP_HTTP_API char *php_http_env_get_response_header(const char *name_str, size_t char *val = NULL; HashTable headers; - zend_hash_init(&headers, 0, NULL, NULL, 0); + zend_hash_init(&headers, 0, NULL, ZVAL_PTR_DTOR, 0); if (SUCCESS == php_http_env_get_response_headers(&headers TSRMLS_CC)) { zval **zvalue; char *key = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1); @@ -661,7 +669,7 @@ PHP_METHOD(HttpEnv, getRequestBody) php_http_message_body_t *body = php_http_env_get_request_body(TSRMLS_C); if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_message_body_object_new_ex, php_http_message_body_class_entry, php_http_message_body_copy(body, NULL, 0), NULL TSRMLS_CC)) { - RETURN_OBJVAL(ov, 0); + RETVAL_OBJVAL(ov, 0); } } } end_error_handling(); diff --git a/php_http_message.c b/php_http_message.c index 7dbf608..58d8ee9 100644 --- a/php_http_message.c +++ b/php_http_message.c @@ -69,14 +69,6 @@ PHP_HTTP_API php_http_message_t *php_http_message_init_env(php_http_message_t *m if ((sval = php_http_env_get_server_var(ZEND_STRL("REQUEST_URI"), 1 TSRMLS_CC))) { message->http.info.request.url = estrdup(Z_STRVAL_P(sval)); } - if ((sval = php_http_env_get_server_var(ZEND_STRL("CONTENT_TYPE"), 1 TSRMLS_CC))) { - Z_ADDREF_P(sval); - zend_hash_update(&message->hdrs, "Content-Type", sizeof("Content-Type"), (void *) &sval, sizeof(zval *), NULL); - } - if ((sval = php_http_env_get_server_var(ZEND_STRL("CONTENT_LENGTH"), 1 TSRMLS_CC))) { - Z_ADDREF_P(sval); - zend_hash_update(&message->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &sval, sizeof(zval *), NULL); - } php_http_env_get_request_headers(&message->hdrs TSRMLS_CC); diff --git a/php_http_message_body.c b/php_http_message_body.c index 34b44f8..e02c2e4 100644 --- a/php_http_message_body.c +++ b/php_http_message_body.c @@ -425,6 +425,7 @@ static size_t splitbody(void *opaque, char *buf, size_t len TSRMLS_DC) if ((boundary = php_http_locate_str(buf, len, arg->boundary_str + first_boundary, arg->boundary_len - first_boundary))) { size_t real_boundary_len = arg->boundary_len - 1, cut; const char *real_boundary = boundary + !first_boundary; + int eol_len = 0; if (buf + len <= real_boundary + real_boundary_len) { /* if we just have enough data for the boundary, it's just a byte too less */ @@ -444,7 +445,12 @@ static size_t splitbody(void *opaque, char *buf, size_t len TSRMLS_DC) len -= cut; consumed += cut; - if (buf == php_http_locate_bin_eol(buf, len, NULL)) { + if (buf == php_http_locate_bin_eol(buf, len, &eol_len)) { + /* skip CRLF */ + buf += eol_len; + len -= eol_len; + consumed += eol_len; + if (!first_boundary) { /* advance messages */ php_http_message_t *msg; diff --git a/phpunit/MessageBodyTest.php b/phpunit/MessageBodyTest.php index 708d317..0218af1 100644 --- a/phpunit/MessageBodyTest.php +++ b/phpunit/MessageBodyTest.php @@ -106,4 +106,8 @@ class MessageBodyTest extends PHPUnit_Framework_TestCase { ); $this->assertEquals($s, (string) $this->file); } + + function testClone() { + $this->assertEquals((string) $this->file, (string) clone $this->file); + } } diff --git a/tests/data/message_r_multipart_put.txt b/tests/data/message_r_multipart_put.txt new file mode 100644 index 0000000..52776d4 --- /dev/null +++ b/tests/data/message_r_multipart_put.txt @@ -0,0 +1,65 @@ +PUT /docs/ HTTP/1.1 +User-Agent: curl/7.24.0 (x86_64-unknown-linux-gnu) libcurl/7.24.0 OpenSSL/1.0.0g zlib/1.2.6 libssh2/1.3.0 +Host: drop +Accept: */* +Content-Length: 2284 +Expect: 100-continue +Content-Type: multipart/form-data; boundary=----------------------------6e182425881c + +------------------------------6e182425881c +Content-Disposition: form-data; name="LICENSE"; filename="LICENSE" +Content-Type: application/octet-stream + +Copyright (c) 2011-2012, Michael Wallner . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +------------------------------6e182425881c +Content-Disposition: form-data; name="composer"; filename="composer.json" +Content-Type: application/octet-stream + +{ + "name": "mike_php_net/autocracy", + "type": "library", + "description": "http\\Controller preserves your autocracy", + "keywords": ["http", "controller", "pecl", "pecl_http"], + "homepage": "http://github.com/mike-php-net/autocracy", + "license": "BSD-2", + "authors": [ + { + "name": "Michael Wallner", + "email": "mike@php.net" + } + ], + "require": { + "php": ">=5.4.0", + "pecl/pecl_http": "2.*" + }, + "autoload": { + "psr-0": { + "http\\Controller": "lib" + } + } +} + +------------------------------6e182425881c-- diff --git a/tests/envrequestbody001.phpt b/tests/envrequestbody001.phpt new file mode 100644 index 0000000..2351186 --- /dev/null +++ b/tests/envrequestbody001.phpt @@ -0,0 +1,15 @@ +--TEST-- +env request body +--SKIPIF-- + +DONE +--EXPECT-- +string(3) "foo" +DONE diff --git a/tests/envrequestheader001.phpt b/tests/envrequestheader001.phpt new file mode 100644 index 0000000..2a6a940 --- /dev/null +++ b/tests/envrequestheader001.phpt @@ -0,0 +1,30 @@ +--TEST-- +request header +--SKIPIF-- + + string(7) "foo.bar" + ["Accept"]=> + string(3) "*/*" + ["Content-Length"]=> + string(1) "3" + ["Content-Type"]=> + string(33) "application/x-www-form-urlencoded" +} diff --git a/tests/envresponseheader001.phpt b/tests/envresponseheader001.phpt index fe7fc75..194f7d7 100644 --- a/tests/envresponseheader001.phpt +++ b/tests/envresponseheader001.phpt @@ -5,17 +5,35 @@ env response header --FILE-- %s [Foo] => bar + [More] => Array + ( + [0] => than + [1] => what's + [2] => good + ) + + [Content-Type] => text/html ) +Created diff --git a/tests/envresponseranges001.phpt b/tests/envresponseranges001.phpt new file mode 100644 index 0000000..ec8fe2f --- /dev/null +++ b/tests/envresponseranges001.phpt @@ -0,0 +1,49 @@ +--TEST-- +ranges +--SKIPIF-- +setBody(new http\Message\Body(fopen(__FILE__, "rb"))); +$r->send(); + +?> +--EXPECTF-- +--%s +Content-Type: application/octet-stream +Content-Range: bytes 107-109/110 + +?> + +--%s +Content-Type: application/octet-stream +Content-Range: bytes 0-1/110 + + + +--%s-- \ No newline at end of file diff --git a/tests/message002.phpt b/tests/message002.phpt index bb19875..005f098 100644 --- a/tests/message002.phpt +++ b/tests/message002.phpt @@ -47,12 +47,12 @@ object(%s)#%d (13) { string(3) "1.1" ["headers":protected]=> array(4) { - ["Content-Type"]=> - string(14) "test/something" - ["Content-Length"]=> - string(1) "3" ["X-Test"]=> string(4) "test" + ["Content-Length"]=> + string(1) "3" + ["Content-Type"]=> + string(14) "test/something" ["Cookie"]=> string(7) "foo=bar" } diff --git a/tests/message003.phpt b/tests/message003.phpt new file mode 100644 index 0000000..0ce10b2 --- /dev/null +++ b/tests/message003.phpt @@ -0,0 +1,81 @@ +--TEST-- +multipart message +--SKIPIF-- +isMultipart($boundary)) { + var_dump($boundary); + + foreach ($m->splitMultipartBody() as $mm) { + echo "===\n",$mm,"===\n"; + } +} +?> +DONE +--EXPECTF-- +string(40) "----------------------------6e182425881c" +=== +Content-Disposition: form-data; name="composer"; filename="composer.json" +Content-Type: application/octet-stream +Content-Length: 567 + +{ + "name": "mike_php_net/autocracy", + "type": "library", + "description": "http\\Controller preserves your autocracy", + "keywords": ["http", "controller", "pecl", "pecl_http"], + "homepage": "http://github.com/mike-php-net/autocracy", + "license": "BSD-2", + "authors": [ + { + "name": "Michael Wallner", + "email": "mike@php.net" + } + ], + "require": { + "php": ">=5.4.0", + "pecl/pecl_http": "2.*" + }, + "autoload": { + "psr-0": { + "http\\Controller": "lib" + } + } +} + + +=== +=== +Content-Disposition: form-data; name="LICENSE"; filename="LICENSE" +Content-Type: application/octet-stream +Content-Length: 1354 + +Copyright (c) 2011-2012, Michael Wallner . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +=== +DONE diff --git a/tests/negotiate001.phpt b/tests/negotiate001.phpt index d7bd755..d384b87 100644 --- a/tests/negotiate001.phpt +++ b/tests/negotiate001.phpt @@ -49,6 +49,14 @@ echo "$ln: "; print_r($lnr); $ln = http\Env::negotiateLanguage(array("nl", "fr", "en"), $lnr); echo "$ln: "; print_r($lnr); ?> + +CUSTOM + + DONE --EXPECT-- CONTENT TYPE @@ -108,4 +116,13 @@ en: Array ( [en] => 0.8 ) + +CUSTOM + +a.b: Array +( + [a.b] => 0.9 + [c.e] => 0.1 + [a.x] => 0.1 +) DONE diff --git a/tests/response003.phpt b/tests/response003.phpt new file mode 100644 index 0000000..1e9e0ab --- /dev/null +++ b/tests/response003.phpt @@ -0,0 +1,25 @@ +--TEST-- +response ranges +--SKIPIF-- + +--ENV-- +HTTP_RANGE=bytes=2-4 +--GET-- +a=b +--FILE-- +setContentType("text/plain"); +$r->setContentDisposition( + http\Env\Response::CONTENT_DISPOSITION_ATTACHMENT, + basename(__FILE__) +); +$r->setBody(new http\Message\Body(fopen(__FILE__, "rb"))); +$r->send(); + +?> +--EXPECTHEADERS-- +Content-Type: text/plain +--EXPECTF-- +php -- 2.30.2