Merge branch 'master' of git.php.net:/pecl/http/pecl_http
authorRemi Collet <remi@php.net>
Sat, 2 Aug 2014 15:48:24 +0000 (17:48 +0200)
committerRemi Collet <remi@php.net>
Sat, 2 Aug 2014 15:48:24 +0000 (17:48 +0200)
* 'master' of git.php.net:/pecl/http/pecl_http: (76 commits)
  BFN
  prepare R_2_1_0_RC1
  fix libevent version
  ensure string and custom options are reset properly
  rm unused constant
  upgrade curl stuff
  CURLOPT_XFERINFO{FUNCTION,DATA}
  CURLINFO_TLS_SESSION
  update
  ssl lib config fixes
  error out on missing pecl dependencies
  alloca
  save funccall
  abuse zend_ptr_stack
  abuse zend_ptr_stack for better performance
  save a funccall
  get rid of slow sscanf
  improve message parsing performance by about 25%
  back to dev
  fix xml
  ...

114 files changed:
.gitattributes [new file with mode: 0644]
.gitignore [new file with mode: 0644]
TODO
check_package-xml.php [new file with mode: 0755]
config9.m4
gen_curlinfo.php
package.xml
php_http.h
php_http_buffer.c
php_http_buffer.h
php_http_client.c
php_http_client_curl.c
php_http_cookie.c
php_http_env.c
php_http_env_request.c
php_http_env_response.c
php_http_header_parser.c
php_http_header_parser.h
php_http_message.c
php_http_message_parser.c
php_http_message_parser.h
php_http_misc.c
php_http_misc.h
php_http_params.c
php_http_params.h
php_http_version.c
phpunit.php [deleted file]
phpunit/CookieTest.php [deleted file]
phpunit/EncodingTest.php [deleted file]
phpunit/MessageBodyTest.php [deleted file]
phpunit/ParamsTest.php [deleted file]
phpunit/QueryStringTest.php [deleted file]
phpunit/UrlTest.php [deleted file]
tests/bug66388.phpt
tests/client002.phpt
tests/client003.phpt
tests/client004.phpt
tests/client005.phpt
tests/client006.phpt
tests/client007.phpt
tests/client008.phpt
tests/client009.phpt
tests/client010.phpt
tests/client011.phpt
tests/client012.phpt
tests/client013.phpt
tests/client014.phpt [new file with mode: 0644]
tests/clientresponse001.phpt
tests/clientresponse002.phpt
tests/clientresponse003.phpt
tests/cookie001.phpt [new file with mode: 0644]
tests/cookie002.phpt [new file with mode: 0644]
tests/cookie003.phpt [new file with mode: 0644]
tests/cookie004.phpt [new file with mode: 0644]
tests/cookie005.phpt [new file with mode: 0644]
tests/cookie006.phpt [new file with mode: 0644]
tests/cookie007.phpt [new file with mode: 0644]
tests/cookie008.phpt [new file with mode: 0644]
tests/cookie009.phpt [new file with mode: 0644]
tests/cookie010.phpt [new file with mode: 0644]
tests/cookie011.phpt [new file with mode: 0644]
tests/cookie012.phpt [new file with mode: 0644]
tests/encstream001.phpt [new file with mode: 0644]
tests/encstream002.phpt [new file with mode: 0644]
tests/encstream003.phpt [new file with mode: 0644]
tests/encstream004.phpt [new file with mode: 0644]
tests/encstream005.phpt [new file with mode: 0644]
tests/encstream006.phpt [new file with mode: 0644]
tests/encstream007.phpt [new file with mode: 0644]
tests/encstream008.phpt [new file with mode: 0644]
tests/encstream009.phpt [new file with mode: 0644]
tests/envresponse003.phpt
tests/envresponse004.phpt
tests/envresponse016.phpt [new file with mode: 0644]
tests/envresponseheader001.phpt
tests/envresponseranges001.phpt
tests/etag001.phpt
tests/message003.phpt
tests/message004.phpt
tests/messagebody001.phpt [new file with mode: 0644]
tests/messagebody002.phpt [new file with mode: 0644]
tests/messagebody003.phpt [new file with mode: 0644]
tests/messagebody004.phpt [new file with mode: 0644]
tests/messagebody005.phpt [new file with mode: 0644]
tests/messagebody006.phpt [new file with mode: 0644]
tests/messagebody007.phpt [new file with mode: 0644]
tests/messagebody008.phpt [new file with mode: 0644]
tests/messagebody009.phpt [new file with mode: 0644]
tests/messagebody010.phpt [new file with mode: 0644]
tests/params001.phpt
tests/params003.phpt [new file with mode: 0644]
tests/params004.phpt [new file with mode: 0644]
tests/params005.phpt [new file with mode: 0644]
tests/params006.phpt [new file with mode: 0644]
tests/params007.phpt [new file with mode: 0644]
tests/params008.phpt [new file with mode: 0644]
tests/params009.phpt [new file with mode: 0644]
tests/params010.phpt [new file with mode: 0644]
tests/params011.phpt [new file with mode: 0644]
tests/params012.phpt [new file with mode: 0644]
tests/params013.phpt [new file with mode: 0644]
tests/params014.phpt [new file with mode: 0644]
tests/params015.phpt [new file with mode: 0644]
tests/phpunit.phpt [deleted file]
tests/propertyproxy001.phpt
tests/querystring001.phpt [new file with mode: 0644]
tests/querystring002.phpt [new file with mode: 0644]
tests/querystring_001.phpt [deleted file]
tests/skipif.inc
tests/url001.phpt
tests/url002.phpt [new file with mode: 0644]
tests/url003.phpt [new file with mode: 0644]
tests/url004.phpt [new file with mode: 0644]
tests/url005.phpt [new file with mode: 0644]

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..a55a7ae
--- /dev/null
@@ -0,0 +1,2 @@
+package.xml            merge=touch
+php_http.h             merge=touch
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..64b23b6
--- /dev/null
@@ -0,0 +1,39 @@
+.cproject
+.deps
+.libs/
+.project
+Makefile
+Makefile.fragments
+Makefile.global
+Makefile.objects
+acinclude.m4
+aclocal.m4
+autom4te.cache/
+build/
+config.guess
+config.h
+config.h.in
+config.log
+config.nice
+config.status
+config.sub
+configure
+configure.in
+http.la
+install-sh
+lcov_data
+libtool
+ltmain.sh
+missing
+mkinstalldirs
+modules/
+pecl_http-*.tgz
+*.lo
+run-tests.php
+tests/*.diff
+tests/*.exp
+tests/*.log
+tests/*.out
+tests/*.php
+tests/*.sh
+lcov_data
diff --git a/TODO b/TODO
index 07bf35a0528947d443bc6705627c09b56e49a4d8..3981099147240132e94898d0351ed67405ad4da8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
 * let http_info.request.url be a php_url
 * let the message body be a simple query string unless files are added
 * php_http_message_serialize reverses the chain twice; remove that
+* CURLOPT_PROXY_HEADER and CURLOPT_HEADEROPT
\ No newline at end of file
diff --git a/check_package-xml.php b/check_package-xml.php
new file mode 100755 (executable)
index 0000000..4000054
--- /dev/null
@@ -0,0 +1,92 @@
+#!/usr/bin/env php
+<?php
+
+ini_set("log_errors", false);
+ini_set("display_errors", true);
+
+if ($argc > 1) {
+       if ($argv[1] === "-") {
+               $file = "php://stdin";
+       } else {
+               $file = $argv[1];
+       }
+} elseif (stdin_is_readable()) {
+       $file = "php://stdin";
+} else {
+       $file = "./package.xml";
+}
+
+if (($xml = simplexml_load_file($file))) {
+       $xml_files = xmllist($xml->contents[0]);
+       $dirs = ["."];
+       while ($dir = array_shift($dirs)) {
+               foreach (dirlist($dir) as $file) {
+                       if (is_gitignored($file)) {
+                               continue;
+                       }
+                       if (!is_dir($file)) {
+                               if (!in_array($file, $xml_files)) {
+                                       echo "Missing file $file\n";
+                               }
+                       } else {
+                               $base = basename($file);
+                               if ($base{0} !== ".") {
+                                       array_push($dirs, $file);
+                               }
+                       }
+               }
+       }
+}
+
+###
+
+function error($fmt) {
+       trigger_error(call_user_func_array("sprintf", func_get_args()));
+}
+
+function stdin_is_readable() {
+       $r = [STDIN]; $w = $e = [];
+       return stream_select($r, $w, $e, 0);
+}
+
+function is_gitignored($file) {
+       static $gitignore;
+       
+       if (!isset($gitignore)) {
+               if (is_readable(".gitignore")) {
+                       $gitignore = explode("\n", `find | git check-ignore --stdin`);
+               } else {
+                       $gitignore = false;
+               }
+       }
+       if ($gitignore) {
+               return in_array($file, $gitignore);
+       }
+       return false;
+}
+
+function xmllist(SimpleXmlElement $dir, $p = ".", &$a = null) {
+       settype($a, "array");
+       $p = trim($p, "/") . "/" . trim($dir["name"], "/") . "/";
+       foreach ($dir as $file) {
+               switch ($file->getName()) {
+                       case "dir":
+                               xmllist($file, $p, $a);
+                               break;
+                       case "file":
+                               $a[] = sprintf("%s/%s", trim($p, "/"), trim($file["name"]));
+                               break;
+                       default:
+                               error("Unknown content type: %s", $file->getName());
+                               break;
+               }
+       }
+       return $a;
+}
+
+function dirlist($dir, $p = null) {
+       $p = implode("/", array_filter([trim($p, "/"), trim($dir, "/")]));
+       foreach (scandir($p) as $file) {
+               yield $p."/".$file;
+       }
+}
index a5ede93f7ba36990cf0bf5fe2420a75b3156176d..ba1b93511b551885c801bcead58a0503532346d1 100644 (file)
@@ -187,13 +187,13 @@ dnl ----
                        save_LIBS="$LIBS"
                        LIBS=
                        save_CFLAGS="$CFLAGS"
-                       CFLAGS=`$CURL_CONFIG --cflags`
+                       CFLAGS="$CFLAGS `$CURL_CONFIG --cflags`"
                        save_LDFLAGS="$LDFLAGS"
-                       LDFLAGS=`$CURL_CONFIG --libs`
-                       LDFLAGS="$LDFLAGS $ld_runpath_switch$CURL_DIR/$PHP_LIBDIR"
+                       LDFLAGS="$LDFLAGS `$CURL_CONFIG --libs` $ld_runpath_switch$CURL_DIR/$PHP_LIBDIR"
                
                        AC_MSG_CHECKING([for SSL support in libcurl])
                        CURL_SSL=`$CURL_CONFIG --feature | $EGREP SSL`
+                       CURL_SSL_LIBS=()
                        if test "$CURL_SSL" = "SSL"; then
                                AC_MSG_RESULT([yes])
                                AC_DEFINE([PHP_HTTP_HAVE_SSL], [1], [ ])
@@ -212,9 +212,11 @@ dnl ----
                                        }
                                ], [
                                        AC_MSG_RESULT([yes])
-                                       AC_CHECK_HEADER([openssl/crypto.h], [
-                                               AC_DEFINE([PHP_HTTP_HAVE_OPENSSL], [1], [ ])
-                                               CURL_SSL="crypto"
+                                       AC_CHECK_HEADER([openssl/ssl.h], [
+                                               AC_CHECK_HEADER([openssl/crypto.h], [
+                                                       AC_DEFINE([PHP_HTTP_HAVE_OPENSSL], [1], [ ])
+                                                       CURL_SSL_LIBS=(ssl crypto)
+                                               ])
                                        ])
                                ], [
                                        AC_MSG_RESULT([no])
@@ -236,9 +238,11 @@ dnl ----
                                        }
                                ], [
                                        AC_MSG_RESULT([yes])
-                                       AC_CHECK_HEADER([gcrypt.h], [
-                                               AC_DEFINE([PHP_HTTP_HAVE_GNUTLS], [1], [ ])
-                                               CURL_SSL="gcrypt"
+                                       AC_CHECK_HEADER([gnutls.h], [
+                                               AC_CHECK_HEADER([gcrypt.h], [
+                                                       AC_DEFINE([PHP_HTTP_HAVE_GNUTLS], [1], [ ])
+                                                       CURL_SSL_LIBS=(gnutls gcrypt)
+                                               ])
                                        ])
                                ], [
                                        AC_MSG_RESULT([no])
@@ -248,17 +252,40 @@ dnl ----
                        else
                                AC_MSG_RESULT([no])
                        fi
+                       
+                       AC_MSG_CHECKING([for ares support in libcurl])
+                       AC_TRY_RUN([
+                               #include <curl/curl.h>
+                               int main(int argc, char *argv[]) {
+                                       curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
+                                       if (data && data->ares && data->ares_num0) {
+                                               return 0;
+                                       }
+                                       return 1;
+                               }
+                       ], [
+                               AC_MSG_RESULT([yes])
+                               AC_DEFINE([PHP_HTTP_HAVE_ARES], [1], [ ])
+                       ], [
+                               AC_MSG_RESULT([no])
+                       ], [
+                               AC_MSG_RESULT([no])
+                       ])
                
                        INCLUDES="$save_INCLUDES"
                        LIBS="$save_LIBS"
                        CFLAGS="$save_CFLAGS"
                        LDFLAGS="$save_LDFLAGS"
-               
+                       
+                       for CURL_SSL_LIB in "${CURL_SSL_LIBS[[@]]}"; do
+                               PHP_ADD_LIBRARY_WITH_PATH([$CURL_SSL_LIB], $CURL_DIR/$PHP_LIBDIR, PHP_HTTP_SHARED_LIBADD)
+                       done
+                       
                        dnl end compile tests
                
                        AC_MSG_CHECKING([for bundled SSL CA info])
                        CURL_CAINFO=
-                       for i in `$CURL_CONFIG --ca` "/etc/ssl/certs/ca-certificates.crt"; do
+                       for i in `$CURL_CONFIG --ca` "/etc/ssl/certs/ca-certificates.crt" "/etc/ssl/certs/ca-bundle.crt"; do
                                if test -f "$i"; then
                                        CURL_CAINFO="$i"
                                        break
@@ -274,9 +301,6 @@ dnl ----
                        PHP_ADD_INCLUDE($CURL_DIR/include)
                        PHP_ADD_LIBRARY_WITH_PATH(curl, $CURL_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
                        PHP_EVAL_LIBLINE(`$CURL_CONFIG --libs`, HTTP_SHARED_LIBADD)
-                       if test "x$CURL_SSL" != "x"; then
-                               PHP_ADD_LIBRARY_WITH_PATH([$CURL_SSL], $CURL_DIR/$PHP_LIBDIR, PHP_HTTP_SHARED_LIBADD)
-                       fi
                        AC_DEFINE([PHP_HTTP_HAVE_CURL], [1], [Have libcurl support])
                        HTTP_HAVE_A_REQUEST_LIB=true
                fi
@@ -307,7 +331,7 @@ dnl ----
                        AC_MSG_CHECKING([for libevent version, roughly])
                        
                        if test -f "$EVENT_DIR/include/event2/event.h"; then
-                               EVENT_VER="`$EGREP _EVENT_VERSION $EVENT_DIR/include/event2/event-config.h | $AWK '{print $3}'`"
+                               EVENT_VER="`$AWK '/_EVENT_VERSION/ {gsub(/\"/,\"\",$3); print $3}' < $EVENT_DIR/include/event2/event-config.h`"
                                AC_DEFINE([PHP_HTTP_HAVE_EVENT2], [1], [ ])
                        else
                                AC_DEFINE([PHP_HTTP_HAVE_EVENT2], [0], [ ])
@@ -354,6 +378,8 @@ dnl ----
                        AC_DEFINE([PHP_HTTP_HAVE_PHP_RAPHF_H], [1], [Have ext/raphf support])
                        PHP_ADD_INCLUDE([$HTTP_EXT_RAPHF_INCDIR])
                fi
+       ], [
+               AC_MSG_ERROR([Please install pecl/raphf])
        ])
 
 dnl ----
@@ -380,6 +406,8 @@ dnl ----
                        AC_DEFINE([PHP_HTTP_HAVE_PHP_PROPRO_H], [1], [Have ext/propro support])
                        PHP_ADD_INCLUDE([$HTTP_EXT_PROPRO_INCDIR])
                fi
+       ], [
+               AC_MSG_ERROR([Please install pecl/propro])
        ])
 
 PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared],
index fea14bbfb9aeed7cbbb8a789b7ec8ee495f11702..0e8dfa1272da5553a3c6267e0c594dee6d991767 100644 (file)
@@ -40,7 +40,7 @@ $ifdefs = array(
     'LOCAL_IP' => 'PHP_HTTP_CURL_VERSION(7,21,0)',
 );
 $exclude = array(
-    'PRIVATE', 'LASTSOCKET', 'FTP_ENTRY_PATH', 'CERTINFO',
+    'PRIVATE', 'LASTSOCKET', 'FTP_ENTRY_PATH', 'CERTINFO', 'TLS_SESSION',
     'RTSP_SESSION_ID', 'RTSP_CLIENT_CSEQ', 'RTSP_SERVER_CSEQ', 'RTSP_CSEQ_RECV'
 );
 
@@ -91,8 +91,8 @@ foreach ($infos as $info) {
        if (isset($ifdefs[$short])) printf("#endif\n");
 }
 
-file_put_contents("php_http_curl_client.c", 
+file_put_contents("php_http_client_curl.c", 
        preg_replace('/(\/\* BEGIN::CURLINFO \*\/\n).*(\n\s*\/\* END::CURLINFO \*\/)/s', '$1'. ob_get_contents() .'$2',
-               file_get_contents("php_http_curl_client.c")));
+               file_get_contents("php_http_client_curl.c")));
 
 ?>
index 9113135031a545fca900d32683f61da623c680b4..33d50e662bb09b11f7a760f3ee1dff4ab33e6acf 100644 (file)
@@ -37,19 +37,27 @@ v2: http://dev.iworks.at/ext-http/lcov/ext/http/
   <email>mike@php.net</email>
   <active>yes</active>
  </lead>
- <date>2014-01-02</date>
+ <date>2014-08-01</date>
  <version>
-  <release>2.0.4</release>
-  <api>2.0.0</api>
+  <release>2.1.0RC1</release>
+  <api>2.1.0</api>
  </version>
  <stability>
-  <release>stable</release>
+  <release>beta</release>
   <api>stable</api>
  </stability>
  <license>BSD, revised</license>
  <notes><![CDATA[
-* Removed the pecl/event conflict
-* Fixed bug #66388 (Crash on POST with Content-Length:0 and untouched body)
+* Fixed bug #67733 (Compile error with libevent 2.x)
++ Added RFC5987 support in http\Params
++ Improved synthetic HTTP message parsing performace for ~20%
++ Added request options if libcurl has builtin c-ares support:
+  dns_interface, dns_local_ip4, dns_local_ip6 (all libcurl >= 7.33.0)
++ Added request options:
+  expect_100_timeout (libcurl >= 7.36.0)
+  tcp_nodelay
++ Added transfer info:
+  tls_session (libcurl >= 7.34.0), only available during transfer
 ]]></notes>
  <contents>
   <dir name="/">
@@ -149,6 +157,7 @@ v2: http://dev.iworks.at/ext-http/lcov/ext/http/
      <file role="test" name="client011.phpt"/>
      <file role="test" name="client012.phpt"/>
      <file role="test" name="client013.phpt"/>
+     <file role="test" name="client014.phpt"/>
      <file role="test" name="clientrequest001.phpt"/>
      <file role="test" name="clientrequest002.phpt"/>
      <file role="test" name="clientrequest003.phpt"/>
@@ -156,6 +165,27 @@ v2: http://dev.iworks.at/ext-http/lcov/ext/http/
      <file role="test" name="clientresponse001.phpt"/>
      <file role="test" name="clientresponse002.phpt"/>
      <file role="test" name="clientresponse003.phpt"/>
+     <file role="test" name="cookie001.phpt"/>
+     <file role="test" name="cookie002.phpt"/>
+     <file role="test" name="cookie003.phpt"/>
+     <file role="test" name="cookie004.phpt"/>
+     <file role="test" name="cookie005.phpt"/>
+     <file role="test" name="cookie006.phpt"/>
+     <file role="test" name="cookie007.phpt"/>
+     <file role="test" name="cookie008.phpt"/>
+     <file role="test" name="cookie009.phpt"/>
+     <file role="test" name="cookie010.phpt"/>
+     <file role="test" name="cookie011.phpt"/>
+     <file role="test" name="cookie012.phpt"/>
+     <file role="test" name="encstream001.phpt"/>
+     <file role="test" name="encstream002.phpt"/>
+     <file role="test" name="encstream003.phpt"/>
+     <file role="test" name="encstream004.phpt"/>
+     <file role="test" name="encstream005.phpt"/>
+     <file role="test" name="encstream006.phpt"/>
+     <file role="test" name="encstream007.phpt"/>
+     <file role="test" name="encstream008.phpt"/>
+     <file role="test" name="encstream009.phpt"/>
      <file role="test" name="envrequestbody001.phpt"/>
      <file role="test" name="envrequestbody002.phpt"/>
      <file role="test" name="envrequestbody003.phpt"/>
@@ -181,6 +211,7 @@ v2: http://dev.iworks.at/ext-http/lcov/ext/http/
      <file role="test" name="envresponse013.phpt"/>
      <file role="test" name="envresponse014.phpt"/>
      <file role="test" name="envresponse015.phpt"/>
+     <file role="test" name="envresponse016.phpt"/>
      <file role="test" name="envresponsebody001.phpt"/>
      <file role="test" name="envresponsebody002.phpt"/>
      <file role="test" name="envresponsecodes.phpt"/>
@@ -215,24 +246,43 @@ v2: http://dev.iworks.at/ext-http/lcov/ext/http/
      <file role="test" name="message013.phpt"/>
      <file role="test" name="message014.phpt"/>
      <file role="test" name="message015.phpt"/>
+     <file role="test" name="messagebody001.phpt"/>
+     <file role="test" name="messagebody002.phpt"/>
+     <file role="test" name="messagebody003.phpt"/>
+     <file role="test" name="messagebody004.phpt"/>
+     <file role="test" name="messagebody005.phpt"/>
+     <file role="test" name="messagebody006.phpt"/>
+     <file role="test" name="messagebody007.phpt"/>
+     <file role="test" name="messagebody008.phpt"/>
+     <file role="test" name="messagebody009.phpt"/>
+     <file role="test" name="messagebody010.phpt"/>
      <file role="test" name="negotiate001.phpt"/>
      <file role="test" name="params001.phpt"/>
      <file role="test" name="params002.phpt"/>
-     <file role="test" name="phpunit.phpt"/>
+     <file role="test" name="params003.phpt"/>
+     <file role="test" name="params004.phpt"/>
+     <file role="test" name="params005.phpt"/>
+     <file role="test" name="params006.phpt"/>
+     <file role="test" name="params007.phpt"/>
+     <file role="test" name="params008.phpt"/>
+     <file role="test" name="params009.phpt"/>
+     <file role="test" name="params010.phpt"/>
+     <file role="test" name="params011.phpt"/>
+     <file role="test" name="params012.phpt"/>
+     <file role="test" name="params013.phpt"/>
+     <file role="test" name="params014.phpt"/>
+     <file role="test" name="params015.phpt"/>
      <file role="test" name="propertyproxy001.phpt"/>
-     <file role="test" name="querystring_001.phpt"/>
+     <file role="test" name="querystring001.phpt"/>
+     <file role="test" name="querystring002.phpt"/>
      <file role="test" name="serialize001.phpt"/>
+     <file role="test" name="url002.phpt"/>
+     <file role="test" name="url003.phpt"/>
+     <file role="test" name="url004.phpt"/>
+     <file role="test" name="url005.phpt"/>
      <file role="test" name="url001.phpt"/>
      <file role="test" name="version001.phpt"/>
    </dir>
-   <dir name="phpunit">
-    <file role="test" name="CookieTest.php"/>
-    <file role="test" name="EncodingTest.php"/>
-    <file role="test" name="MessageBodyTest.php"/>
-    <file role="test" name="ParamsTest.php"/>
-    <file role="test" name="QueryStringTest.php"/>
-    <file role="test" name="UrlTest.php"/>
-   </dir>
   </dir>
  </contents>
  <dependencies>
index 0d2613922b0e1005f4548bae12fd844c20a5138c..72670089e143978455d034e0d8f5ce931bbe060a 100644 (file)
@@ -13,7 +13,7 @@
 #ifndef PHP_EXT_HTTP_H
 #define PHP_EXT_HTTP_H
 
-#define PHP_PECL_HTTP_VERSION "2.0.4"
+#define PHP_PECL_HTTP_VERSION "2.1.0RC1"
 
 extern zend_module_entry http_module_entry;
 #define phpext_http_ptr &http_module_entry
index 1a4fdc4a0e3dcadd60d3541f0ca5b2ad001058f4..8ccee0847584b0e4f678596105ccfee8a5915251 100644 (file)
@@ -103,7 +103,7 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_shrink(php_http_buffer_t *buf)
 
 PHP_HTTP_BUFFER_API size_t php_http_buffer_append(php_http_buffer_t *buf, const char *append, size_t append_len)
 {
-       if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, append_len)) {
+       if (buf->free < append_len && PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize(buf, append_len)) {
                return PHP_HTTP_BUFFER_NOMEM;
        }
        memcpy(buf->data + buf->used, append, append_len);
@@ -160,7 +160,7 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_cut(php_http_buffer_t *buf, size_t of
 
 PHP_HTTP_BUFFER_API php_http_buffer_t *php_http_buffer_fix(php_http_buffer_t *buf)
 {
-       if (PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize_ex(buf, 1, 1, 0)) {
+       if (buf->free < 1 && PHP_HTTP_BUFFER_NOMEM == php_http_buffer_resize_ex(buf, 1, 1, 0)) {
                return NULL;
        }
        buf->data[buf->used] = '\0';
@@ -222,13 +222,17 @@ PHP_HTTP_BUFFER_API size_t php_http_buffer_chunk_buffer(php_http_buffer_t **s, c
        return 0;
 }
 
-PHP_HTTP_BUFFER_API void php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_len, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC)
+PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_len, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC)
 {
        char *chunk = NULL;
-       size_t got = 0;
+       size_t passed = 0, got = 0;
 
        while ((got = php_http_buffer_chunk_buffer(s, data, data_len, &chunk, chunk_len))) {
-               passout(opaque, chunk, got TSRMLS_CC);
+               if (PHP_HTTP_BUFFER_PASS0 == passout(opaque, chunk, got TSRMLS_CC)) {
+                       STR_SET(chunk, NULL);
+                       return PHP_HTTP_BUFFER_PASS0;
+               }
+               ++passed;
                if (!chunk_len) {
                        /*      we already got the last chunk,
                                and freed all resources */
@@ -239,6 +243,7 @@ PHP_HTTP_BUFFER_API void php_http_buffer_chunked_output(php_http_buffer_t **s, c
                STR_SET(chunk, NULL);
        }
        STR_FREE(chunk);
+       return passed;
 }
 
 PHP_HTTP_BUFFER_API ssize_t php_http_buffer_passthru(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *passin_arg, php_http_buffer_pass_func_t passon, void *passon_arg TSRMLS_DC)
index bc2a7f2d351365eca9a70fcd2feb2f453bac5e66..cf9b45863b7af0f2752680be22a9c21b51257bf3 100644 (file)
@@ -191,7 +191,7 @@ typedef size_t (*php_http_buffer_pass_func_t)(void *opaque, char *, size_t TSRML
 PHP_HTTP_BUFFER_API ssize_t php_http_buffer_passthru(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *passin_arg, php_http_buffer_pass_func_t passon, void *passon_arg TSRMLS_DC);
 
 /* wrapper around php_http_buffer_chunk_buffer, which passes available chunks to passthru() */
-PHP_HTTP_BUFFER_API void php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_size, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC);
+PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_output(php_http_buffer_t **s, const char *data, size_t data_len, size_t chunk_size, php_http_buffer_pass_func_t passout, void *opaque TSRMLS_DC);
 
 /* write chunks directly into php_http_buffer_t buffer */
 PHP_HTTP_BUFFER_API size_t php_http_buffer_chunked_input(php_http_buffer_t **s, size_t chunk_size, php_http_buffer_pass_func_t passin, void *opaque TSRMLS_DC);
index b2bd7f8c023f4e02261b01eedff1e178e74fb2c8..f96164bbba08ad449733b745503149948412de03 100644 (file)
@@ -377,6 +377,7 @@ static void handle_history(zval *zclient, php_http_message_t *request, php_http_
 
 static STATUS handle_response(void *arg, php_http_client_t *client, php_http_client_enqueue_t *e, php_http_message_t **request, php_http_message_t **response)
 {
+       zend_bool dequeue = 0;
        zval zclient;
        php_http_message_t *msg;
        php_http_client_progress_state_t *progress;
@@ -390,7 +391,10 @@ static STATUS handle_response(void *arg, php_http_client_t *client, php_http_cli
                zval *info, *zresponse, *zrequest;
                HashTable *info_ht;
 
-               if (i_zend_is_true(zend_read_property(php_http_client_class_entry, &zclient, ZEND_STRL("recordHistory"), 0 TSRMLS_CC))) {
+               /* ensure the message is of type response (could be uninitialized in case of early error, like DNS) */
+               php_http_message_set_type(msg, PHP_HTTP_RESPONSE);
+
+               if (z_is_true(zend_read_property(php_http_client_class_entry, &zclient, ZEND_STRL("recordHistory"), 0 TSRMLS_CC))) {
                        handle_history(&zclient, *request, *response TSRMLS_CC);
                }
 
@@ -427,8 +431,8 @@ static STATUS handle_response(void *arg, php_http_client_t *client, php_http_cli
                        zend_fcall_info_argn(&e->closure.fci TSRMLS_CC, 0);
 
                        if (retval) {
-                               if (Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval)) {
-                                       php_http_client_dequeue(client, e->request);
+                               if (Z_TYPE_P(retval) == IS_BOOL) {
+                                       dequeue = Z_BVAL_P(retval);
                                }
                                zval_ptr_dtor(&retval);
                        }
@@ -444,6 +448,10 @@ static STATUS handle_response(void *arg, php_http_client_t *client, php_http_cli
                client->callback.progress.func(client->callback.progress.arg, client, e, progress);
        }
 
+       if (dequeue) {
+               php_http_client_dequeue(client, e->request);
+       }
+
        return SUCCESS;
 }
 
@@ -720,7 +728,9 @@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_count, 0, 0, 0)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(HttpClient, count)
 {
-       if (SUCCESS == zend_parse_parameters_none()) {
+       long count_mode = -1;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &count_mode)) {
                php_http_client_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
                RETVAL_LONG(zend_llist_count(&obj->client->requests));
index 4033b9f56c5c0c61a36b19ae4475d5e9edb50f19..15d26192cedfdc27dbeff17d8ec7ab23a3e5c7d2 100644 (file)
 #      endif
 #endif
 
+#ifdef PHP_HTTP_HAVE_OPENSSL
+#      include <openssl/ssl.h>
+#endif
+#ifdef PHP_HTTP_HAVE_GNUTLS
+#      include <gnutls.h>
+#endif
+
 typedef struct php_http_client_curl {
        CURLM *handle;
 
@@ -187,7 +194,11 @@ static size_t php_http_curle_read_callback(void *data, size_t len, size_t n, voi
        return 0;
 }
 
+#if PHP_HTTP_CURL_VERSION(7,32,0)
+static int php_http_curle_xferinfo_callback(void *ctx, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
+#else
 static int php_http_curle_progress_callback(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow)
+#endif
 {
        php_http_client_curl_handler_t *h = ctx;
        zend_bool update = 0;
@@ -258,6 +269,8 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data,
                                h->progress.info = "blacklist check";
                        } else if (php_memnstr(data, ZEND_STRL("SSL"), data + length)) {
                                h->progress.info = "ssl negotiation";
+                       } else if (php_memnstr(data, ZEND_STRL("upload"), data + length)) {
+                               h->progress.info = "uploaded";
                        } else if (php_memnstr(data, ZEND_STRL("left intact"), data + length)) {
                                h->progress.info = "not disconnected";
                        } else if (php_memnstr(data, ZEND_STRL("closed"), data + length)) {
@@ -269,6 +282,7 @@ static int php_http_curle_raw_callback(CURL *ch, curl_infotype type, char *data,
                        } else {
 #if PHP_DEBUG
                                h->progress.info = data;
+                               data[length - 1] = '\0';
 #endif
                        }
                        if (h->client->callback.progress.func) {
@@ -471,6 +485,87 @@ static STATUS php_http_curle_get_info(CURL *ch, HashTable *info)
 
        /* END::CURLINFO */
 
+#if PHP_HTTP_CURL_VERSION(7,34,0)
+       {
+               int i;
+               zval *ti_array;
+               struct curl_tlssessioninfo *ti;
+
+               if (CURLE_OK == curl_easy_getinfo(ch, CURLINFO_TLS_SESSION, &ti)) {
+                       const char *backend;
+
+                       MAKE_STD_ZVAL(subarray);
+                       ZVAL_NULL(subarray);
+                       MAKE_STD_ZVAL(ti_array);
+                       array_init(ti_array);
+
+                       switch (ti->backend) {
+                       case CURLSSLBACKEND_NONE:
+                               backend = "none";
+                               break;
+                       case CURLSSLBACKEND_OPENSSL:
+                               backend = "openssl";
+#ifdef PHP_HTTP_HAVE_OPENSSL
+                               {
+                                       SSL_CTX *ctx = ti->internals;
+
+                                       array_init(subarray);
+                                       add_assoc_long_ex(subarray, ZEND_STRS("number"), SSL_CTX_sess_number(ctx));
+                                       add_assoc_long_ex(subarray, ZEND_STRS("connect"), SSL_CTX_sess_connect(ctx));
+                                       add_assoc_long_ex(subarray, ZEND_STRS("connect_good"), SSL_CTX_sess_connect_good(ctx));
+                                       add_assoc_long_ex(subarray, ZEND_STRS("connect_renegotiate"), SSL_CTX_sess_connect_renegotiate(ctx));
+                                       add_assoc_long_ex(subarray, ZEND_STRS("hits"), SSL_CTX_sess_hits(ctx));
+                                       add_assoc_long_ex(subarray, ZEND_STRS("cache_full"), SSL_CTX_sess_cache_full(ctx));
+                               }
+#endif
+                               break;
+                       case CURLSSLBACKEND_GNUTLS:
+                               backend = "gnutls";
+#ifdef PHP_HTTP_HAVE_GNUTLS
+                               {
+                                       gnutls_session_t sess = ti->internals;
+                                       char *desc;
+
+                                       array_init(subarray);
+                                       if ((desc = gnutls_session_get_desc(sess))) {
+                                               add_assoc_string_ex(subarray, ZEND_STRS("desc"), desc, 1);
+                                               gnutls_free(desc);
+                                       }
+                                       add_assoc_bool_ex(subarray, ZEND_STRS("resumed"), gnutls_session_is_resumed(sess));
+                               }
+#endif
+                               break;
+                       case CURLSSLBACKEND_NSS:
+                               backend = "nss";
+                               break;
+                       case CURLSSLBACKEND_QSOSSL:
+                               backend = "qsossl";
+                               break;
+                       case CURLSSLBACKEND_GSKIT:
+                               backend = "gskit";
+                               break;
+                       case CURLSSLBACKEND_POLARSSL:
+                               backend = "polarssl";
+                               break;
+                       case CURLSSLBACKEND_CYASSL:
+                               backend = "cyassl";
+                               break;
+                       case CURLSSLBACKEND_SCHANNEL:
+                               backend = "schannel";
+                               break;
+                       case CURLSSLBACKEND_DARWINSSL:
+                               backend = "darwinssl";
+                               break;
+                       default:
+                               backend = "unknown";
+                       }
+                       add_assoc_string_ex(ti_array, ZEND_STRS("backend"), estrdup(backend), 0);
+                       add_assoc_zval_ex(ti_array, ZEND_STRS("internals"), subarray);
+                       add_assoc_zval_ex(&array, "tls_session", sizeof("tls_session"), ti_array);
+               }
+       }
+#endif
+
 #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
        {
                int i;
@@ -701,9 +796,9 @@ static void php_http_curlm_timer_callback(CURLM *multi, long timeout_ms, void *t
 
 static php_http_options_t php_http_curle_options;
 
-#define PHP_HTTP_CURLE_OPTION_CHECK_STRLEN     0x0001
-#define PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR    0x0002
-#define PHP_HTTP_CURLE_OPTION_TRANSFORM_MS     0x0004
+#define PHP_HTTP_CURLE_OPTION_CHECK_STRLEN             0x0001
+#define PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR            0x0002
+#define PHP_HTTP_CURLE_OPTION_TRANSFORM_MS             0x0004
 
 static STATUS php_http_curle_option_set_ssl_verifyhost(php_http_option_t *opt, zval *val, void *userdata)
 {
@@ -720,19 +815,20 @@ static STATUS php_http_curle_option_set_cookiestore(php_http_option_t *opt, zval
 {
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
+       php_http_curle_storage_t *storage = php_http_curle_get_storage(curl->handle);
 
-       if (val) {
-               php_http_curle_storage_t *storage = php_http_curle_get_storage(curl->handle);
-
-               if (storage->cookiestore) {
-                       pefree(storage->cookiestore, 1);
-               }
+       if (storage->cookiestore) {
+               pefree(storage->cookiestore, 1);
+       }
+       if (val && Z_STRLEN_P(val)) {
                storage->cookiestore = pestrndup(Z_STRVAL_P(val), Z_STRLEN_P(val), 1);
-               if (    CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEFILE, storage->cookiestore)
-                       ||      CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEJAR, storage->cookiestore)
-               ) {
-                       return FAILURE;
-               }
+       } else {
+               storage->cookiestore = NULL;
+       }
+       if (    CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEFILE, storage->cookiestore)
+               ||      CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIEJAR, storage->cookiestore)
+       ) {
+               return FAILURE;
        }
        return SUCCESS;
 }
@@ -775,6 +871,11 @@ static STATUS php_http_curle_option_set_cookies(php_http_option_t *opt, zval *va
                                }
                        }
                }
+       } else {
+               php_http_buffer_reset(&curl->options.cookies);
+               if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIE, NULL)) {
+                       return FAILURE;
+               }
        }
        return SUCCESS;
 }
@@ -830,13 +931,15 @@ static STATUS php_http_curle_option_set_etag(php_http_option_t *opt, zval *val,
 {
        php_http_client_curl_handler_t *curl = userdata;
        php_http_buffer_t header;
-       zend_bool is_quoted = !((Z_STRVAL_P(val)[0] != '"') || (Z_STRVAL_P(val)[Z_STRLEN_P(val)-1] != '"'));
 
-       php_http_buffer_init(&header);
-       php_http_buffer_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", curl->options.range_request?"If-Match":"If-None-Match", Z_STRVAL_P(val));
-       php_http_buffer_fix(&header);
-       curl->options.headers = curl_slist_append(curl->options.headers, header.data);
-       php_http_buffer_dtor(&header);
+       if (Z_STRLEN_P(val)) {
+               zend_bool is_quoted = !((Z_STRVAL_P(val)[0] != '"') || (Z_STRVAL_P(val)[Z_STRLEN_P(val)-1] != '"'));
+               php_http_buffer_init(&header);
+               php_http_buffer_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", curl->options.range_request?"If-Match":"If-None-Match", Z_STRVAL_P(val));
+               php_http_buffer_fix(&header);
+               curl->options.headers = curl_slist_append(curl->options.headers, header.data);
+               php_http_buffer_dtor(&header);
+       }
        return SUCCESS;
 }
 
@@ -1026,10 +1129,23 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                opt->setter = php_http_curle_option_set_resolve;
        }
 #endif
-#if PHP_HTTP_CURL_VERSION(7,24,0)
+#if PHP_HTTP_HAVE_ARES
+# if PHP_HTTP_CURL_VERSION(7,24,0)
        if ((opt = php_http_option_register(registry, ZEND_STRL("dns_servers"), CURLOPT_DNS_SERVERS, IS_STRING))) {
                opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
        }
+# endif
+# if PHP_HTTP_CURL_VERSION(7,33,0)
+       if ((opt = php_http_option_register(registry, ZEND_STRL("dns_interface"), CURLOPT_DNS_INTERFACE, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+       if ((opt = php_http_option_register(registry, ZEND_STRL("dns_local_ip4"), CURLOPT_DNS_LOCAL_IP4, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+       if ((opt = php_http_option_register(registry, ZEND_STRL("dns_local_ip6"), CURLOPT_DNS_LOCAL_IP6, IS_STRING))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+       }
+# endif
 #endif
 
        /* limits */
@@ -1100,7 +1216,11 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
        /* useragent */
        if ((opt = php_http_option_register(registry, ZEND_STRL("useragent"), CURLOPT_USERAGENT, IS_STRING))) {
                /* don't check strlen, to allow sending no useragent at all */
-               ZVAL_STRING(&opt->defval, "PECL::HTTP/" PHP_PECL_HTTP_VERSION " (PHP/" PHP_VERSION ")", 0);
+               ZVAL_STRING(&opt->defval,
+                               "PECL_HTTP/" PHP_PECL_HTTP_VERSION " "
+                               "PHP/" PHP_VERSION " "
+                               "libcurl/" LIBCURL_VERSION
+                       , 0);
        }
 
        /* resume */
@@ -1160,8 +1280,15 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                opt->flags |= PHP_HTTP_CURLE_OPTION_TRANSFORM_MS;
                Z_DVAL(opt->defval) = 3;
        }
+#if PHP_HTTP_CURL_VERSION(7,36,0)
+       if ((opt = php_http_option_register(registry, ZEND_STRL("expect_100_timeout"), CURLOPT_EXPECT_100_TIMEOUT_MS, IS_DOUBLE))) {
+               opt->flags |= PHP_HTTP_CURLE_OPTION_TRANSFORM_MS;
+               Z_DVAL(opt->defval) = 1;
+       }
+#endif
 
        /* tcp */
+       php_http_option_register(registry, ZEND_STRL("tcp_nodelay"), CURLOPT_TCP_NODELAY, IS_BOOL);
 #if PHP_HTTP_CURL_VERSION(7,25,0)
        php_http_option_register(registry, ZEND_STRL("tcp_keepalive"), CURLOPT_TCP_KEEPALIVE, IS_BOOL);
        if ((opt = php_http_option_register(registry, ZEND_STRL("tcp_keepidle"), CURLOPT_TCP_KEEPIDLE, IS_LONG))) {
@@ -1180,14 +1307,21 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
                }
-               php_http_option_register(registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING);
-
+               if ((opt = php_http_option_register(registry, ZEND_STRL("certtype"), CURLOPT_SSLCERTTYPE, IS_STRING))) {
+                       opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+                       ZVAL_STRING(&opt->defval, "PEM", 1);
+               }
                if ((opt = php_http_option_register(registry, ZEND_STRL("key"), CURLOPT_SSLKEY, IS_STRING))) {
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
                        opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR;
                }
-               php_http_option_register(registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING);
-               php_http_option_register(registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING);
+               if ((opt = php_http_option_register(registry, ZEND_STRL("keytype"), CURLOPT_SSLKEYTYPE, IS_STRING))) {
+                       opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+                       ZVAL_STRING(&opt->defval, "PEM", 1);
+               }
+               if ((opt = php_http_option_register(registry, ZEND_STRL("keypasswd"), CURLOPT_SSLKEYPASSWD, IS_STRING))) {
+                       opt->flags |= PHP_HTTP_CURLE_OPTION_CHECK_STRLEN;
+               }
                php_http_option_register(registry, ZEND_STRL("engine"), CURLOPT_SSLENGINE, IS_STRING);
                php_http_option_register(registry, ZEND_STRL("version"), CURLOPT_SSLVERSION, IS_LONG);
                if ((opt = php_http_option_register(registry, ZEND_STRL("verifypeer"), CURLOPT_SSL_VERIFYPEER, IS_BOOL))) {
@@ -1231,6 +1365,14 @@ static void php_http_curle_options_init(php_http_options_t *registry TSRMLS_DC)
 #endif
 #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
                php_http_option_register(registry, ZEND_STRL("certinfo"), CURLOPT_CERTINFO, IS_BOOL);
+#endif
+#if PHP_HTTP_CURL_VERSION(7,36,0)
+               if ((opt = php_http_option_register(registry, ZEND_STRL("enable_npn"), CURLOPT_SSL_ENABLE_NPN, IS_BOOL))) {
+                       ZVAL_BOOL(&opt->defval, 1);
+               }
+               if ((opt = php_http_option_register(registry, ZEND_STRL("enable_alpn"), CURLOPT_SSL_ENABLE_ALPN, IS_BOOL))) {
+                       ZVAL_BOOL(&opt->defval, 1);
+               }
 #endif
        }
 }
@@ -1252,6 +1394,7 @@ static STATUS php_http_curle_set_option(php_http_option_t *opt, zval *val, void
        php_http_client_curl_handler_t *curl = userdata;
        CURL *ch = curl->handle;
        zval tmp;
+       CURLcode rc = CURLE_OK;
        STATUS rv = SUCCESS;
        TSRMLS_FETCH_FROM_CTX(curl->client->ts);
 
@@ -1277,14 +1420,18 @@ static STATUS php_http_curle_set_option(php_http_option_t *opt, zval *val, void
                break;
 
        case IS_STRING:
-               if (!(opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_STRLEN) || Z_STRLEN_P(val)) {
-                       if (!(opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR) || !Z_STRVAL_P(val) || SUCCESS == php_check_open_basedir(Z_STRVAL_P(val) TSRMLS_CC)) {
-                               if (opt->setter) {
-                                       rv = opt->setter(opt, val, curl);
-                               } else if (CURLE_OK != curl_easy_setopt(ch, opt->option, Z_STRVAL_P(val))) {
-                                       rv = FAILURE;
-                               }
+               if (opt->setter) {
+                       rv = opt->setter(opt, val, curl);
+               } else if ((opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_STRLEN) && !Z_STRLEN_P(val)) {
+                       if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, NULL))) {
+                               rv = FAILURE;
+                       }
+               } else if ((opt->flags & PHP_HTTP_CURLE_OPTION_CHECK_BASEDIR) && Z_STRVAL_P(val) && SUCCESS != php_check_open_basedir(Z_STRVAL_P(val) TSRMLS_CC)) {
+                       if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, NULL))) {
+                               rv = FAILURE;
                        }
+               } else if (CURLE_OK != (rc = curl_easy_setopt(ch, opt->option, Z_STRVAL_P(val)))) {
+                       rv = FAILURE;
                }
                break;
 
@@ -1318,7 +1465,7 @@ static STATUS php_http_curle_set_option(php_http_option_t *opt, zval *val, void
                break;
        }
        if (rv != SUCCESS) {
-               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s", opt->name.s);
+               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Could not set option %s (%s)", opt->name.s, curl_easy_strerror(rc));
        }
        return rv;
 }
@@ -1412,9 +1559,14 @@ static php_http_client_curl_handler_t *php_http_client_curl_handler_init(php_htt
        curl_easy_setopt(handle, CURLOPT_DEBUGFUNCTION, php_http_curle_raw_callback);
        curl_easy_setopt(handle, CURLOPT_READFUNCTION, php_http_curle_read_callback);
        curl_easy_setopt(handle, CURLOPT_IOCTLFUNCTION, php_http_curle_ioctl_callback);
+#if PHP_HTTP_CURL_VERSION(7,32,0)
+       curl_easy_setopt(handle, CURLOPT_XFERINFOFUNCTION, php_http_curle_xferinfo_callback);
+       curl_easy_setopt(handle, CURLOPT_XFERINFODATA, handler);
+#else
        curl_easy_setopt(handle, CURLOPT_PROGRESSFUNCTION, php_http_curle_progress_callback);
-       curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler);
        curl_easy_setopt(handle, CURLOPT_PROGRESSDATA, handler);
+#endif
+       curl_easy_setopt(handle, CURLOPT_DEBUGDATA, handler);
 
        php_http_client_curl_handler_reset(handler);
 
@@ -1492,8 +1644,8 @@ static STATUS php_http_client_curl_handler_prepare(php_http_client_curl_handler_
                        }
                }
                php_http_buffer_dtor(&header);
-               curl_easy_setopt(curl->handle, CURLOPT_HTTPHEADER, curl->options.headers);
        }
+       curl_easy_setopt(curl->handle, CURLOPT_HTTPHEADER, curl->options.headers);
 
        /* attach request body */
        if ((body_size = php_http_message_body_size(msg->body))) {
@@ -1525,7 +1677,11 @@ static void php_http_client_curl_handler_dtor(php_http_client_curl_handler_t *ha
        TSRMLS_FETCH_FROM_CTX(handler->client->ts);
 
        curl_easy_setopt(handler->handle, CURLOPT_NOPROGRESS, 1L);
+#if PHP_HTTP_CURL_VERSION(7,32,0)
+       curl_easy_setopt(handler->handle, CURLOPT_XFERINFOFUNCTION, NULL);
+#else
        curl_easy_setopt(handler->handle, CURLOPT_PROGRESSFUNCTION, NULL);
+#endif
        curl_easy_setopt(handler->handle, CURLOPT_VERBOSE, 0L);
        curl_easy_setopt(handler->handle, CURLOPT_DEBUGFUNCTION, NULL);
 
index b565312fe984cc02c41fab7012ad12b091ba79b1..4bd8d80224606f7464a4470250da56d2eb1c07e1 100644 (file)
@@ -526,7 +526,7 @@ static PHP_METHOD(HttpCookie, setCookies)
 
        zend_hash_clean(&obj->list->cookies);
        if (cookies) {
-               array_copy(cookies, &obj->list->cookies);
+               array_copy_strings(cookies, &obj->list->cookies);
        }
 
        RETVAL_ZVAL(getThis(), 1, 0);
@@ -546,7 +546,7 @@ static PHP_METHOD(HttpCookie, addCookies)
 
        PHP_HTTP_COOKIE_OBJECT_INIT(obj);
 
-       array_join(cookies, &obj->list->cookies, 1, ARRAY_JOIN_STRONLY);
+       array_join(cookies, &obj->list->cookies, 1, ARRAY_JOIN_STRONLY|ARRAY_JOIN_STRINGIFY);
 
        RETVAL_ZVAL(getThis(), 1, 0);
 }
@@ -585,7 +585,7 @@ static PHP_METHOD(HttpCookie, setExtras)
 
        zend_hash_clean(&obj->list->extras);
        if (extras) {
-               array_copy(extras, &obj->list->extras);
+               array_copy_strings(extras, &obj->list->extras);
        }
 
        RETVAL_ZVAL(getThis(), 1, 0);
@@ -605,7 +605,7 @@ static PHP_METHOD(HttpCookie, addExtras)
 
        PHP_HTTP_COOKIE_OBJECT_INIT(obj);
 
-       array_join(extras, &obj->list->extras, 1, ARRAY_JOIN_STRONLY);
+       array_join(extras, &obj->list->extras, 1, ARRAY_JOIN_STRONLY|ARRAY_JOIN_STRINGIFY);
 
        RETVAL_ZVAL(getThis(), 1, 0);
 }
index fdc7b9696a0f80e6736436660e849af70b48a50f..10d54fe4019a5a0472ffc95b1c6bfe1758964279 100644 (file)
@@ -715,6 +715,7 @@ static PHP_METHOD(HttpEnv, getRequestBody)
 
        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, body, NULL TSRMLS_CC)) {
+               php_http_message_body_addref(body);
                RETVAL_OBJVAL(ov, 0);
        }
 }
@@ -957,26 +958,29 @@ static SAPI_POST_HANDLER_FUNC(php_http_json_post_handler)
        size_t json_len = 0;
 
 #if PHP_VERSION_ID >= 50600
-       php_http_message_body_to_string(php_http_env_get_request_body(TSRMLS_C),
-                       &json_str, &json_len, 0, -1);
+       if (SG(request_info).request_body) {
+               /* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
+               php_stream_rewind(SG(request_info).request_body);
+               json_len = php_stream_copy_to_mem(SG(request_info).request_body, &json_str, PHP_STREAM_COPY_ALL, 0);
+       }
 #else
        json_str = SG(request_info).raw_post_data;
        json_len = SG(request_info).raw_post_data_length;
 #endif
 
        if (json_len) {
-               zval_dtor(zarg);
-               ZVAL_NULL(zarg);
-               php_json_decode(zarg, json_str, json_len, 1, PG(max_input_nesting_level) TSRMLS_CC);
+               zval zjson;
+
+               INIT_ZVAL(zjson);
+               php_json_decode(&zjson, json_str, json_len, 1, PG(max_input_nesting_level) TSRMLS_CC);
+               if (Z_TYPE(zjson) != IS_NULL) {
+                       zval_dtor(zarg);
+                       ZVAL_COPY_VALUE(zarg, (&zjson));
+               }
        }
 #if PHP_VERSION_ID >= 50600
        STR_FREE(json_str);
 #endif
-
-       /* always let $_POST be array() */
-       if (Z_TYPE_P(zarg) == IS_NULL) {
-               array_init(zarg);
-       }
 }
 
 static void php_http_env_register_json_handler(TSRMLS_D)
index f2b8bf20fe36bec862cb4d531cdece047d69f9fd..6aff0c00fe0d106fba418841e061efc02bb7778d 100644 (file)
@@ -96,7 +96,11 @@ static int grab_files(void *zpp TSRMLS_DC, int argc, va_list argv, zend_hash_key
                                add_assoc_zval_ex(cpy, ZEND_STRS("file"), *tmp);
                                zend_hash_del_key_or_index(Z_ARRVAL_P(cpy), ZEND_STRS("tmp_name"), 0, HASH_DEL_KEY);
                        }
-                       zend_hash_quick_update(Z_ARRVAL_P(zfiles), key->arKey, key->nKeyLength, key->h, (void *) &cpy, sizeof(zval *), NULL);
+                       if (key->nKeyLength > 0) {
+                               zend_hash_quick_update(Z_ARRVAL_P(zfiles), key->arKey, key->nKeyLength, key->h, (void *) &cpy, sizeof(zval *), NULL);
+                       } else {
+                               zend_hash_index_update(Z_ARRVAL_P(zfiles), key->h, (void *) &cpy, sizeof(zval *), NULL);
+                       }
                }
        }
 
index 275b91b2280a56996321398fccea1c08775b7e6b..4d6ef037471fb9bb02faf0a32f2773e052a631e1 100644 (file)
@@ -217,7 +217,9 @@ static size_t output(void *context, char *buf, size_t len TSRMLS_DC)
 {
        php_http_env_response_t *r = context;
 
-       r->ops->write(r, buf, len);
+       if (SUCCESS != r->ops->write(r, buf, len)) {
+               return (size_t) -1;
+       }
 
        /*      we really only need to flush when throttling is enabled,
                because we push the data as fast as possible anyway if not */
@@ -231,7 +233,7 @@ static size_t output(void *context, char *buf, size_t len TSRMLS_DC)
 #define php_http_env_response_send_done(r) php_http_env_response_send_data((r), NULL, 0)
 static STATUS php_http_env_response_send_data(php_http_env_response_t *r, const char *buf, size_t len)
 {
-       size_t chunk = r->throttle.chunk ? r->throttle.chunk : PHP_HTTP_SENDBUF_SIZE;
+       size_t chunks_sent, chunk = r->throttle.chunk ? r->throttle.chunk : PHP_HTTP_SENDBUF_SIZE;
        TSRMLS_FETCH_FROM_CTX(r->ts);
 
        if (r->content.encoder) {
@@ -248,15 +250,16 @@ static STATUS php_http_env_response_send_data(php_http_env_response_t *r, const
                        }
                }
 
-               if (enc_str) {
-                       php_http_buffer_chunked_output(&r->buffer, enc_str, enc_len, buf ? chunk : 0, output, r TSRMLS_CC);
-                       STR_FREE(enc_str);
+               if (!enc_str) {
+                       return SUCCESS;
                }
+               chunks_sent = php_http_buffer_chunked_output(&r->buffer, enc_str, enc_len, buf ? chunk : 0, output, r TSRMLS_CC);
+               STR_FREE(enc_str);
        } else {
-               php_http_buffer_chunked_output(&r->buffer, buf, len, buf ? chunk : 0, output, r TSRMLS_CC);
+               chunks_sent = php_http_buffer_chunked_output(&r->buffer, buf, len, buf ? chunk : 0, output, r TSRMLS_CC);
        }
 
-       return SUCCESS;
+       return chunks_sent != (size_t) -1 ? SUCCESS : FAILURE;
 }
 
 php_http_env_response_t *php_http_env_response_init(php_http_env_response_t *r, zval *options, php_http_env_response_ops_t *ops, void *init_arg TSRMLS_DC)
@@ -996,7 +999,9 @@ static STATUS php_http_env_response_stream_write(php_http_env_response_t *r, con
                }
        }
 
-       php_stream_write(stream_ctx->stream, data_str, data_len);
+       if (data_len != php_stream_write(stream_ctx->stream, data_str, data_len)) {
+               return FAILURE;
+       }
 
        return SUCCESS;
 }
index cfcb5b131457667eb0224461a896edb1297200c7..f560a8561a5917f241500b1c53a647f28e60a66e 100644 (file)
@@ -44,10 +44,13 @@ php_http_header_parser_state_t php_http_header_parser_state_push(php_http_header
        unsigned i;
        php_http_header_parser_state_t state = 0;
 
+       /* short circuit */
+       ZEND_PTR_STACK_RESIZE_IF_NEEDED((&parser->stack), argc);
+
        va_start(va_args, argc);
        for (i = 0; i < argc; ++i) {
                state = va_arg(va_args, php_http_header_parser_state_t);
-               zend_stack_push(&parser->stack, &state, sizeof(state));
+               zend_ptr_stack_push(&parser->stack, (void *) state);
        }
        va_end(va_args);
 
@@ -56,28 +59,27 @@ php_http_header_parser_state_t php_http_header_parser_state_push(php_http_header
 
 php_http_header_parser_state_t php_http_header_parser_state_is(php_http_header_parser_t *parser)
 {
-       php_http_header_parser_state_t *state;
+       php_http_header_parser_state_t state;
 
-       if (SUCCESS == zend_stack_top(&parser->stack, (void *) &state)) {
-               return *state;
+       if (parser->stack.top) {
+               return (php_http_header_parser_state_t) zend_ptr_stack_top(&parser->stack);
        }
+
        return PHP_HTTP_HEADER_PARSER_STATE_START;
 }
 
 php_http_header_parser_state_t php_http_header_parser_state_pop(php_http_header_parser_t *parser)
 {
-       php_http_header_parser_state_t state, *state_ptr;
-       if (SUCCESS == zend_stack_top(&parser->stack, (void *) &state_ptr)) {
-               state = *state_ptr;
-               zend_stack_del_top(&parser->stack);
-               return state;
+       if (parser->stack.top) {
+               return (php_http_header_parser_state_t) zend_ptr_stack_pop(&parser->stack);
        }
+
        return PHP_HTTP_HEADER_PARSER_STATE_START;
 }
 
 void php_http_header_parser_dtor(php_http_header_parser_t *parser)
 {
-       zend_stack_destroy(&parser->stack);
+       zend_ptr_stack_destroy(&parser->stack);
        php_http_info_dtor(&parser->info);
        STR_FREE(parser->_key.str);
        STR_FREE(parser->_val.str);
index d8ac43c8ff69d017fd64ac6ee285d8c1dd46edb2..4c60f6ef634b4b262eb9228855588816b19419d2 100644 (file)
@@ -28,7 +28,7 @@ typedef enum php_http_header_parser_state {
 #define PHP_HTTP_HEADER_PARSER_CLEANUP 0x1
 
 typedef struct php_http_header_parser {
-       zend_stack stack;
+       zend_ptr_stack stack;
        php_http_info_t info;
        struct {
                char *str;
index 61a1f747d9660781a9015112467ae54662dcec2b..cc04edcf3850285742935ce626e74b76fdb816ef 100644 (file)
@@ -149,7 +149,13 @@ php_http_message_t *php_http_message_parse(php_http_message_t *msg, const char *
 zval *php_http_message_header(php_http_message_t *msg, const char *key_str, size_t key_len, int join)
 {
        zval *ret = NULL, **header;
-       char *key = php_http_pretty_key(estrndup(key_str, key_len), key_len, 1, 1);
+       char *key;
+       ALLOCA_FLAG(free_key);
+
+       key = do_alloca(key_len + 1, free_key);
+       memcpy(key, key_str, key_len);
+       key[key_len] = '\0';
+       php_http_pretty_key(key, key_len, 1, 1);
 
        if (SUCCESS == zend_symtable_find(&msg->hdrs, key, key_len + 1, (void *) &header)) {
                if (join && Z_TYPE_PP(header) == IS_ARRAY) {
@@ -162,7 +168,7 @@ zval *php_http_message_header(php_http_message_t *msg, const char *key_str, size
                }
        }
 
-       efree(key);
+       free_alloca(key, free_key);
 
        return ret;
 }
@@ -300,6 +306,14 @@ void php_http_message_update_headers(php_http_message_t *msg)
                                zval_ptr_dtor(&h);
                        }
                }
+       } else if ((h = php_http_message_header(msg, ZEND_STRL("Content-Length"), 1))) {
+               zval *h_cpy = php_http_ztyp(IS_LONG, h);
+
+               zval_ptr_dtor(&h);
+               if (Z_LVAL_P(h_cpy)) {
+                       zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length"));
+               }
+               zval_ptr_dtor(&h_cpy);
        }
 }
 
@@ -764,7 +778,9 @@ STATUS php_http_message_object_set_body(php_http_message_object_t *msg_obj, zval
        }
 
        body_obj = zend_object_store_get_object(zbody TSRMLS_CC);
-
+       if (!body_obj->body) {
+               body_obj->body = php_http_message_body_init(NULL, NULL TSRMLS_CC);
+       }
        if (msg_obj->body) {
                zend_objects_store_del_ref_by_handle(msg_obj->body->zv.handle TSRMLS_CC);
        }
@@ -784,7 +800,7 @@ STATUS php_http_message_object_set_body(php_http_message_object_t *msg_obj, zval
 
 STATUS php_http_message_object_init_body_object(php_http_message_object_t *obj)
 {
-       TSRMLS_FETCH_FROM_CTX(obj);
+       TSRMLS_FETCH_FROM_CTX(obj->message->ts);
 
        php_http_message_body_addref(obj->message->body);
        return php_http_new(NULL, php_http_message_body_class_entry, (php_http_new_t) php_http_message_body_object_new_ex, NULL, obj->message->body, (void *) &obj->body TSRMLS_CC);
@@ -1808,7 +1824,9 @@ ZEND_BEGIN_ARG_INFO_EX(ai_HttpMessage_count, 0, 0, 0)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(HttpMessage, count)
 {
-       if (SUCCESS == zend_parse_parameters_none()) {
+       long count_mode = -1;
+
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &count_mode)) {
                long i = 0;
                php_http_message_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
 
index b9f1cb1e7920c1921864c5c403b5f0a0c65f1349..6328fa49e503a04944c618cb3ca56a38dcaccd57 100644 (file)
@@ -54,7 +54,6 @@ php_http_message_parser_t *php_http_message_parser_init(php_http_message_parser_
        TSRMLS_SET_CTX(parser->ts);
 
        php_http_header_parser_init(&parser->header TSRMLS_CC);
-       zend_stack_init(&parser->stack);
 
        return parser;
 }
@@ -65,10 +64,13 @@ php_http_message_parser_state_t php_http_message_parser_state_push(php_http_mess
        va_list va_args;
        unsigned i;
 
+       /* short circuit */
+       ZEND_PTR_STACK_RESIZE_IF_NEEDED((&parser->stack), argc);
+
        va_start(va_args, argc);
        for (i = 0; i < argc; ++i) {
                state  = va_arg(va_args, php_http_message_parser_state_t);
-               zend_stack_push(&parser->stack, &state, sizeof(state));
+               zend_ptr_stack_push(&parser->stack, (void *) state);
        }
        va_end(va_args);
 
@@ -77,21 +79,16 @@ php_http_message_parser_state_t php_http_message_parser_state_push(php_http_mess
 
 php_http_message_parser_state_t php_http_message_parser_state_is(php_http_message_parser_t *parser)
 {
-       php_http_message_parser_state_t *state;
-
-       if (SUCCESS == zend_stack_top(&parser->stack, (void *) &state)) {
-               return *state;
+       if (parser->stack.top) {
+               return (php_http_message_parser_state_t) zend_ptr_stack_top(&parser->stack);
        }
        return PHP_HTTP_MESSAGE_PARSER_STATE_START;
 }
 
 php_http_message_parser_state_t php_http_message_parser_state_pop(php_http_message_parser_t *parser)
 {
-       php_http_message_parser_state_t state, *state_ptr;
-       if (SUCCESS == zend_stack_top(&parser->stack, (void *) &state_ptr)) {
-               state = *state_ptr;
-               zend_stack_del_top(&parser->stack);
-               return state;
+       if (parser->stack.top) {
+               return (php_http_message_parser_state_t) zend_ptr_stack_pop(&parser->stack);
        }
        return PHP_HTTP_MESSAGE_PARSER_STATE_START;
 }
@@ -99,7 +96,7 @@ php_http_message_parser_state_t php_http_message_parser_state_pop(php_http_messa
 void php_http_message_parser_dtor(php_http_message_parser_t *parser)
 {
        php_http_header_parser_dtor(&parser->header);
-       zend_stack_destroy(&parser->stack);
+       zend_ptr_stack_destroy(&parser->stack);
        if (parser->dechunk) {
                php_http_encoding_stream_free(&parser->dechunk);
        }
index ade991bdc6037e03c82a27d965df4dad73ea0da2..ebc2142157bd3feb13021e53cfafe5abc6960352 100644 (file)
@@ -37,7 +37,7 @@ typedef enum php_http_message_parser_state {
 
 typedef struct php_http_message_parser {
        php_http_header_parser_t header;
-       zend_stack stack;
+       zend_ptr_stack stack;
        size_t body_length;
        php_http_message_t *message;
        php_http_encoding_stream_t *dechunk;
index 0515c961b597629b388c4df68cc5090d64ad48ad..7afa006053299cb1215069e98c49a9a47c765e1d 100644 (file)
@@ -61,7 +61,8 @@ int php_http_match(const char *haystack_str, const char *needle_str, int flags)
                        result = !strcasecmp(haystack_str, needle_str);
                }
        } else {
-               char *found, *haystack = estrdup(haystack_str), *needle = estrdup(needle_str);
+               const char *found;
+               char *haystack = estrdup(haystack_str), *needle = estrdup(needle_str);
 
                if (flags & PHP_HTTP_MATCH_CASE) {
                        found = zend_memnstr(haystack, needle, strlen(needle), haystack+strlen(haystack));
@@ -86,16 +87,16 @@ int php_http_match(const char *haystack_str, const char *needle_str, int flags)
        return result;
 }
 
-char *php_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
+char *php_http_pretty_key(register char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
 {
-       size_t i;
+       size_t i = 1;
        int wasalpha;
 
        if (key && key_len) {
                if ((wasalpha = PHP_HTTP_IS_CTYPE(alpha, key[0]))) {
                        key[0] = (char) (uctitle ? PHP_HTTP_TO_CTYPE(upper, key[0]) : PHP_HTTP_TO_CTYPE(lower, key[0]));
                }
-               for (i = 1; i < key_len; i++) {
+               PHP_HTTP_DUFF(1, key_len,
                        if (PHP_HTTP_IS_CTYPE(alpha, key[i])) {
                                key[i] = (char) (((!wasalpha) && uctitle) ? PHP_HTTP_TO_CTYPE(upper, key[i]) : PHP_HTTP_TO_CTYPE(lower, key[i]));
                                wasalpha = 1;
@@ -105,7 +106,8 @@ char *php_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_boo
                                }
                                wasalpha = 0;
                        }
-               }
+                       ++i;
+               );
        }
        return key;
 }
@@ -165,12 +167,19 @@ unsigned php_http_array_list(HashTable *ht TSRMLS_DC, unsigned argc, ...)
        return argl;
 }
 
+void php_http_array_copy_strings(void *zpp)
+{
+       zval **zvpp = ((zval **) zpp);
+
+       *zvpp = php_http_zsep(1, IS_STRING, *zvpp);
+}
+
 int php_http_array_apply_append_func(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
 {
        int flags;
        char *key = NULL;
        HashTable *dst;
-       zval **data = NULL, **value = (zval **) pDest;
+       zval **data = NULL, *value = *((zval **) pDest);
 
        dst = va_arg(args, HashTable *);
        flags = va_arg(args, int);
@@ -183,16 +192,21 @@ int php_http_array_apply_append_func(void *pDest TSRMLS_DC, int num_args, va_lis
                        zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data);
                }
 
-               Z_ADDREF_P(*value);
+               if (flags & ARRAY_JOIN_STRINGIFY) {
+                       value = php_http_zsep(1, IS_STRING, value);
+               } else {
+                       Z_ADDREF_P(value);
+               }
+
                if (data) {
                        if (Z_TYPE_PP(data) != IS_ARRAY) {
                                convert_to_array(*data);
                        }
-                       add_next_index_zval(*data, *value);
+                       add_next_index_zval(*data, value);
                } else if (key) {
-                       zend_symtable_update(dst, key, hash_key->nKeyLength, value, sizeof(zval *), NULL);
+                       zend_symtable_update(dst, key, hash_key->nKeyLength, &value, sizeof(zval *), NULL);
                } else {
-                       zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, value, sizeof(zval *), NULL);
+                       zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, &value, sizeof(zval *), NULL);
                }
 
                if (key) {
@@ -208,19 +222,24 @@ int php_http_array_apply_merge_func(void *pDest TSRMLS_DC, int num_args, va_list
        int flags;
        char *key = NULL;
        HashTable *dst;
-       zval **value = (zval **) pDest;
+       zval *value = *((zval **) pDest);
 
        dst = va_arg(args, HashTable *);
        flags = va_arg(args, int);
 
        if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
-               Z_ADDREF_P(*value);
+               if (flags & ARRAY_JOIN_STRINGIFY) {
+                       value = php_http_zsep(1, IS_STRING, value);
+               } else {
+                       Z_ADDREF_P(value);
+               }
+
                if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
                        key = php_http_pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
-                       zend_hash_update(dst, key, hash_key->nKeyLength, (void *) value, sizeof(zval *), NULL);
+                       zend_hash_update(dst, key, hash_key->nKeyLength, (void *) &value, sizeof(zval *), NULL);
                        efree(key);
                } else {
-                       zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) value, sizeof(zval *), NULL);
+                       zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &value, sizeof(zval *), NULL);
                }
        }
 
index 75090bdad4cc70dccffae0130e87d8f63dc8ae9c..d47477c91ccaf87dc6256ae84bbef31d6c5fe14a 100644 (file)
@@ -60,25 +60,51 @@ PHP_HTTP_API void php_http_sleep(double s);
 #define PHP_HTTP_MATCH_STRICT  (PHP_HTTP_MATCH_CASE|PHP_HTTP_MATCH_FULL)
 
 int php_http_match(const char *haystack, const char *needle, int flags);
-char *php_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen);
+char *php_http_pretty_key(register char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen);
 size_t php_http_boundary(char *buf, size_t len TSRMLS_DC);
 int php_http_select_str(const char *cmp, int argc, ...);
 
-static inline const char *php_http_locate_str(const char *h, size_t h_len, const char *n, size_t n_len)
+/* See "A Reusable Duff Device" By Ralf Holly, August 01, 2005 */
+#define PHP_HTTP_DUFF_BREAK(i) do { \
+       times_##i = 1; \
+} while (0)
+
+#define PHP_HTTP_DUFF(i, c, a) do { \
+               size_t count_##i = (c); \
+               size_t times_##i = (count_##i + 7) >> 3; \
+               switch (count_##i & 7){ \
+               case 0: do { a; \
+               case 7: a; \
+               case 6: a; \
+               case 5: a; \
+               case 4: a; \
+               case 3: a; \
+               case 2: a; \
+               case 1: a; \
+               } while (--times_##i > 0); \
+       } \
+} while (0)
+
+
+static inline const char *php_http_locate_str(register const char *h, size_t h_len, const char *n, size_t n_len)
 {
-       const char *p, *e;
+       register const char *p1, *p2;
 
-       if (n_len && h_len) {
-               e = h + h_len;
-               do {
+       if (n_len && h_len && h_len >= n_len) {
+               PHP_HTTP_DUFF(1, h_len - n_len + 1,
                        if (*h == *n) {
-                               for (p = n; *p == h[p-n]; ++p) {
-                                       if (p == n+n_len-1) {
+                               p1 = h;
+                               p2 = n;
+                               PHP_HTTP_DUFF(2, n_len,
+                                       if (*p1++ != *p2++) {
+                                               PHP_HTTP_DUFF_BREAK(2);
+                                       } else if (p2 == n + n_len - 1) {
                                                return h;
                                        }
-                               }
+                               );
                        }
-               } while (h++ != e);
+                       ++h;
+               );
        }
 
        return NULL;
@@ -96,17 +122,19 @@ static inline const char *php_http_locate_eol(const char *line, int *eol_len)
 
 static inline const char *php_http_locate_bin_eol(const char *bin, size_t len, int *eol_len)
 {
-       const char *eol;
+       register const char *eol = bin;
 
-       for (eol = bin; eol - bin < len; ++eol) {
-               if (*eol == '\r' || *eol == '\n') {
-                       if (eol_len) {
-                               *eol_len = ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1);
+       if (len > 0) {
+               PHP_HTTP_DUFF(1, len,
+                       if (*eol == '\r' || *eol == '\n') {
+                               if (eol_len) {
+                                       *eol_len = ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1);
+                               }
+                               return eol;
                        }
-                       return eol;
-               }
+                       ++eol;
+               );
        }
-
        return NULL;
 }
 
@@ -127,6 +155,12 @@ static inline const char *php_http_locate_bin_eol(const char *bin, size_t len, i
 #      define PHP_HTTP_ZEND_LITERAL_CCN , NULL
 #endif
 
+#if PHP_VERSION_ID < 50700
+#      define z_is_true zend_is_true
+#else
+#      define z_is_true(z) zend_is_true(z TSRMLS_CC)
+#endif
+
 #define INIT_PZVAL_ARRAY(zv, ht) \
        { \
                INIT_PZVAL((zv)); \
@@ -134,42 +168,37 @@ static inline const char *php_http_locate_bin_eol(const char *bin, size_t len, i
                Z_ARRVAL_P(zv) = (ht); \
        }
 
-static inline zval *php_http_ztyp(int type, zval *z)
+static inline zval *php_http_zconv(int type, zval *z)
 {
-       SEPARATE_ARG_IF_REF(z);
-       if (Z_TYPE_P(z) != type) {
-               switch (type) {
-                       case IS_NULL:   convert_to_null_ex(&z);         break;
-                       case IS_BOOL:   convert_to_boolean_ex(&z);      break;
-                       case IS_LONG:   convert_to_long_ex(&z);         break;
-                       case IS_DOUBLE: convert_to_double_ex(&z);       break;
-                       case IS_STRING: convert_to_string_ex(&z);       break;
-                       case IS_ARRAY:  convert_to_array_ex(&z);        break;
-                       case IS_OBJECT: convert_to_object_ex(&z);       break;
-               }
+       switch (type) {
+               case IS_NULL:   convert_to_null_ex(&z);         break;
+               case IS_BOOL:   convert_to_boolean_ex(&z);      break;
+               case IS_LONG:   convert_to_long_ex(&z);         break;
+               case IS_DOUBLE: convert_to_double_ex(&z);       break;
+               case IS_STRING: convert_to_string_ex(&z);       break;
+               case IS_ARRAY:  convert_to_array_ex(&z);        break;
+               case IS_OBJECT: convert_to_object_ex(&z);       break;
        }
        return z;
 }
 
+static inline zval *php_http_ztyp(int type, zval *z)
+{
+       SEPARATE_ARG_IF_REF(z);
+       return (Z_TYPE_P(z) == type) ? z : php_http_zconv(type, z);
+}
+
 static inline zval *php_http_zsep(zend_bool add_ref, int type, zval *z)
 {
        if (add_ref) {
                Z_ADDREF_P(z);
        }
        if (Z_TYPE_P(z) != type) {
-               switch (type) {
-                       case IS_NULL:   convert_to_null_ex(&z);         break;
-                       case IS_BOOL:   convert_to_boolean_ex(&z);      break;
-                       case IS_LONG:   convert_to_long_ex(&z);         break;
-                       case IS_DOUBLE: convert_to_double_ex(&z);       break;
-                       case IS_STRING: convert_to_string_ex(&z);       break;
-                       case IS_ARRAY:  convert_to_array_ex(&z);        break;
-                       case IS_OBJECT: convert_to_object_ex(&z);       break;
-               }
+               return php_http_zconv(type, z);
        } else {
                SEPARATE_ZVAL_IF_NOT_REF(&z);
+               return z;
        }
-       return z;
 }
 
 static inline STATUS php_http_ini_entry(const char *name_str, size_t name_len, const char **value_str, size_t *value_len, zend_bool orig TSRMLS_DC)
@@ -240,6 +269,11 @@ static inline STATUS php_http_ini_entry(const char *name_str, size_t name_len, c
 #define PHP_RSHUTDOWN_CALL(func) PHP_RSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU)
 
 /* ARRAYS */
+
+#ifndef HASH_KEY_NON_EXISTENT
+#      define HASH_KEY_NON_EXISTENT HASH_KEY_NON_EXISTANT
+#endif
+
 PHP_HTTP_API unsigned php_http_array_list(HashTable *ht TSRMLS_DC, unsigned argc, ...);
 
 typedef struct php_http_array_hashkey {
@@ -285,10 +319,13 @@ static inline void php_http_array_hashkey_stringfree(php_http_array_hashkey_t *k
                        zend_hash_move_forward_ex(hash, &pos))
 
 #define array_copy(src, dst) zend_hash_copy(dst, src, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *))
-#define ARRAY_JOIN_STRONLY 1
-#define ARRAY_JOIN_PRETTIFY 2
+#define array_copy_strings(src, dst) zend_hash_copy(dst, src, php_http_array_copy_strings, NULL, sizeof(zval *))
+#define ARRAY_JOIN_STRONLY   0x01
+#define ARRAY_JOIN_PRETTIFY  0x02
+#define ARRAY_JOIN_STRINGIFY 0x04
 #define array_join(src, dst, append, flags) zend_hash_apply_with_arguments(src TSRMLS_CC, (append)?php_http_array_apply_append_func:php_http_array_apply_merge_func, 2, dst, (int)flags)
 
+void php_http_array_copy_strings(void *zpp);
 int php_http_array_apply_append_func(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
 int php_http_array_apply_merge_func(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
 
index d2df6cf125f4dc5fa821c2fd11554eff8f7d4285..65504ac660155e6d40da74c98d8e7b0d4b15b7cc 100644 (file)
@@ -47,9 +47,10 @@ typedef struct php_http_params_state {
        } current;
        unsigned quotes:1;
        unsigned escape:1;
+       unsigned rfc5987:1;
 } php_http_params_state_t;
 
-static inline void sanitize_default(zval *zv TSRMLS_DC)
+static inline void sanitize_escaped(zval *zv TSRMLS_DC)
 {
        if (Z_STRVAL_P(zv)[0] == '"' && Z_STRVAL_P(zv)[Z_STRLEN_P(zv) - 1] == '"') {
                size_t deq_len = Z_STRLEN_P(zv) - 2;
@@ -59,17 +60,18 @@ static inline void sanitize_default(zval *zv TSRMLS_DC)
                ZVAL_STRINGL(zv, deq, deq_len, 0);
        }
 
-       php_stripslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv) TSRMLS_CC);
+       php_stripcslashes(Z_STRVAL_P(zv), &Z_STRLEN_P(zv));
 }
 
-static inline void prepare_default(zval *zv TSRMLS_DC)
+static inline void prepare_escaped(zval *zv TSRMLS_DC)
 {
        if (Z_TYPE_P(zv) == IS_STRING) {
                int len = Z_STRLEN_P(zv);
 
-               Z_STRVAL_P(zv) = php_addslashes(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &Z_STRLEN_P(zv), 1 TSRMLS_CC);
+               Z_STRVAL_P(zv) = php_addcslashes(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &Z_STRLEN_P(zv), 1,
+                               ZEND_STRL("\0..\37\173\\\"") TSRMLS_CC);
 
-               if (len != Z_STRLEN_P(zv)) {
+               if (len != Z_STRLEN_P(zv) || strpbrk(Z_STRVAL_P(zv), "()<>@,;:\"[]?={} ")) {
                        zval tmp = *zv;
                        int len = Z_STRLEN_P(zv) + 2;
                        char *str = emalloc(len + 1);
@@ -96,7 +98,7 @@ static inline void sanitize_urlencoded(zval *zv TSRMLS_DC)
 static inline void prepare_urlencoded(zval *zv TSRMLS_DC)
 {
        int len;
-       char *str =     php_url_encode(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &len);
+       char *str =     php_raw_url_encode(Z_STRVAL_P(zv), Z_STRLEN_P(zv), &len);
 
        zval_dtor(zv);
        ZVAL_STRINGL(zv, str, len, 0);
@@ -212,13 +214,22 @@ static void prepare_dimension(php_http_buffer_t *buf, php_http_buffer_t *keybuf,
        --ht->nApplyCount;
 }
 
-static inline void sanitize_key(unsigned flags, char *str, size_t len, zval *zv TSRMLS_DC)
+static inline void sanitize_key(unsigned flags, char *str, size_t len, zval *zv, zend_bool *rfc5987 TSRMLS_DC)
 {
+       char *eos;
+
        zval_dtor(zv);
        php_trim(str, len, NULL, 0, zv, 3 TSRMLS_CC);
 
-       if (flags & PHP_HTTP_PARAMS_DEFAULT) {
-               sanitize_default(zv TSRMLS_CC);
+       if (flags & PHP_HTTP_PARAMS_ESCAPED) {
+               sanitize_escaped(zv TSRMLS_CC);
+       }
+
+       eos = &Z_STRVAL_P(zv)[Z_STRLEN_P(zv)-1];
+       if (*eos == '*') {
+               *eos = '\0';
+               *rfc5987 = 1;
+               Z_STRLEN_P(zv) -= 1;
        }
 
        if (flags & PHP_HTTP_PARAMS_URLENCODED) {
@@ -230,18 +241,110 @@ static inline void sanitize_key(unsigned flags, char *str, size_t len, zval *zv
        }
 }
 
-static inline void sanitize_value(unsigned flags, char *str, size_t len, zval *zv TSRMLS_DC)
+static inline void sanitize_rfc5987(zval *zv, char **language, zend_bool *latin1 TSRMLS_DC)
+{
+       char *ptr;
+
+       /* examples:
+        * iso-8850-1'de'bl%f6der%20schei%df%21
+        * utf-8'de-DE'bl%c3%b6der%20schei%c3%9f%21
+        */
+
+       switch (Z_STRVAL_P(zv)[0]) {
+       case 'I':
+       case 'i':
+               if (!strncasecmp(Z_STRVAL_P(zv), ZEND_STRL("iso-8859-1"))) {
+                       *latin1 = 1;
+                       ptr = Z_STRVAL_P(zv) + lenof("iso-8859-1");
+                       break;
+               }
+               /* no break */
+       case 'U':
+       case 'u':
+               if (!strncasecmp(Z_STRVAL_P(zv), ZEND_STRL("utf-8"))) {
+                       *latin1 = 0;
+                       ptr = Z_STRVAL_P(zv) + lenof("utf-8");
+                       break;
+               }
+               /* no break */
+       default:
+               return;
+       }
+
+       /* extract language */
+       if (*ptr == '\'') {
+               for (*language = ++ptr; *ptr && *ptr != '\''; ++ptr);
+               if (!*ptr) {
+                       *language = NULL;
+                       return;
+               }
+               *language = estrndup(*language, ptr - *language);
+
+               /* remainder */
+               ptr = estrdup(++ptr);
+               zval_dtor(zv);
+               ZVAL_STRING(zv, ptr, 0);
+       }
+}
+
+static void utf8encode(zval *zv)
+{
+       size_t pos, len = 0;
+       unsigned char *ptr = (unsigned char *) Z_STRVAL_P(zv);
+
+       while (*ptr) {
+               if (*ptr++ >= 0x80) {
+                       ++len;
+               }
+               ++len;
+       }
+
+       ptr = safe_emalloc(1, len, 1);
+       for (len = 0, pos = 0; len <= Z_STRLEN_P(zv); ++len, ++pos) {
+               ptr[pos] = Z_STRVAL_P(zv)[len];
+               if ((ptr[pos]) >= 0x80) {
+                       ptr[pos + 1] = 0x80 | (ptr[pos] & 0x3f);
+                       ptr[pos] = 0xc0 | ((ptr[pos] >> 6) & 0x1f);
+                       ++pos;
+               }
+       }
+       zval_dtor(zv);
+       ZVAL_STRINGL(zv, (char *) ptr, pos-1, 0);
+}
+
+static inline void sanitize_value(unsigned flags, char *str, size_t len, zval *zv, zend_bool rfc5987 TSRMLS_DC)
 {
+       char *language = NULL;
+       zend_bool latin1 = 0;
+
        zval_dtor(zv);
        php_trim(str, len, NULL, 0, zv, 3 TSRMLS_CC);
 
-       if (flags & PHP_HTTP_PARAMS_DEFAULT) {
-               sanitize_default(zv TSRMLS_CC);
+       if (rfc5987) {
+               sanitize_rfc5987(zv, &language, &latin1 TSRMLS_CC);
        }
 
-       if (flags & PHP_HTTP_PARAMS_URLENCODED) {
+       if (flags & PHP_HTTP_PARAMS_ESCAPED) {
+               sanitize_escaped(zv TSRMLS_CC);
+       }
+
+       if ((flags & PHP_HTTP_PARAMS_URLENCODED) || (rfc5987 && language)) {
                sanitize_urlencoded(zv TSRMLS_CC);
        }
+
+       if (rfc5987 && language) {
+               zval *tmp;
+
+               if (latin1) {
+                       utf8encode(zv);
+               }
+
+               MAKE_STD_ZVAL(tmp);
+               ZVAL_COPY_VALUE(tmp, zv);
+               array_init(zv);
+               add_assoc_zval(zv, language, tmp);
+               STR_FREE(language);
+       }
 }
 
 static inline void prepare_key(unsigned flags, char *old_key, size_t old_len, char **new_key, size_t *new_len TSRMLS_DC)
@@ -255,8 +358,8 @@ static inline void prepare_key(unsigned flags, char *old_key, size_t old_len, ch
                prepare_urlencoded(&zv TSRMLS_CC);
        }
 
-       if (flags & PHP_HTTP_PARAMS_DEFAULT) {
-               prepare_default(&zv TSRMLS_CC);
+       if (flags & PHP_HTTP_PARAMS_ESCAPED) {
+               prepare_escaped(&zv TSRMLS_CC);
        }
 
        *new_key = Z_STRVAL(zv);
@@ -269,8 +372,8 @@ static inline void prepare_value(unsigned flags, zval *zv TSRMLS_DC)
                prepare_urlencoded(zv TSRMLS_CC);
        }
 
-       if (flags & PHP_HTTP_PARAMS_DEFAULT) {
-               prepare_default(zv TSRMLS_CC);
+       if (flags & PHP_HTTP_PARAMS_ESCAPED) {
+               prepare_escaped(zv TSRMLS_CC);
        }
 }
 
@@ -392,34 +495,55 @@ static void push_param(HashTable *params, php_http_params_state_t *state, const
 {
        if (state->val.str) {
                if (0 < (state->val.len = state->input.str - state->val.str)) {
-                       sanitize_value(opts->flags, state->val.str, state->val.len, *(state->current.val) TSRMLS_CC);
+                       sanitize_value(opts->flags, state->val.str, state->val.len, *(state->current.val), state->rfc5987 TSRMLS_CC);
                }
+               state->rfc5987 = 0;
        } else if (state->arg.str) {
                if (0 < (state->arg.len = state->input.str - state->arg.str)) {
                        zval *val, key;
+                       zend_bool rfc5987 = 0;
 
                        INIT_PZVAL(&key);
                        ZVAL_NULL(&key);
-                       sanitize_key(opts->flags, state->arg.str, state->arg.len, &key TSRMLS_CC);
+                       sanitize_key(opts->flags, state->arg.str, state->arg.len, &key, &rfc5987 TSRMLS_CC);
+                       state->rfc5987 = rfc5987;
                        if (Z_TYPE(key) == IS_STRING && Z_STRLEN(key)) {
                                MAKE_STD_ZVAL(val);
                                ZVAL_TRUE(val);
-                               zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
+
+                               if (rfc5987) {
+                                       zval **rfc;
+
+                                       if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(state->current.args), ZEND_STRS("*rfc5987*"), (void *) &rfc)) {
+                                               zend_symtable_update(Z_ARRVAL_PP(rfc), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
+                                       } else {
+                                               zval *tmp;
+
+                                               MAKE_STD_ZVAL(tmp);
+                                               array_init_size(tmp, 1);
+                                               zend_symtable_update(Z_ARRVAL_P(tmp), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
+                                               zend_symtable_update(Z_ARRVAL_PP(state->current.args), ZEND_STRS("*rfc5987*"), (void *) &tmp, sizeof(zval *), NULL);
+                                       }
+                               } else {
+                                       zend_symtable_update(Z_ARRVAL_PP(state->current.args), Z_STRVAL(key), Z_STRLEN(key) + 1, (void *) &val, sizeof(zval *), (void *) &state->current.val);
+                               }
                        }
                        zval_dtor(&key);
                }
        } else if (state->param.str) {
                if (0 < (state->param.len = state->input.str - state->param.str)) {
                        zval *prm, *arg, *val, *key;
+                       zend_bool rfc5987 = 0;
 
                        MAKE_STD_ZVAL(key);
                        ZVAL_NULL(key);
-                       sanitize_key(opts->flags, state->param.str, state->param.len, key TSRMLS_CC);
+                       sanitize_key(opts->flags, state->param.str, state->param.len, key, &rfc5987 TSRMLS_CC);
+                       state->rfc5987 = rfc5987;
                        if (Z_TYPE_P(key) != IS_STRING) {
                                merge_param(params, key, &state->current.val, &state->current.args TSRMLS_CC);
                        } else if (Z_STRLEN_P(key)) {
                                MAKE_STD_ZVAL(prm);
-                               array_init(prm);
+                               array_init_size(prm, 2);
 
                                MAKE_STD_ZVAL(val);
                                if (opts->defval) {
@@ -428,10 +552,14 @@ static void push_param(HashTable *params, php_http_params_state_t *state, const
                                } else {
                                        ZVAL_TRUE(val);
                                }
-                               zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val);
+                               if (rfc5987 && (opts->flags & PHP_HTTP_PARAMS_RFC5987)) {
+                                       zend_hash_update(Z_ARRVAL_P(prm), "*rfc5987*", sizeof("*rfc5987*"), (void *) &val, sizeof(zval *), (void *) &state->current.val);
+                               } else {
+                                       zend_hash_update(Z_ARRVAL_P(prm), "value", sizeof("value"), (void *) &val, sizeof(zval *), (void *) &state->current.val);
+                               }
 
                                MAKE_STD_ZVAL(arg);
-                               array_init(arg);
+                               array_init_size(arg, 3);
                                zend_hash_update(Z_ARRVAL_P(prm), "arguments", sizeof("arguments"), (void *) &arg, sizeof(zval *), (void *) &state->current.args);
 
                                zend_symtable_update(params, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void *) &prm, sizeof(zval *), (void *) &state->current.param);
@@ -442,7 +570,7 @@ static void push_param(HashTable *params, php_http_params_state_t *state, const
 }
 
 static inline zend_bool check_str(const char *chk_str, size_t chk_len, const char *sep_str, size_t sep_len) {
-       return 0 < sep_len && chk_len >= sep_len && !memcmp(chk_str, sep_str, sep_len);
+       return 0 < sep_len && chk_len >= sep_len && *chk_str == *sep_str && !memcmp(chk_str + 1, sep_str + 1, sep_len - 1);
 }
 
 static size_t check_sep(php_http_params_state_t *state, php_http_params_token_t **separators)
@@ -576,6 +704,28 @@ static inline void shift_key(php_http_buffer_t *buf, char *key_str, size_t key_l
        efree(str);
 }
 
+static inline void shift_rfc5987(php_http_buffer_t *buf, zval *zvalue, const char *vss, size_t vsl, unsigned flags TSRMLS_DC)
+{
+       HashTable *ht = HASH_OF(zvalue);
+       zval **zdata, *tmp;
+       php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
+
+       if (SUCCESS == zend_hash_get_current_data(ht, (void *) &zdata)
+       &&      HASH_KEY_NON_EXISTENT != (key.type = zend_hash_get_current_key_ex(ht, &key.str, &key.len, &key.num, key.dup, NULL))
+       ) {
+               php_http_array_hashkey_stringify(&key);
+               php_http_buffer_appendf(buf, "*%.*sutf-8'%.*s'",
+                               (int) (vsl > INT_MAX ? INT_MAX : vsl), vss,
+                               (int) (key.len > INT_MAX ? INT_MAX : key.len), key.str);
+               php_http_array_hashkey_stringfree(&key);
+
+               tmp = php_http_zsep(1, IS_STRING, *zdata);
+               prepare_value(flags | PHP_HTTP_PARAMS_URLENCODED, tmp TSRMLS_CC);
+               php_http_buffer_append(buf, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
+               zval_ptr_dtor(&tmp);
+       }
+}
+
 static inline void shift_val(php_http_buffer_t *buf, zval *zvalue, const char *vss, size_t vsl, unsigned flags TSRMLS_DC)
 {
        if (Z_TYPE_P(zvalue) != IS_BOOL) {
@@ -598,12 +748,20 @@ static void shift_arg(php_http_buffer_t *buf, char *key_str, size_t key_len, zva
                HashPosition pos;
                php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
                zval **val;
+               zend_bool rfc5987 = !strcmp(key_str, "*rfc5987*");
 
-               shift_key(buf, key_str, key_len, ass, asl, flags TSRMLS_CC);
+               if (!rfc5987) {
+                       shift_key(buf, key_str, key_len, ass, asl, flags TSRMLS_CC);
+               }
                FOREACH_KEYVAL(pos, zvalue, key, val) {
                        /* did you mean recursion? */
                        php_http_array_hashkey_stringify(&key);
-                       shift_arg(buf, key.str, key.len-1, *val, ass, asl, vss, vsl, flags TSRMLS_CC);
+                       if (rfc5987 && (Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT)) {
+                               shift_key(buf, key.str, key.len-1, ass, asl, flags TSRMLS_CC);
+                               shift_rfc5987(buf, *val, vss, vsl, flags TSRMLS_CC);
+                       } else {
+                               shift_arg(buf, key.str, key.len-1, *val, ass, asl, vss, vsl, flags TSRMLS_CC);
+                       }
                        php_http_array_hashkey_stringfree(&key);
                }
        } else {
@@ -612,14 +770,17 @@ static void shift_arg(php_http_buffer_t *buf, char *key_str, size_t key_len, zva
        }
 }
 
-static void shift_param(php_http_buffer_t *buf, char *key_str, size_t key_len, zval *zvalue, const char *pss, size_t psl, const char *ass, size_t asl, const char *vss, size_t vsl, unsigned flags TSRMLS_DC)
+static void shift_param(php_http_buffer_t *buf, char *key_str, size_t key_len, zval *zvalue, const char *pss, size_t psl, const char *ass, size_t asl, const char *vss, size_t vsl, unsigned flags, zend_bool rfc5987 TSRMLS_DC)
 {
        if (Z_TYPE_P(zvalue) == IS_ARRAY || Z_TYPE_P(zvalue) == IS_OBJECT) {
-               /* treat as arguments, unless we care for dimensions */
+               /* treat as arguments, unless we care for dimensions or rfc5987 */
                if (flags & PHP_HTTP_PARAMS_DIMENSION) {
                        php_http_buffer_t *keybuf = php_http_buffer_from_string(key_str, key_len);
                        prepare_dimension(buf, keybuf, zvalue, pss, psl, vss, vsl, flags TSRMLS_CC);
                        php_http_buffer_free(&keybuf);
+               } else if (rfc5987) {
+                       shift_key(buf, key_str, key_len, pss, psl, flags TSRMLS_CC);
+                       shift_rfc5987(buf, zvalue, vss, vsl, flags TSRMLS_CC);
                } else {
                        shift_arg(buf, key_str, key_len, zvalue, ass, asl, vss, vsl, flags TSRMLS_CC);
                }
@@ -634,6 +795,7 @@ php_http_buffer_t *php_http_params_to_string(php_http_buffer_t *buf, HashTable *
        zval **zparam;
        HashPosition pos, pos1;
        php_http_array_hashkey_t key = php_http_array_hashkey_init(0), key1 = php_http_array_hashkey_init(0);
+       zend_bool rfc5987 = 0;
 
        if (!buf) {
                buf = php_http_buffer_init(NULL);
@@ -642,12 +804,20 @@ php_http_buffer_t *php_http_params_to_string(php_http_buffer_t *buf, HashTable *
        FOREACH_HASH_KEYVAL(pos, params, key, zparam) {
                zval **zvalue, **zargs;
 
-               if (Z_TYPE_PP(zparam) != IS_ARRAY || SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
+               if (Z_TYPE_PP(zparam) != IS_ARRAY) {
                        zvalue = zparam;
+               } else {
+                       if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("value"), (void *) &zvalue)) {
+                               if (SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("*rfc5987*"), (void *) &zvalue)) {
+                                       zvalue = zparam;
+                               } else {
+                                       rfc5987 = 1;
+                               }
+                       }
                }
 
                php_http_array_hashkey_stringify(&key);
-               shift_param(buf, key.str, key.len - 1, *zvalue, pss, psl, ass, asl, vss, vsl, flags TSRMLS_CC);
+               shift_param(buf, key.str, key.len - 1, *zvalue, pss, psl, ass, asl, vss, vsl, flags, rfc5987 TSRMLS_CC);
                php_http_array_hashkey_stringfree(&key);
 
                if (Z_TYPE_PP(zparam) == IS_ARRAY && SUCCESS != zend_hash_find(Z_ARRVAL_PP(zparam), ZEND_STRS("arguments"), (void *) &zvalue)) {
@@ -1002,9 +1172,11 @@ PHP_MINIT_FUNCTION(http_params)
        zend_declare_class_constant_stringl(php_http_params_class_entry, ZEND_STRL("COOKIE_PARAM_SEP"), ZEND_STRL("") TSRMLS_CC);
 
        zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_RAW"), PHP_HTTP_PARAMS_RAW TSRMLS_CC);
-       zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_DEFAULT"), PHP_HTTP_PARAMS_DEFAULT TSRMLS_CC);
+       zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_ESCAPED"), PHP_HTTP_PARAMS_ESCAPED TSRMLS_CC);
        zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_URLENCODED"), PHP_HTTP_PARAMS_URLENCODED TSRMLS_CC);
        zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_DIMENSION"), PHP_HTTP_PARAMS_DIMENSION TSRMLS_CC);
+       zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_RFC5987"), PHP_HTTP_PARAMS_RFC5987 TSRMLS_CC);
+       zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_DEFAULT"), PHP_HTTP_PARAMS_DEFAULT TSRMLS_CC);
        zend_declare_class_constant_long(php_http_params_class_entry, ZEND_STRL("PARSE_QUERY"), PHP_HTTP_PARAMS_QUERY TSRMLS_CC);
 
        zend_declare_property_null(php_http_params_class_entry, ZEND_STRL("params"), ZEND_ACC_PUBLIC TSRMLS_CC);
index 006895299583f00508662c11bd682e4f84517b72..42f56f901c5249b2bf12d661761ab048d49a56c7 100644 (file)
@@ -19,10 +19,12 @@ typedef struct php_http_params_token {
 } php_http_params_token_t;
 
 #define PHP_HTTP_PARAMS_RAW                    0x00
-#define PHP_HTTP_PARAMS_DEFAULT                0x01
+#define PHP_HTTP_PARAMS_ESCAPED                0x01
 #define PHP_HTTP_PARAMS_URLENCODED     0x04
 #define PHP_HTTP_PARAMS_DIMENSION      0x08
+#define PHP_HTTP_PARAMS_RFC5987                0x10
 #define PHP_HTTP_PARAMS_QUERY          (PHP_HTTP_PARAMS_URLENCODED|PHP_HTTP_PARAMS_DIMENSION)
+#define PHP_HTTP_PARAMS_DEFAULT                (PHP_HTTP_PARAMS_ESCAPED|PHP_HTTP_PARAMS_RFC5987)
 
 typedef struct php_http_params_opts {
        php_http_params_token_t input;
index 60a8ad9357b3a81199abc7dec98d8d6e8852d16f..fbe94118cf53532bc603b52fbe46f160f14a3951 100644 (file)
@@ -27,19 +27,37 @@ php_http_version_t *php_http_version_init(php_http_version_t *v, unsigned major,
 php_http_version_t *php_http_version_parse(php_http_version_t *v, const char *str TSRMLS_DC)
 {
        php_http_version_t tmp;
-       char separator = 0;
+       char separator = 0, *stop = NULL;
+       register const char *ptr = str;
 
-       if (3 != sscanf(str, "HTTP/%u%c%u", &tmp.major, &separator, &tmp.minor)
-       &&      3 != sscanf(str, "%u%c%u", &tmp.major, &separator, &tmp.minor)) {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP protocol version '%s'", str);
-               return NULL;
+       switch (*ptr) {
+       case 'h':
+       case 'H':
+               ++ptr; if (*ptr != 't' && *ptr != 'T') break;
+               ++ptr; if (*ptr != 't' && *ptr != 'T') break;
+               ++ptr; if (*ptr != 'p' && *ptr != 'P') break;
+               ++ptr; if (*ptr != '/') break;
+               ++ptr;
+               /* no break */
+       default:
+               tmp.major = strtol(ptr, &stop, 10);
+               if (stop && stop != ptr && tmp.major != LONG_MIN && tmp.major != LONG_MAX) {
+                       separator = *stop;
+                       if (separator) {
+                               if (separator != '.' && separator != ',') {
+                                       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Non-standard version separator '%c' in HTTP protocol version '%s'", separator, ptr);
+                               }
+                               ptr = stop + 1;
+                               tmp.minor = strtol(ptr, &stop, 10);
+                               if (tmp.minor != LONG_MIN && tmp.minor != LONG_MAX) {
+                                       return php_http_version_init(v, tmp.major, tmp.minor TSRMLS_CC);
+                               }
+                       }
+               }
        }
 
-       if (separator && separator != '.' && separator != ',') {
-               php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Non-standard version separator '%c' in HTTP protocol version '%s'", separator, str);
-       }
-
-       return php_http_version_init(v, tmp.major, tmp.minor TSRMLS_CC);
+       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP protocol version '%s'", str);
+       return NULL;
 }
 
 void php_http_version_to_string(php_http_version_t *v, char **str, size_t *len, const char *pre, const char *post TSRMLS_DC)
diff --git a/phpunit.php b/phpunit.php
deleted file mode 100644 (file)
index 8a61937..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-require_once "PHPUnit/Autoload.php";
-$c = new PHPUnit_TextUI_Command;
-$c->run(array_merge($argv, array(__DIR__."/phpunit/")));
diff --git a/phpunit/CookieTest.php b/phpunit/CookieTest.php
deleted file mode 100644 (file)
index d569c75..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-<?php
-
-ini_set("date.timezone", "Europe/Vienna");
-
-class CookieTest extends PHPUnit_Framework_TestCase {
-    function testEmpty() {
-        $c = new http\Cookie;
-        $o = clone $c;
-        $a = array(
-            "cookies" => array(),
-            "extras" => array(),
-            "flags" => 0,
-            "expires" => -1,
-            "path" => "",
-            "domain" => "",
-               "max-age" => -1,
-        );
-        $this->assertEquals($a, $c->toArray());
-        $this->assertEquals($a, $o->toArray());
-    }
-
-    function testExpiresAsDate() {
-        $d = new DateTime;
-        $c = new http\Cookie(array("expires" => $d->format(DateTime::RFC1123)));
-        $this->assertEquals($d->format("U"), $c->getExpires());
-    }
-
-    function testNumeric() {
-        $c = new http\Cookie("1=%20; 2=%22; 3=%5D", 0, array(2));
-        $this->assertEquals("1=%20; 3=%5D; 2=%22; ", (string) $c);
-    }
-
-    function testRaw() {
-        $c = new http\Cookie("1=%20; 2=%22; e3=%5D", http\Cookie::PARSE_RAW, array(2));
-        $this->assertEquals("1=%2520; e3=%255D; 2=%2522; ", (string) $c);
-    }
-
-    function testSimple() {
-        $orig = new http\Cookie("key=value");
-        $copy = clone $orig;
-        $same = new http\Cookie($copy);
-        $even = new http\Cookie($same->toArray());
-        foreach (array($orig, $copy) as $c) {
-            $this->assertEquals("value", $c->getCookie("key"));
-            $this->assertEquals(-1, $c->getExpires());
-            $this->assertEquals(-1, $c->getMaxAge());
-            $this->assertEquals(0, $c->getFlags());
-            $this->assertEquals(null, $c->getPath());
-            $this->assertEquals(null, $c->getDomain());
-            $this->assertEquals(array(), $c->getExtras());
-            $this->assertEquals(array("key" => "value"), $c->getCookies());
-            $this->assertEquals("key=value; ", $c->toString());
-            $this->assertEquals(
-                array (
-                    "cookies" => 
-                        array (
-                            "key" => "value",
-                        ),
-                    "extras" => 
-                        array (
-                        ),
-                    "flags" => 0,
-                    "expires" => -1,
-                    "path" => "",
-                    "domain" => "",
-                       "max-age" => -1,
-                ),
-                $c->toArray()
-            );
-        }
-    }
-
-    function testExpires() {
-        $c = new http\Cookie("this=expires; expires=Tue, 24 Jan 2012 10:35:32 +0100");
-        $this->assertEquals("expires", $c->getCookie("this"));
-        $this->assertEquals(1327397732, $c->getExpires());
-        $o = clone $c;
-        $t = time();
-        $o->setExpires();
-        $this->assertEquals(-1, $o->getExpires());
-        $this->assertNotEquals(-1, $c->getExpires());
-        $o->setExpires($t);
-        $this->assertEquals($t, $o->getExpires());
-        $this->assertNotEquals($t, $c->getExpires());
-        $this->assertEquals(
-            sprintf(
-                "this=expires; expires=%s; ", 
-                date_create("@$t")
-                       ->setTimezone(new DateTimezone("UTC"))
-                       ->format("D, d M Y H:i:s \\G\\M\\T")
-            ), 
-            $o->toString()
-        );
-    }
-
-    function testMaxAge() {
-        $c = new http\Cookie("this=max-age; max-age=12345");
-        $this->assertEquals("max-age", $c->getCookie("this"));
-        $this->assertEquals(12345, $c->getMaxAge());
-        $o = clone $c;
-        $t = 54321;
-        $o->setMaxAge();
-        $this->assertEquals(-1, $o->getMaxAge());
-        $this->assertNotEquals(-1, $c->getMaxAge());
-        $o->setMaxAge($t);
-        $this->assertEquals($t, $o->getMaxAge());
-        $this->assertNotEquals($t, $c->getMaxAge());
-        $this->assertEquals(
-               "this=max-age; max-age=$t; ",
-            $o->toString()
-        );
-    }
-
-    function testPath() {
-        $c = new http\Cookie("this=has a path; path=/down; ");
-        $this->assertEquals("has a path", $c->getCookie("this"));
-        $this->assertEquals("this=has%20a%20path; path=/down; ", (string)$c);
-        $this->assertEquals("/down", $c->getPath());
-        $o = clone $c;
-        $p = "/up";
-        $o->setPath();
-        $this->assertEquals(null, $o->getPath());
-        $this->assertNotEquals(null, $c->getPath());
-        $o->setPath($p);
-        $this->assertEquals($p, $o->getPath());
-        $this->assertNotEquals($p, $c->getPath());
-        $this->assertEquals("this=has%20a%20path; path=$p; ", $o->toString());
-    }
-
-    function testDomain() {
-        $c = new http\Cookie("this=has a domain; domain=.example.com; ");
-        $this->assertEquals("has a domain", $c->getCookie("this"));
-        $this->assertEquals("this=has%20a%20domain; domain=.example.com; ", (string)$c);
-        $this->assertEquals(".example.com", $c->getDomain());
-        $o = clone $c;
-        $d = "sub.example.com";
-        $o->setDomain();
-        $this->assertEquals(null, $o->getDomain());
-        $this->assertNotEquals(null, $c->getDomain());
-        $o->setDomain($d);
-        $this->assertEquals($d, $o->getDomain());
-        $this->assertNotEquals($d, $c->getDomain());
-        $this->assertEquals("this=has%20a%20domain; domain=$d; ", $o->toString());
-    }
-
-    function testFlags() {
-        $c = new http\Cookie("icanhas=flags; secure; httpOnly");
-        $this->assertEquals(http\Cookie::SECURE, $c->getFlags() & http\Cookie::SECURE, "secure");
-        $this->assertEquals(http\Cookie::HTTPONLY, $c->getFlags() & http\Cookie::HTTPONLY, "httpOnly");
-        $c->setFlags($c->getFlags() ^ http\Cookie::SECURE);
-        $this->assertEquals(0, $c->getFlags() & http\Cookie::SECURE, "secure");
-        $this->assertEquals(http\Cookie::HTTPONLY, $c->getFlags() & http\Cookie::HTTPONLY, "httpOnly");
-        $c->setFlags($c->getFlags() ^ http\Cookie::HTTPONLY);
-        $this->assertEquals(0, $c->getFlags() & http\Cookie::SECURE, "secure");
-        $this->assertEquals(0, $c->getFlags() & http\Cookie::HTTPONLY, "httpOnly");
-        $this->assertEquals("icanhas=flags; ", $c->toString());
-        $c->setFlags(http\Cookie::SECURE|http\Cookie::HTTPONLY);
-        $this->assertEquals("icanhas=flags; secure; httpOnly; ", $c->toString());
-    }
-
-    function testExtras() {
-        $c = new http\Cookie("c1=v1; e0=1; e2=2; c2=v2", 0, array("e0", "e1", "e2"));
-        $this->assertEquals(array("c1"=>"v1", "c2"=>"v2"), $c->getCookies());
-        $this->assertEquals(array("e0"=>"1", "e2"=>"2"), $c->getExtras());
-        $c->addExtra("e1", 1);
-        $c->setExtra("e0");
-        $c->setExtra("e3", 123);
-        $this->assertEquals(123, $c->getExtra("e3"));
-        $c->setExtra("e3");
-        $this->assertEquals(array("e2"=>"2", "e1"=>1), $c->getExtras());
-        $this->assertEquals("c1=v1; c2=v2; e2=2; e1=1; ", $c->toString());
-        $c->addExtras(array("e3"=>3, "e4"=>4));
-        $this->assertEquals(array("e2"=>"2", "e1"=>1, "e3"=>3, "e4"=>4), $c->getExtras());
-        $this->assertEquals("c1=v1; c2=v2; e2=2; e1=1; e3=3; e4=4; ", $c->toString());
-        $c->setExtras(array("e"=>"x"));
-        $this->assertEquals(array("e"=>"x"), $c->getExtras());
-        $this->assertEquals("c1=v1; c2=v2; e=x; ", $c->toString());
-        $c->setExtras();
-        $this->assertEquals(array(), $c->getExtras());
-        $this->assertEquals("c1=v1; c2=v2; ", $c->toString());
-    }
-
-    function testCookies() {
-        $c = new http\Cookie("e0=1; c1=v1; e2=2; c2=v2", 0, array("c0", "c1", "c2"));
-        $this->assertEquals(array("c1"=>"v1", "c2"=>"v2"), $c->getExtras());
-        $this->assertEquals(array("e0"=>"1", "e2"=>"2"), $c->getCookies());
-        $c->addCookie("e1", 1);
-        $c->setCookie("e0");
-        $c->setCookie("e3", 123);
-        $this->assertEquals(123, $c->getCookie("e3"));
-        $c->setCookie("e3");
-        $this->assertEquals(array("e2"=>"2", "e1"=>1), $c->getCookies());
-        $this->assertEquals("e2=2; e1=1; c1=v1; c2=v2; ", $c->toString());
-        $c->addCookies(array("e3"=>3, "e4"=>4));
-        $this->assertEquals(array("e2"=>"2", "e1"=>1, "e3"=>3, "e4"=>4), $c->getCookies());
-        $this->assertEquals("e2=2; e1=1; e3=3; e4=4; c1=v1; c2=v2; ", $c->toString());
-        $c->setCookies(array("e"=>"x"));
-        $this->assertEquals(array("e"=>"x"), $c->getCookies());
-        $this->assertEquals("e=x; c1=v1; c2=v2; ", $c->toString());
-        $c->setCookies();
-        $this->assertEquals(array(), $c->getCookies());
-        $this->assertEquals("c1=v1; c2=v2; ", $c->toString());
-    }
-}
diff --git a/phpunit/EncodingTest.php b/phpunit/EncodingTest.php
deleted file mode 100644 (file)
index 4642613..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-
-class EncodingStreamTest extends PHPUnit_Framework_TestCase {
-    function testChunkStatic() {
-        $file = file(__FILE__);
-        $cenc = array_reduce(
-            $file,
-            function($data, $line) {
-                return $data . sprintf("%lx\r\n%s\r\n", strlen($line), $line);
-            }
-        ) . "0\r\n";
-
-        $this->assertEquals(implode("", $file), http\Encoding\Stream\Dechunk::decode($cenc));
-    }
-
-    function testChunkNoteEncoded() {
-        $s = "this is apparently not encodded\n";
-        $this->assertEquals($s, @http\Encoding\Stream\Dechunk::decode($s));
-    }
-
-    function testChunkNotEncodedNotice() {
-           error_reporting(E_ALL);
-        $this->setExpectedException("PHPUnit_Framework_Error_Notice", 
-            "Data does not seem to be chunked encoded");
-        $s = "this is apparently not encodded\n";
-        $this->assertEquals($s, http\Encoding\Stream\Dechunk::decode($s));
-    }
-
-    function testChunkNotEncodedFail() {
-        $s = "3\nis \nbetter than\n1\n";
-        $this->assertNotEquals($s, @http\Encoding\Stream\Dechunk::decode($s));
-    }
-
-    function testChunkNotEncodedWarning1() {
-        $this->setExpectedException("PHPUnit_Framework_Error_Warning", 
-            "Expected LF at pos 8 of 20 but got 0x74");
-        $s = "3\nis \nbetter than\n1\n";
-        http\Encoding\Stream\Dechunk::decode($s);
-    }
-
-    function testChunkNotEncodedWarning2() {
-        $this->setExpectedException("PHPUnit_Framework_Error_Warning", 
-            "Expected CRLF at pos 10 of 24 but got 0x74 0x74");
-        $s = "3\r\nis \r\nbetter than\r\n1\r\n";
-        http\Encoding\Stream\Dechunk::decode($s);
-    }
-
-    function testChunkNotEncodedWarning3() {
-        $this->setExpectedException("PHPUnit_Framework_Error_Warning", 
-            "Expected chunk size at pos 6 of 27 but got trash");
-        $s = "3\nis \nreally better than\n1\n";
-        http\Encoding\Stream\Dechunk::decode($s);
-    }
-
-    function testChunkFlush() {
-        $dech = new http\Encoding\Stream\Dechunk(http\Encoding\Stream::FLUSH_FULL);
-        $file = file(__FILE__);
-        $data = "";
-        foreach ($file as $i => $line) {
-            $dech = clone $dech;
-            if ($i % 2) {
-                $data .= $dech->update(sprintf("%lx\r\n%s\r\n", strlen($line), $line));
-            } else {
-                $data .= $dech->update(sprintf("%lx\r\n", strlen($line)));
-                $data .= $dech->flush();
-                $data .= $dech->update($line);
-                $data .= $dech->flush();
-                $data .= $dech->update("\r\n");
-            }
-            $dech->flush();
-            $this->assertFalse($dech->done());
-        }
-        $data .= $dech->update("0\r\n");
-        $this->assertTrue($dech->done());
-        $data .= $dech->finish();
-        $this->assertEquals(implode("", $file), $data);
-    }
-
-    function testZlibStatic() {
-        $file = file_get_contents(__FILE__);
-        $this->assertEquals($file, 
-            http\Encoding\Stream\Inflate::decode(
-                http\Encoding\Stream\Deflate::encode(
-                    $file, http\Encoding\Stream\Deflate::TYPE_GZIP
-                )
-            )
-        );
-        $this->assertEquals($file, 
-            http\Encoding\Stream\Inflate::decode(
-                http\Encoding\Stream\Deflate::encode(
-                    $file, http\Encoding\Stream\Deflate::TYPE_ZLIB
-                )
-            )
-        );
-        $this->assertEquals($file, 
-            http\Encoding\Stream\Inflate::decode(
-                http\Encoding\Stream\Deflate::encode(
-                    $file, http\Encoding\Stream\Deflate::TYPE_RAW
-                )
-            )
-        );
-    }
-
-    function testZlibAutoFlush() {
-        $defl = new http\Encoding\Stream\Deflate(http\Encoding\Stream::FLUSH_FULL);
-        $infl = new http\Encoding\Stream\Inflate;
-
-        for ($f = fopen(__FILE__, "rb"); !feof($f); $data = fread($f, 0x100)) {
-            $infl = clone $infl;
-            $defl = clone $defl;
-            if (isset($data)) {
-                $this->assertEquals($data, $infl->update($defl->update($data)));
-            }
-        }
-
-        echo $infl->update($defl->finish());
-        echo $infl->finish();
-    }
-
-    function testZlibWithoutFlush() {
-        $defl = new http\Encoding\Stream\Deflate;
-        $infl = new http\Encoding\Stream\Inflate;
-        $file = file(__FILE__);
-        $data = "";
-        foreach ($file as $line) {
-            $infl = clone $infl;
-            $defl = clone $defl;
-            if (strlen($temp = $defl->update($line))) {
-                foreach(str_split($temp) as $byte) {
-                    $data .= $infl->update($byte);
-                }
-            }
-        }
-        if (strlen($temp = $defl->finish())) {
-            $data .= $infl->update($temp);
-        }
-        $data .= $infl->finish();
-        $this->assertEquals(implode("", $file), $data);
-    }
-
-    function testZlibWithExplicitFlush() {
-        $defl = new http\Encoding\Stream\Deflate;
-        $infl = new http\Encoding\Stream\Inflate;
-        $file = file(__FILE__);
-        $data = "";
-        foreach ($file as $line) {
-               $data .= $infl->flush();
-            if (strlen($temp = $defl->update($line))) {
-                $data .= $infl->update($temp);
-                       $data .= $infl->flush();
-            }
-            if (strlen($temp = $defl->flush())) {
-                $data .= $infl->update($temp);
-                       $data .= $infl->flush();
-            }
-            $this->assertTrue($defl->done());
-        }
-        if (strlen($temp = $defl->finish())) {
-            $data .= $infl->update($temp);
-        }
-        $this->assertTrue($defl->done());
-        $data .= $infl->finish();
-        $this->assertTrue($infl->done());
-        $this->assertEquals(implode("", $file), $data);
-    }
-
-    function testInflateError() {
-        $this->setExpectedException("PHPUnit_Framework_Error_Warning",
-            "Could not inflate data: data error");
-        http\Encoding\Stream\Inflate::decode("if this goes through, something's pretty wrong");
-    }
-}
diff --git a/phpunit/MessageBodyTest.php b/phpunit/MessageBodyTest.php
deleted file mode 100644 (file)
index 3aaf3eb..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-
-class MessageBodyTest extends PHPUnit_Framework_TestCase {
-    protected $file, $temp;
-
-    function setUp() {
-        $this->file = new http\Message\Body(fopen(__FILE__, "r"));
-        $this->temp = new http\Message\Body();
-    }
-
-    function testStat() {
-        $this->assertEquals(filesize(__FILE__), $this->file->stat("size"));
-        $this->assertEquals(filemtime(__FILE__), $this->file->stat("mtime"));
-        $this->assertEquals(fileatime(__FILE__), $this->file->stat("atime"));
-        $this->assertEquals(filectime(__FILE__), $this->file->stat("ctime"));
-        $this->assertEquals(
-            (object) array(
-                "size" => 0,
-                "mtime" => 0,
-                "atime" => 0,
-                "ctime" => 0,
-            ),
-            $this->temp->stat()
-        );
-    }
-
-    function testAppendError() {
-       $this->setExpectedException("http\Exception\RuntimeException");
-        $this->file->append("nope");
-    }
-    function testAppend() {
-        $this->temp->append("yes");
-    }
-
-    function testAddForm() {
-        $this->temp->addForm(
-            array(
-                "foo" => "bar",
-                "more" => array(
-                    "bah", "baz", "fuz"
-                ),
-            ),
-            array(
-                array(
-                    "file" => __FILE__,
-                    "name" => "upload",
-                    "type" => "text/plain",
-                )
-            )
-        );
-
-        $file = str_replace("%", "%c", file_get_contents(__FILE__));
-        $this->assertStringMatchesFormat(
-            "--%x.%x\r\n".
-            "Content-Disposition: form-data; name=\"foo\"\r\n".
-            "\r\n".
-            "bar\r\n".
-            "--%x.%x\r\n".
-            "Content-Disposition: form-data; name=\"more[0]\"\r\n".
-            "\r\n".
-            "bah\r\n".
-            "--%x.%x\r\n".
-            "Content-Disposition: form-data; name=\"more[1]\"\r\n".
-            "\r\n".
-            "baz\r\n".
-            "--%x.%x\r\n".
-            "Content-Disposition: form-data; name=\"more[2]\"\r\n".
-            "\r\n".
-            "fuz\r\n".
-            "--%x.%x\r\n".
-            "Content-Disposition: form-data; name=\"upload\"; filename=\"MessageBodyTest.php\"\r\n".
-            "Content-Transfer-Encoding: binary\r\n".
-            "Content-Type: text/plain\r\n".
-            "\r\n".
-            "{$file}\r\n".
-            "--%x.%x--\r\n".
-            "",
-            str_replace("\r", "", $this->temp) // phpunit replaces \r\n with \n
-        );
-    }
-
-    function testAddPart() {
-        $this->temp->addPart(new http\Message("This: is a header\n\nand this is the data\n"));
-        $this->assertStringMatchesFormat(
-            "--%x.%x\r\n".
-            "This: is a header\r\n".
-            "Content-Length: 21\r\n".
-            "\r\n".
-            "and this is the data\n\r\n".
-            "--%x.%x--\r\n".
-            "",
-            str_replace("\r", "", $this->temp)
-        );
-    }
-
-    function testEtag() {
-        $s = stat(__FILE__);
-        $this->assertEquals(
-            sprintf(
-                "%lx-%lx-%lx", 
-                $s["ino"],$s["mtime"],$s["size"]
-            ),
-            $this->file->etag()
-        );
-        $this->assertEquals(crc32(""), $this->temp->etag());
-    }
-
-    function testToStream() {
-        $this->file->toStream($f = fopen("php://temp", "w")); 
-        fseek($f, 0, SEEK_SET);
-        $this->assertEquals(
-            file_get_contents(__FILE__), 
-            fread($f, filesize(__FILE__))
-        );
-    }
-
-    function testToCallback() {
-        $s = "";
-        $this->file->toCallback(
-            function($body, $string) use (&$s) { $s.=$string; }
-        );
-        $this->assertEquals($s, (string) $this->file);
-    }
-
-    function testClone() {
-        $this->assertEquals((string) $this->file, (string) clone $this->file);
-    }
-    
-    function testGetResource() {
-       $stream = $this->file->getResource();
-       $this->assertTrue(is_resource($stream));
-       $stat = fstat($stream);
-       $this->assertEquals(filesize(__FILE__), $stat["size"]);
-    }
-}
diff --git a/phpunit/ParamsTest.php b/phpunit/ParamsTest.php
deleted file mode 100644 (file)
index 71bfcf4..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-<?php
-
-class ParamsTest extends PHPUnit_Framework_TestCase {
-    function testDefault() {
-        $s = "foo, bar;arg=0;bla, gotit=0;now";
-        $this->runAssertions(
-            new http\Params($s),
-            str_replace(" ", "", $s)
-        );
-    }
-
-    function testCustom() {
-        $s = "foo bar.arg:0.bla gotit:0.now";
-        $this->runAssertions(
-            new http\Params($s, " ", ".", ":"),
-            $s
-        );
-    }
-
-    function testQuoted() {
-        $p = new http\Params("multipart/form-data; boundary=\"--123\"");
-        $this->assertEquals(
-            array(
-                "multipart/form-data" => array(
-                    "value" => true,
-                    "arguments" => array(
-                        "boundary" => "--123"
-                    )
-                )
-            ),
-            $p->params
-        );
-        $this->assertEquals("multipart/form-data;boundary=--123", (string) $p);
-    }
-
-    function testEscaped() {
-        $p = new http\Params("form-data; name=\"upload\"; filename=\"trick\\\"\0\\\"ed\"");
-        $this->assertEquals(
-            array(
-                "form-data" => array(
-                    "value" => true,
-                    "arguments" => array(
-                        "name" => "upload",
-                        "filename" => "trick\"\0\"ed"
-                    )
-                )
-            ),
-            $p->params
-        );
-        $this->assertEquals("form-data;name=upload;filename=\"trick\\\"\\0\\\"ed\"", (string) $p);
-    }
-
-    function testUrlencoded() {
-        $s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1";
-        $p = new http\Params($s, "&", "", "=", http\Params::PARSE_URLENCODED);
-        $this->assertEquals(
-            array(
-                "foo" => array(
-                    "value" => "b\"r",
-                    "arguments" => array(),
-                ),
-                "bar" => array(
-                    "value" => "b\"z",
-                    "arguments" => array(),
-                ),
-                "a[][]" => array(
-                    "value" => "1",
-                    "arguments" => array(),
-                ),
-            ),
-            $p->params
-        );
-        $this->assertEquals("foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1", (string) $p);
-    }
-
-    function testQuery() {
-        $s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1";
-        $p = new http\Params($s, "&", "", "=", http\Params::PARSE_QUERY);
-        $this->assertEquals(
-            array(
-                "foo" => array(
-                    "value" => "b\"r",
-                    "arguments" => array(),
-                ),
-                "bar" => array(
-                    "value" => "b\"z",
-                    "arguments" => array(),
-                ),
-                "a" => array(
-                    "value" => array(
-                        array("1")
-                    ),
-                    "arguments" => array(),
-                ),
-            ),
-            $p->params
-        );
-        $this->assertEquals("foo=b%22r&bar=b%22z&a%5B0%5D%5B0%5D=1", (string) $p);
-    }
-
-
-    function testEmpty() {
-        $p = new http\Params(NULL);
-        $this->assertEquals(array(), $p->params);
-    }
-
-    function testErrorOfToArrayWithArgs() {
-        $this->setExpectedException("PHPUnit_Framework_Error_Warning");
-        $p = new http\Params();
-        $p->toArray("dummy");
-    }
-
-    function testIntegerKeys() {
-        $p = new http\Params("0=nothing;1=yes");
-        $this->assertEquals(array("0" => array("value" => "nothing", "arguments" => array(1=>"yes"))), $p->params);
-        $this->assertEquals("0=nothing;1=yes", $p->toString());
-    }
-
-    function testBoolParamArguments() {
-        $p = new http\Params;
-        $container = array("value" => false, "arguments" => array("wrong" => false, "correct" => true));
-        $p["container"] = $container;
-        $this->assertEquals("container=0;wrong=0;correct", $p->toString());
-        $this->assertEquals(array("container" => $container), $p->toArray());
-    }
-
-    function testNoArgsForParam() {
-        $p = new http\Params;
-        $p["param"] = true;
-        $this->assertEquals("param", $p->toString());
-        $p["param"] = false;
-        $this->assertEquals("param=0", $p->toString());
-    }
-
-    protected function runAssertions($p, $s) {
-        $this->assertCount(3, $p->params);
-        $this->assertArrayHasKey("foo", $p->params);
-        $this->assertArrayHasKey("bar", $p->params);
-        $this->assertArrayHasKEy("gotit", $p->params);
-
-        $this->assertTrue($p["foo"]["value"]);
-        $this->assertTrue($p["bar"]["value"]);
-        $this->assertEmpty($p["gotit"]["value"]);
-
-        $this->assertEmpty($p["foo"]["arguments"]);
-        $this->assertCount(2, $p["bar"]["arguments"]);
-        $this->assertCount(1, $p["gotit"]["arguments"]);
-
-        $this->assertEmpty($p["bar"]["arguments"]["arg"]);
-        $this->assertTrue($p["bar"]["arguments"]["bla"]);
-        $this->assertTrue($p["gotit"]["arguments"]["now"]);
-
-        $this->assertEquals($s, (string) $p);
-
-        $comp = array (
-            'foo' => 
-            array (
-                'value' => true,
-                'arguments' => 
-                array (
-                ),
-            ),
-            'bar' => 
-            array (
-                'value' => true,
-                'arguments' => 
-                array (
-                    'arg' => '0',
-                    'bla' => true,
-                ),
-            ),
-            'gotit' => 
-            array (
-                'value' => '0',
-                'arguments' => 
-                array (
-                    'now' => true,
-                ),
-            ),
-        );
-
-        $this->assertEquals($comp, $p->params);
-        $a = new http\Params($p->params);
-        $this->assertEquals($comp, $a->toArray());
-       }
-}
diff --git a/phpunit/QueryStringTest.php b/phpunit/QueryStringTest.php
deleted file mode 100644 (file)
index fb2eb47..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-class QueryStringTest extends PHPUnit_Framework_TestCase {
-    protected $q;
-    protected $s = "a=b&r[]=0&r[]=1&r[]=2&rr[][]=00&rr[][]=01&1=2";
-    protected $e = "a=b&r%5B0%5D=0&r%5B1%5D=1&r%5B2%5D=2&rr%5B0%5D%5B0%5D=00&rr%5B0%5D%5B1%5D=01&1=2";
-
-    function setUp() {
-        $this->q = new http\QueryString($this->s);
-    }
-
-    function testSimple() {
-        $this->assertEquals($this->e, (string) $this->q);
-        $this->assertEquals($this->e, $this->q->get());
-    }
-
-    function testGetDefval() {
-        $this->assertEquals("nonexistant", $this->q->get("unknown", "s", "nonexistant"));
-        $this->assertEquals(null, $this->q->get("unknown"));
-    }
-
-    function testGetA() {
-        $this->assertEquals("b", $this->q->get("a"));
-        $this->assertEquals(0, $this->q->get("a", "i"));
-        $this->assertEquals(array("b"), $this->q->get("a", "a"));
-        $this->assertEquals((object)array("scalar" => "b"), $this->q->get("a", "o"));
-    }
-
-    function testGetR() {
-        $this->assertEquals(array(0,1,2), $this->q->get("r"));
-    }
-
-    function testGetRR() {
-        $this->assertEquals(array(array("00","01")), $this->q->get("rr"));
-    }
-
-    function testGet1() {
-        $this->assertEquals(2, $this->q->get(1));
-        $this->assertEquals("2", $this->q->get(1, "s"));
-        $this->assertEquals(2.0, $this->q->get(1, "f"));
-        $this->assertTrue($this->q->get(1, "b"));
-    }
-
-    function testDelA() {
-        $this->assertEquals("b", $this->q->get("a", http\QueryString::TYPE_STRING, null, true));
-        $this->assertEquals(null, $this->q->get("a"));
-    }
-
-    function testDelAll() {
-        $this->q->set(array("a" => null, "r" => null, "rr" => null, 1 => null));
-        $this->assertEquals("", $this->q->toString());
-    }
-
-    function testQSO() {
-        $this->assertEquals($this->e, (string) new http\QueryString($this->q));
-        $this->assertEquals(http_build_query(array("e"=>$this->q->toArray())), (string) new http\QueryString(array("e" => $this->q)));
-    }
-
-    function testIterator() {
-        $this->assertEquals($this->q->toArray(), iterator_to_array($this->q));
-    }
-
-    function testSerialize() {
-        $this->assertEquals($this->e, (string) unserialize(serialize($this->q)));
-    }
-}
diff --git a/phpunit/UrlTest.php b/phpunit/UrlTest.php
deleted file mode 100644 (file)
index dcf3b4f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-
-class UrlTest extends PHPUnit_Framework_TestCase {
-       protected $url; 
-       function setUp() {
-               $this->url = "http://user:pass@www.example.com:8080/path/file.ext".
-                       "?foo=bar&more[]=1&more[]=2#hash";
-    }
-
-       function testStandard() {
-               $this->assertEquals($this->url, (string) new http\Url($this->url));
-               
-               $url = new http\Url($this->url, 
-                       array("path" => "changed", "query" => "foo=&added=this"), 
-                       http\Url::JOIN_PATH |
-                       http\Url::JOIN_QUERY |
-                       http\Url::STRIP_AUTH |
-                       http\Url::STRIP_FRAGMENT
-               );
-
-               $this->assertEquals("http", $url->scheme);
-               $this->assertEmpty($url->user);
-               $this->assertEmpty($url->pass);
-               $this->assertEquals("www.example.com", $url->host);
-               $this->assertEquals(8080, $url->port);
-               $this->assertEquals("/path/changed", $url->path);
-               $this->assertEquals("more%5B0%5D=1&more%5B1%5D=2&added=this", $url->query);
-        $this->assertEmpty($url->fragment);
-    }
-
-    function testMod() {
-        $tmp = new http\Url($this->url);
-        $mod = $tmp->mod(array("query" => "set=1"), http\Url::REPLACE);
-        $this->assertNotEquals($tmp->toArray(), $mod->toArray());
-        $this->assertEquals("set=1", $mod->query);
-        $this->assertEquals("new_fragment", $tmp->mod("#new_fragment")->fragment);
-    }
-
-    function testStrings() {
-        $url = new http\Url($this->url);
-        $this->assertEquals((string) $url, (string) new http\Url((string) $url));
-    }
-
-    function testArrays() {
-        $url = new http\Url($this->url);
-               $url2 = new http\Url($url->toArray());
-        $this->assertEquals($url->toArray(), $url2->toArray());
-    }
-}
index ac0bff336d4e9b39f6ed3a5cd4fe9a9f1142e19f..9f9c95e9ed1aa723fe3b41c717e0850b9715f10c 100644 (file)
@@ -1,8 +1,9 @@
 --TEST--
 Bug #66388 (Crash on POST with Content-Length:0 and untouched body)
 --SKIPIF--
-<?php php
+<?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index 44ff3d1b92e4ab0f13dc520b3865d18df223bc84..89d4d658b8a58ee2d5cfcf94cf72ca4b8c319bbe 100644 (file)
@@ -3,6 +3,7 @@ client observer
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index b09c299764ed21be9210fd61a5c31d526d4a1857..62d0bca64be7eee3e5522918605ecdac601797ca 100644 (file)
@@ -3,6 +3,7 @@ client once & wait
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index 22ad9feb221d54b0db4016bd0aafebaffe07c641..1342efaadd61601e07e08675015b532032f94b06 100644 (file)
@@ -3,6 +3,7 @@ client reset
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index 36a3f0a4e73a125641d98d7730f0327deb5e2981..4576f16d0868785d328dd3cb8fac30dd8ca6557d 100644 (file)
@@ -3,6 +3,7 @@ client response callback
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index 762e044b5f213864f1ec60cf6d3f0e90d471f988..7b3986e583a2703f38a6153099d4091aab9cd5f0 100644 (file)
@@ -3,6 +3,7 @@ client response callback + dequeue
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index 8421b51e7678dc7c66e637e2a7c6de7f63cc9992..74cdbcd9d06f677797338ab422a324bbd1679510 100644 (file)
@@ -3,6 +3,7 @@ client response callback + requeue
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index d7fe35822517fed372a1a254fdcfcbd79389db91..31584d30c548e36372ef2695ec01c9607a90f6a8 100644 (file)
@@ -3,6 +3,7 @@ client features
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
index 937045d061e2246f69d27b0f8dc791791e262ce6..e1553d65449240ec83a1d70875b4023c4881af5c 100644 (file)
@@ -3,6 +3,7 @@ client static cookies
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
@@ -32,16 +33,4 @@ foreach (http\Client::getAvailableDrivers() as $driver) {
 Done
 --EXPECTREGEX--
 Test
-(?:string\(46\) "Array
-\(
-    \[test\] \=\> bar
-    \[foo\] \=\> test
-\)
-"
-string\(46\) "Array
-\(
-    \[test\] \=\> test
-    \[foo\] \=\> bar
-\)
-"
-)+Done
+(?:string\(46\) "Array\n\(\n    \[test\] \=\> bar\n    \[foo\] \=\> test\n\)\n"\nstring\(46\) "Array\n\(\n    \[test\] \=\> test\n    \[foo\] \=\> bar\n\)\n"\n)+Done
index 7563a7760246250be341a47de3c248e6c74e9d81..803403f4686366fb78fc83728b07f39cdcb908a6 100644 (file)
@@ -8,29 +8,32 @@ include "skipif.inc";
 <?php
 echo "Test\n";
 
-$request = new http\Client\Request("POST", "http://dev.iworks.at/ext-http/.print_request.php");
-$request->getBody()->addForm(null, array("file"=>__FILE__, "name"=>"upload", "type"=>"text/plain"));
-
-foreach (http\Client::getAvailableDrivers() as $driver) {
-       $client = new http\Client($driver);
-       $client->enqueue($request)->send();
-       var_dump($client->getResponse()->getBody()->toString());
-}
-?>
-Done
---EXPECTREGEX--
-Test
-(?:string\(\d+\) "Array
+$RE =
+'/(Array
 \(
     \[upload\] \=\> Array
         \(
             \[name\] \=\> client010\.php
             \[type\] \=\> text\/plain
-            \[tmp_name\] \=\> .*
+            \[tmp_name\] \=\> .+
             \[error\] \=\> 0
             \[size\] \=\> \d+
         \)
 
 \)
-"
-)+Done
+)+/';
+$request = new http\Client\Request("POST", "http://dev.iworks.at/ext-http/.print_request.php");
+$request->getBody()->addForm(null, array("file"=>__FILE__, "name"=>"upload", "type"=>"text/plain"));
+
+foreach (http\Client::getAvailableDrivers() as $driver) {
+       $client = new http\Client($driver);
+       $client->enqueue($request)->send();
+       if (!preg_match($RE, $s = $client->getResponse()->getBody()->toString())) {
+               echo($s);
+       }
+}
+?>
+Done
+--EXPECT--
+Test
+Done
\ No newline at end of file
index 188b1782afd73dde8f2ef6630e9c13a7a56b0329..17c60ed61ec869b6b4bf8544e0e78f6e04c24b1a 100644 (file)
@@ -3,6 +3,7 @@ client history
 --SKIPIF--
 <?php 
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php 
@@ -40,12 +41,12 @@ X-Original-Content-Length: 6
 
 foobar
 HTTP/1.1 200 OK
+Vary: %s
+Content-Type: text/html
 Date: %s
 Server: %s
-Vary: %s
+X-Original-Transfer-Encoding: chunked
 Content-Length: 19
-Content-Type: text/html
-X-Original-Content-Length: 19
 
 string(6) "foobar"
 
@@ -59,12 +60,12 @@ X-Original-Content-Length: 6
 
 foobar
 HTTP/1.1 200 OK
+Vary: %s
+Content-Type: text/html
 Date: %s
 Server: %s
-Vary: %s
+X-Original-Transfer-Encoding: chunked
 Content-Length: 19
-Content-Type: text/html
-X-Original-Content-Length: 19
 
 string(6) "foobar"
 
@@ -78,12 +79,12 @@ X-Original-Content-Length: 6
 
 foobar
 HTTP/1.1 200 OK
+Vary: %s
+Content-Type: text/html
 Date: %s
 Server: %s
-Vary: %s
+X-Original-Transfer-Encoding: chunked
 Content-Length: 19
-Content-Type: text/html
-X-Original-Content-Length: 19
 
 string(6) "foobar"
 
index 71e5081a5f938220b3f7639ef9bd08702b756125..ad6c2eb15f0d477cddc9e7712b6dd18999233176 100644 (file)
@@ -3,6 +3,7 @@ client ssl
 --SKIPIF--
 <?php 
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php 
index 0de05476db8cff1b2b0fe90f349f1189845053e1..00bae4e0de5c7f7419b42c46c1240d5a1d33d9e4 100644 (file)
@@ -3,6 +3,7 @@ client observers
 --SKIPIF--
 <?php 
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php 
@@ -50,7 +51,7 @@ $client->attach(
                )
 );
 
-$client->enqueue(new http\Client\Request("GET", "http://dev.iworks.at/ext-http/"))->send();
+$client->enqueue(new http\Client\Request("GET", "http://www.example.com/"))->send();
 var_dump(1 === preg_match("/(\.-)+/", $client->pi));
 var_dump(3 === count($client->getObservers()));
 $client->detach($o1);
diff --git a/tests/client014.phpt b/tests/client014.phpt
new file mode 100644 (file)
index 0000000..d0ff471
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+reset content length when resetting body
+--SKIPIF--
+<?php 
+include "skipif.inc";
+?>
+--FILE--
+<?php 
+
+echo "Test\n";
+
+$client = new http\Client;
+$request = new http\Client\Request("PUT", "put.php");
+$request->setBody(new http\Message\Body(fopen(__FILE__, "r")));
+$client->enqueue($request);
+var_dump($request->getHeader("Content-Length"));
+$request->setBody(new http\Message\Body);
+$client->requeue($request);
+var_dump($request->getHeader("Content-Length"));
+?>
+===DONE===
+--EXPECTF--
+Test
+int(379)
+bool(false)
+===DONE===
index 2f2529123950a8ef2fbb4c196e03faf834a8d919..270512b358ab926c94fd2edda42d17390aa6048a 100644 (file)
@@ -3,6 +3,7 @@ client response cookie
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
@@ -20,26 +21,4 @@ foreach (http\Client::getAvailableDrivers() as $driver) {
 Done
 --EXPECTREGEX--
 Test
-(?:array\(7\) \{
-  \["cookies"\]\=\>
-  array\(2\) \{
-    \["foo"\]\=\>
-    string\(3\) "bar"
-    \["bar"\]\=\>
-    string\(3\) "foo"
-  \}
-  \["extras"\]\=\>
-  array\(0\) \{
-  \}
-  \["flags"\]\=\>
-  int\(0\)
-  \["expires"\]\=\>
-  int\(\-1\)
-  \["max\-age"\]\=\>
-  int\(\-1\)
-  \["path"\]\=\>
-  string\(0\) ""
-  \["domain"\]\=\>
-  string\(0\) ""
-\}
-)+Done
+(?:array\(7\) \{\n  \["cookies"\]\=\>\n  array\(2\) \{\n    \["foo"\]\=\>\n    string\(3\) "bar"\n    \["bar"\]\=\>\n    string\(3\) "foo"\n  \}\n  \["extras"\]\=\>\n  array\(0\) \{\n  \}\n  \["flags"\]\=\>\n  int\(0\)\n  \["expires"\]\=\>\n  int\(\-1\)\n  \["max\-age"\]\=\>\n  int\(\-1\)\n  \["path"\]\=\>\n  string\(0\) ""\n  \["domain"\]\=\>\n  string\(0\) ""\n\}\n)+Done
index 3a0c50a2c281d1e1c71a817cbdbafa56635a89a0..2379cc7e6ddf3e7717e373a1b365b9253dc79630 100644 (file)
@@ -3,6 +3,7 @@ client response cookies
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
@@ -20,44 +21,4 @@ foreach (http\Client::getAvailableDrivers() as $driver) {
 Done
 --EXPECTREGEX--
 Test
-(?:array\(7\) \{
-  \["cookies"\]\=\>
-  array\(1\) \{
-    \["temp"\]\=\>
-    string\(1[23]\) "\d+\.\d+"
-  \}
-  \["extras"\]\=\>
-  array\(0\) \{
-  \}
-  \["flags"\]\=\>
-  int\(0\)
-  \["expires"\]\=\>
-  int\(\-1\)
-  \["max\-age"\]\=\>
-  int\(\-1\)
-  \["path"\]\=\>
-  string\(0\) ""
-  \["domain"\]\=\>
-  string\(0\) ""
-\}
-array\(7\) \{
-  \["cookies"\]\=\>
-  array\(1\) \{
-    \["perm"\]\=\>
-    string\(1[23]\) "\d+\.\d+"
-  \}
-  \["extras"\]\=\>
-  array\(0\) \{
-  \}
-  \["flags"\]\=\>
-  int\(0\)
-  \["expires"\]\=\>
-  int\(\d+\)
-  \["max\-age"\]\=\>
-  int\(\-1\)
-  \["path"\]\=\>
-  string\(0\) ""
-  \["domain"\]\=\>
-  string\(0\) ""
-\}
-)+Done
+(?:array\(7\) \{\n  \["cookies"\]\=\>\n  array\(1\) \{\n    \["temp"\]\=\>\n    string\(1\d\) "\d+\.\d+"\n  \}\n  \["extras"\]\=\>\n  array\(0\) \{\n  \}\n  \["flags"\]\=\>\n  int\(0\)\n  \["expires"\]\=\>\n  int\(\-1\)\n  \["max\-age"\]\=\>\n  int\(\-1\)\n  \["path"\]\=\>\n  string\(0\) ""\n  \["domain"\]\=\>\n  string\(0\) ""\n\}\narray\(7\) \{\n  \["cookies"\]\=\>\n  array\(1\) \{\n    \["perm"\]\=\>\n    string\(1\d\) "\d+\.\d+"\n  \}\n  \["extras"\]\=\>\n  array\(0\) \{\n  \}\n  \["flags"\]\=\>\n  int\(0\)\n  \["expires"\]\=\>\n  int\(\d+\)\n  \["max\-age"\]\=\>\n  int\(\-1\)\n  \["path"\]\=\>\n  string\(0\) ""\n  \["domain"\]\=\>\n  string\(0\) ""\n\}\n)+Done
index 20dcef2270a75ba1aa155209bdd3c853fe6cb1a8..8ab936d059b94b94b4302fe77faeada7c90676f4 100644 (file)
@@ -3,6 +3,7 @@ client response transfer info
 --SKIPIF--
 <?php
 include "skipif.inc";
+skip_online_test();
 ?>
 --FILE--
 <?php
diff --git a/tests/cookie001.phpt b/tests/cookie001.phpt
new file mode 100644 (file)
index 0000000..3adf8d7
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+cookies empty state
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie;
+$o = clone $c;
+$a = array(
+       "cookies" => array(),
+       "extras" => array(),
+       "flags" => 0,
+       "expires" => -1,
+       "path" => "",
+       "domain" => "",
+       "max-age" => -1,
+);
+var_dump($a == $c->toArray());
+var_dump($a == $o->toArray());
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/cookie002.phpt b/tests/cookie002.phpt
new file mode 100644 (file)
index 0000000..98c883b
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+cookies expire as date
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+echo "Test\n";
+
+$d = new DateTime;
+$c = new http\Cookie(array("expires" => $d->format(DateTime::RFC1123)));
+var_dump($d->format("U") == $c->getExpires());
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/cookie003.phpt b/tests/cookie003.phpt
new file mode 100644 (file)
index 0000000..c546f52
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+cookies numeric keys
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie("1=%20; 2=%22; 3=%5D", 0, array(2));
+var_dump("1=%20; 3=%5D; 2=%22; " === (string) $c);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/cookie004.phpt b/tests/cookie004.phpt
new file mode 100644 (file)
index 0000000..1c4ead4
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+cookies raw
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie("1=%20; 2=%22; e3=%5D", http\Cookie::PARSE_RAW, array(2));
+var_dump("1=%2520; e3=%255D; 2=%2522; " === (string) $c);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/cookie005.phpt b/tests/cookie005.phpt
new file mode 100644 (file)
index 0000000..f210402
--- /dev/null
@@ -0,0 +1,75 @@
+--TEST--
+cookies simple data
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$orig = new http\Cookie("key=value");
+$copy = clone $orig;
+$same = new http\Cookie($copy);
+$even = new http\Cookie($same->toArray());
+foreach (array($orig, $copy) as $c) {
+       var_dump($c->getCookie("key"));
+       var_dump($c->getExpires());
+       var_dump($c->getMaxAge());
+       var_dump($c->getFlags());
+       var_dump($c->getPath());
+       var_dump($c->getDomain());
+       var_dump($c->getExtras());
+       var_dump($c->getCookies());
+       var_dump($c->toString());
+       var_dump(
+               array (
+                       "cookies" => 
+                               array (
+                                       "key" => "value",
+                               ),
+                       "extras" => 
+                               array (
+                               ),
+                       "flags" => 0,
+                       "expires" => -1,
+                       "path" => "",
+                       "domain" => "",
+                       "max-age" => -1,
+               ) == $c->toArray()
+       );
+}
+
+?>
+DONE
+--EXPECT--
+Test
+string(5) "value"
+int(-1)
+int(-1)
+int(0)
+NULL
+NULL
+array(0) {
+}
+array(1) {
+  ["key"]=>
+  string(5) "value"
+}
+string(11) "key=value; "
+bool(true)
+string(5) "value"
+int(-1)
+int(-1)
+int(0)
+NULL
+NULL
+array(0) {
+}
+array(1) {
+  ["key"]=>
+  string(5) "value"
+}
+string(11) "key=value; "
+bool(true)
+DONE
diff --git a/tests/cookie006.phpt b/tests/cookie006.phpt
new file mode 100644 (file)
index 0000000..d52f982
--- /dev/null
@@ -0,0 +1,47 @@
+--TEST--
+cookies expire
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie("this=expires; expires=Tue, 24 Jan 2012 10:35:32 +0100");
+var_dump($c->getCookie("this"));
+var_dump($c->getExpires());
+
+$o = clone $c;
+$t = time();
+
+$o->setExpires();
+var_dump(-1 === $o->getExpires());
+var_dump(-1 != $c->getExpires());
+
+$o->setExpires($t);
+var_dump($t === $o->getExpires());
+var_dump($t != $c->getExpires());
+var_dump(
+       sprintf(
+               "this=expires; expires=%s; ", 
+               date_create("@$t")
+                       ->setTimezone(new DateTimezone("UTC"))
+                       ->format("D, d M Y H:i:s \\G\\M\\T")
+       ) === $o->toString()
+);
+
+?>
+DONE
+--EXPECT--
+Test
+string(7) "expires"
+int(1327397732)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/cookie007.phpt b/tests/cookie007.phpt
new file mode 100644 (file)
index 0000000..1a7a4c3
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+cookies max-age
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie("this=max-age; max-age=12345");
+var_dump($c->getCookie("this"));
+var_dump($c->getMaxAge());
+$o = clone $c;
+$t = 54321;
+$o->setMaxAge();
+var_dump($o->getMaxAge());
+var_dump(-1 != $c->getMaxAge());
+$o->setMaxAge($t);
+var_dump($o->getMaxAge());
+var_dump($t != $c->getMaxAge());
+var_dump($o->toString());
+
+?>
+DONE
+--EXPECT--
+Test
+string(7) "max-age"
+int(12345)
+int(-1)
+bool(true)
+int(54321)
+bool(true)
+string(29) "this=max-age; max-age=54321; "
+DONE
diff --git a/tests/cookie008.phpt b/tests/cookie008.phpt
new file mode 100644 (file)
index 0000000..5ec43dc
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+cookies path
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie("this=has a path; path=/down; ");
+var_dump($c->getCookie("this"));
+var_dump((string)$c);
+var_dump($c->getPath());
+$o = clone $c;
+$p = "/up";
+$o->setPath();
+var_dump($o->getPath());
+var_dump($c->getPath());
+$o->setPath($p);
+var_dump($o->getPath());
+var_dump($c->getPath());
+var_dump($o->toString());
+
+?>
+DONE
+--EXPECT--
+Test
+string(10) "has a path"
+string(33) "this=has%20a%20path; path=/down; "
+string(5) "/down"
+NULL
+string(5) "/down"
+string(3) "/up"
+string(5) "/down"
+string(31) "this=has%20a%20path; path=/up; "
+DONE
diff --git a/tests/cookie009.phpt b/tests/cookie009.phpt
new file mode 100644 (file)
index 0000000..55aac94
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+cookies domain
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie("this=has a domain; domain=.example.com; ");
+var_dump($c->getCookie("this"));
+var_dump((string)$c);
+var_dump($c->getDomain());
+$o = clone $c;
+$d = "sub.example.com";
+$o->setDomain();
+var_dump($o->getDomain());
+var_dump($c->getDomain());
+$o->setDomain($d);
+var_dump($o->getDomain());
+var_dump($c->getDomain());
+var_dump($o->toString());
+
+?>
+DONE
+--EXPECT--
+Test
+string(12) "has a domain"
+string(44) "this=has%20a%20domain; domain=.example.com; "
+string(12) ".example.com"
+NULL
+string(12) ".example.com"
+string(15) "sub.example.com"
+string(12) ".example.com"
+string(47) "this=has%20a%20domain; domain=sub.example.com; "
+DONE
diff --git a/tests/cookie010.phpt b/tests/cookie010.phpt
new file mode 100644 (file)
index 0000000..34d10f2
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+cookies flags
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$c = new http\Cookie("icanhas=flags; secure; httpOnly");
+var_dump(http\Cookie::SECURE === ($c->getFlags() & http\Cookie::SECURE));
+var_dump(http\Cookie::HTTPONLY === ($c->getFlags() & http\Cookie::HTTPONLY));
+$c->setFlags($c->getFlags() ^ http\Cookie::SECURE);
+var_dump(!($c->getFlags() & http\Cookie::SECURE));
+var_dump(http\Cookie::HTTPONLY === ($c->getFlags() & http\Cookie::HTTPONLY));
+$c->setFlags($c->getFlags() ^ http\Cookie::HTTPONLY);
+var_dump(!($c->getFlags() & http\Cookie::SECURE));
+var_dump(!($c->getFlags() & http\Cookie::HTTPONLY));
+var_dump("icanhas=flags; " === $c->toString());
+$c->setFlags(http\Cookie::SECURE|http\Cookie::HTTPONLY);
+var_dump("icanhas=flags; secure; httpOnly; " === $c->toString());
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/cookie011.phpt b/tests/cookie011.phpt
new file mode 100644 (file)
index 0000000..03700ea
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+cookies extras
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+$c = new http\Cookie("c1=v1; e0=1; e2=2; c2=v2", 0, array("e0", "e1", "e2"));
+var_dump(array("c1"=>"v1", "c2"=>"v2") === $c->getCookies());
+var_dump(array("e0"=>"1", "e2"=>"2") === $c->getExtras());
+$c->addExtra("e1", 1);
+$c->setExtra("e0");
+$c->setExtra("e3", 123);
+var_dump("123" === $c->getExtra("e3"));
+$c->setExtra("e3");
+var_dump(array("e2"=>"2", "e1"=>"1") === $c->getExtras());
+var_dump("c1=v1; c2=v2; e2=2; e1=1; " === $c->toString());
+$c->addExtras(array("e3"=>3, "e4"=>4));
+var_dump(array("e2"=>"2", "e1"=>"1", "e3"=>"3", "e4"=>"4") === $c->getExtras());
+var_dump("c1=v1; c2=v2; e2=2; e1=1; e3=3; e4=4; " === $c->toString());
+$c->setExtras(array("e"=>"x"));
+var_dump(array("e"=>"x") === $c->getExtras());
+var_dump("c1=v1; c2=v2; e=x; " === $c->toString());
+$c->setExtras();
+var_dump(array() === $c->getExtras());
+var_dump("c1=v1; c2=v2; " === $c->toString());
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/cookie012.phpt b/tests/cookie012.phpt
new file mode 100644 (file)
index 0000000..a3898c7
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+cookies cookies
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+$c = new http\Cookie("e0=1; c1=v1; e2=2; c2=v2", 0, array("c0", "c1", "c2"));
+var_dump(array("c1"=>"v1", "c2"=>"v2") === $c->getExtras());
+var_dump(array("e0"=>"1", "e2"=>"2") === $c->getCookies());
+$c->addCookie("e1", 1);
+$c->setCookie("e0");
+$c->setCookie("e3", 123);
+var_dump("123" === $c->getCookie("e3"));
+$c->setCookie("e3");
+var_dump(array("e2"=>"2", "e1"=>"1") === $c->getCookies());
+var_dump("e2=2; e1=1; c1=v1; c2=v2; " === $c->toString());
+$c->addCookies(array("e3"=>3, "e4"=>4));
+var_dump(array("e2"=>"2", "e1"=>"1", "e3"=>"3", "e4"=>"4") === $c->getCookies());
+var_dump("e2=2; e1=1; e3=3; e4=4; c1=v1; c2=v2; " === $c->toString());
+$c->setCookies(array("e"=>"x"));
+var_dump(array("e"=>"x") === $c->getCookies());
+var_dump("e=x; c1=v1; c2=v2; " === $c->toString());
+$c->setCookies();
+var_dump(array() === $c->getCookies());
+var_dump("c1=v1; c2=v2; " === $c->toString());
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/encstream001.phpt b/tests/encstream001.phpt
new file mode 100644 (file)
index 0000000..5dc13d3
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+encoding stream chunked static
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = file(__FILE__);
+$cenc = array_reduce(
+       $file,
+       function($data, $line) {
+               return $data . sprintf("%lx\r\n%s\r\n", strlen($line), $line);
+       }
+) . "0\r\n";
+
+var_dump(implode("", $file) === http\Encoding\Stream\Dechunk::decode($cenc));
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
+
diff --git a/tests/encstream002.phpt b/tests/encstream002.phpt
new file mode 100644 (file)
index 0000000..3be0aca
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+encoding stream chunked not encoded
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$s = "this is apparently not encodded\n";
+var_dump($s === http\Encoding\Stream\Dechunk::decode($s));
+
+?>
+DONE
+--EXPECTF--
+Test
+
+Notice: http\Encoding\Stream\Dechunk::decode(): Data does not seem to be chunked encoded in %s on line %d
+bool(true)
+DONE
diff --git a/tests/encstream003.phpt b/tests/encstream003.phpt
new file mode 100644 (file)
index 0000000..ad8c737
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+encoding stream chunked error
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$s = "3\nis \nbetter than\n1\n";
+var_dump(http\Encoding\Stream\Dechunk::decode($s));
+$s = "3\r\nis \r\nbetter than\r\n1\r\n";
+var_dump(http\Encoding\Stream\Dechunk::decode($s));
+$s = "3\nis \nreally better than\n1\n";
+var_dump(http\Encoding\Stream\Dechunk::decode($s));
+?>
+DONE
+--EXPECTF--
+Test
+
+Warning: http\Encoding\Stream\Dechunk::decode(): Expected LF at pos 8 of 20 but got 0x74 in %s on line %d
+
+Warning: http\Encoding\Stream\Dechunk::decode(): Truncated message: chunk size 190 exceeds remaining data size 11 at pos 9 of 20 in %s on line %d
+string(14) "is ter than
+1
+"
+
+Warning: http\Encoding\Stream\Dechunk::decode(): Expected CRLF at pos 10 of 24 but got 0x74 0x74 in %s on line %d
+
+Warning: http\Encoding\Stream\Dechunk::decode(): Truncated message: chunk size 190 exceeds remaining data size 12 at pos 12 of 24 in %s on line %d
+string(15) "is er than
+1
+"
+
+Warning: http\Encoding\Stream\Dechunk::decode(): Expected chunk size at pos 6 of 27 but got trash in %s on line %d
+bool(false)
+DONE
diff --git a/tests/encstream004.phpt b/tests/encstream004.phpt
new file mode 100644 (file)
index 0000000..eb9da0f
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+encoding stream chunked flush
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$dech = new http\Encoding\Stream\Dechunk(http\Encoding\Stream::FLUSH_FULL);
+$file = file(__FILE__);
+$data = "";
+foreach ($file as $i => $line) {
+       $dech = clone $dech;
+       if ($i % 2) {
+               $data .= $dech->update(sprintf("%lx\r\n%s\r\n", strlen($line), $line));
+       } else {
+               $data .= $dech->update(sprintf("%lx\r\n", strlen($line)));
+               $data .= $dech->flush();
+               $data .= $dech->update($line);
+               $data .= $dech->flush();
+               $data .= $dech->update("\r\n");
+       }
+       $dech->flush();
+       $dech->done() and printf("uh-oh done() reported true!\n");
+}
+$data .= $dech->update("0\r\n");
+var_dump($dech->done());
+$data .= $dech->finish();
+var_dump(implode("", $file) === $data);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/encstream005.phpt b/tests/encstream005.phpt
new file mode 100644 (file)
index 0000000..6455ed4
--- /dev/null
@@ -0,0 +1,41 @@
+--TEST--
+encoding stream zlib static
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = file_get_contents(__FILE__);
+var_dump($file ===
+       http\Encoding\Stream\Inflate::decode(
+               http\Encoding\Stream\Deflate::encode(
+                       $file, http\Encoding\Stream\Deflate::TYPE_GZIP
+               )
+       )
+);
+var_dump($file ===
+       http\Encoding\Stream\Inflate::decode(
+               http\Encoding\Stream\Deflate::encode(
+                       $file, http\Encoding\Stream\Deflate::TYPE_ZLIB
+               )
+       )
+);
+var_dump($file ===
+       http\Encoding\Stream\Inflate::decode(
+               http\Encoding\Stream\Deflate::encode(
+                       $file, http\Encoding\Stream\Deflate::TYPE_RAW
+               )
+       )
+);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/encstream006.phpt b/tests/encstream006.phpt
new file mode 100644 (file)
index 0000000..5430bfa
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+encoding stream zlib auto flush
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$defl = new http\Encoding\Stream\Deflate(http\Encoding\Stream::FLUSH_FULL);
+$infl = new http\Encoding\Stream\Inflate;
+
+for ($f = fopen(__FILE__, "rb"); !feof($f); $data = fread($f, 0x100)) {
+       $infl = clone $infl;
+       $defl = clone $defl;
+       if (isset($data)) {
+               if ($data !== $d=$infl->update($defl->update($data))) {
+                       printf("uh-oh »%s« != »%s«\n", $data, $d);
+               }
+       }
+}
+
+echo $infl->update($defl->finish());
+echo $infl->finish();
+?>
+DONE
+--EXPECT--
+Test
+DONE
diff --git a/tests/encstream007.phpt b/tests/encstream007.phpt
new file mode 100644 (file)
index 0000000..5fdeffe
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+encoding stream zlib without flush
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$defl = new http\Encoding\Stream\Deflate;
+$infl = new http\Encoding\Stream\Inflate;
+$file = file(__FILE__);
+$data = "";
+foreach ($file as $line) {
+       $infl = clone $infl;
+       $defl = clone $defl;
+       if (strlen($temp = $defl->update($line))) {
+               foreach(str_split($temp) as $byte) {
+                       $data .= $infl->update($byte);
+               }
+       }
+}
+if (strlen($temp = $defl->finish())) {
+       $data .= $infl->update($temp);
+}
+$data .= $infl->finish();
+var_dump(implode("", $file) === $data);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/encstream008.phpt b/tests/encstream008.phpt
new file mode 100644 (file)
index 0000000..a46f9f0
--- /dev/null
@@ -0,0 +1,42 @@
+--TEST--
+encoding stream zlib with explicit flush
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$defl = new http\Encoding\Stream\Deflate;
+$infl = new http\Encoding\Stream\Inflate;
+$file = file(__FILE__);
+$data = "";
+foreach ($file as $line) {
+       $data .= $infl->flush();
+       if (strlen($temp = $defl->update($line))) {
+               $data .= $infl->update($temp);
+               $data .= $infl->flush();
+       }
+       if (strlen($temp = $defl->flush())) {
+               $data .= $infl->update($temp);
+               $data .= $infl->flush();
+       }
+       $defl->done() or printf("uh-oh stream's not done yet!\n");
+}
+if (strlen($temp = $defl->finish())) {
+       $data .= $infl->update($temp);
+}
+var_dump($defl->done());
+$data .= $infl->finish();
+var_dump($infl->done());
+var_dump(implode("", $file) === $data);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/encstream009.phpt b/tests/encstream009.phpt
new file mode 100644 (file)
index 0000000..fa51a8a
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+encoding stream zlib error
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+var_dump(http\Encoding\Stream\Inflate::decode("if this goes through, something's pretty wrong"));
+
+?>
+DONE
+--EXPECTF--
+Test
+
+Warning: http\Encoding\Stream\Inflate::decode(): Could not inflate data: data error in %s on line %d
+bool(false)
+DONE
index 3bbf760c7dc77b69ce8212358504ec682f7ac77e..7a02814c27c5b5ea60ecfbeee42ba1c917ecb5da 100644 (file)
@@ -18,7 +18,7 @@ $r->setBody(new http\Message\Body(fopen(__FILE__, "rb")));
 $r->send();
 
 ?>
---EXPECTHEADERS--
-Content-Type: text/plain
+--EXPECTHEADERSF--
+Content-Type: text/plain%s
 --EXPECTF--
 php
index f84c8606aeea76d18921a9fb233db9c99df4584d..deee3f2081b8d397fafb4a6a77259d46fb276862 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-env reponse callback
+env response callback
 --SKIPIF--
 <?php
 include "skipif.inc";
diff --git a/tests/envresponse016.phpt b/tests/envresponse016.phpt
new file mode 100644 (file)
index 0000000..8d48c93
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+env response send failure
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+
+echo "Test\n";
+
+class closer extends php_user_filter {
+       function filter ($in, $out, &$consumed, $closing) {
+               while ($bucket = stream_bucket_make_writeable($in)) {
+                       stream_bucket_append($out, $bucket);
+               }
+               return PSFS_ERR_FATAL;
+       }
+}
+
+stream_filter_register("closer", "closer");
+
+$r = new http\Env\Response;
+$r->getBody()->append(str_repeat("a", 16*1024*4));
+$s = fopen("php://temp", "w");
+stream_filter_append($s, "closer");
+var_dump($r->send($s));
+?>
+DONE
+--EXPECTF--
+Test
+
+Warning: http\Env\Response::send(): Failed to send response body in %s on line %d
+bool(false)
+DONE
index 194f7d78f811928b4440eb55d94320c2835caebe..3997cf88f3fa03670c1eb5938f255988c83b1b7a 100644 (file)
@@ -34,6 +34,6 @@ Array
             [2] => good
         )
 
-    [Content-Type] => text/html
+    [Content-Type] => %s
 )
 Created
index 8511fff1ea12a6e28d5e7b96c4764217da9113c9..08c0f27dabf01059124dd0121acdb494ec93d654 100644 (file)
@@ -1,7 +1,9 @@
 --TEST--
 ranges
 --SKIPIF--
-<? include "skipif.php";
+<?php
+include "skipif.inc";
+?>
 --GET--
 a=b
 --ENV--
index b3a2a5347fbe4207dc2425604e578a8e88805e96..c1e1e44c897a92587198dcab8fd16bb1bf156703 100644 (file)
@@ -11,7 +11,12 @@ version_compare(PHP_VERSION, "5.4.0", ">=") or die("skip PHP>=5.4 required");
 $body = new http\Message\Body;
 $body->append("Hello, my old fellow.");
 foreach (hash_algos() as $algo) {
-       if ($algo == "gost-crypto") continue;
+    switch ($algo) {
+    case "gost-crypto":
+    case "fnv1a32":
+    case "fnv1a64":
+        continue 2;
+    }
     ini_set("http.etag.mode", $algo);
     printf("%10s: %s\n", 
         $algo, 
index 26c6bc16790d2d6a0ff25faee56301284a8e7745..93f128a4362325d5ea479763c606c7712c996904 100644 (file)
@@ -1,7 +1,9 @@
 --TEST--
 multipart message
 --SKIPIF--
-<?php include "skipif.inc"; ?>
+<?php
+include "skipif.inc";
+?>
 --FILE--
 <?php
 $m = new http\Message(fopen(__DIR__."/data/message_r_multipart_put.txt","rb"));
index 914a8dab0a29c28161c1899bfc4366f9359a6380..e1c9aa976be766b78e49b4d957ac8efc63f7df61 100644 (file)
@@ -2,7 +2,8 @@
 message reversal
 --SKIPIF--
 <?php
-include "skip.inc";
+include "skipif.inc";
+?>
 --FILE--
 <?php
 
diff --git a/tests/messagebody001.phpt b/tests/messagebody001.phpt
new file mode 100644 (file)
index 0000000..6f1e10a
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+message body stat
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = new http\Message\Body(fopen(__FILE__, "r"));
+$temp = new http\Message\Body();
+var_dump(filesize(__FILE__) === $file->stat("size"));
+var_dump(filemtime(__FILE__) === $file->stat("mtime"));
+var_dump(fileatime(__FILE__) === $file->stat("atime"));
+var_dump(filectime(__FILE__) === $file->stat("ctime"));
+var_dump(
+       (object) array(
+               "size" => 0,
+               "mtime" => 0,
+               "atime" => 0,
+               "ctime" => 0,
+       ) == $temp->stat()
+);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/messagebody002.phpt b/tests/messagebody002.phpt
new file mode 100644 (file)
index 0000000..fe28e28
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+message body append
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$temp = new http\Message\Body();
+$temp->append("yes");
+
+var_dump((string) $temp);
+
+?>
+DONE
+--EXPECT--
+Test
+string(3) "yes"
+DONE
diff --git a/tests/messagebody003.phpt b/tests/messagebody003.phpt
new file mode 100644 (file)
index 0000000..7b79e6a
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+message body append error
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = new http\Message\Body(fopen(__FILE__, "r"));
+try {
+       $file->append("nope");
+} catch (Exception $e) {
+       echo $e, "\n";
+}
+
+?>
+DONE
+--EXPECTF--
+Test
+exception 'http\Exception\RuntimeException' with message 'http\Message\Body::append(): Failed to append 4 bytes to body; wrote 0' in %s:%d
+Stack trace:
+#0 %s(%d): http\Message\Body->append('nope')
+#1 {main}
+DONE
diff --git a/tests/messagebody004.phpt b/tests/messagebody004.phpt
new file mode 100644 (file)
index 0000000..64254d4
--- /dev/null
@@ -0,0 +1,81 @@
+--TEST--
+message body add form
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$temp = new http\Message\Body;
+$temp->addForm(
+       array(
+               "foo" => "bar",
+               "more" => array(
+                       "bah", "baz", "fuz"
+               ),
+       ),
+       array(
+               array(
+                       "file" => __FILE__,
+                       "name" => "upload",
+                       "type" => "text/plain",
+               )
+       )
+);
+
+echo $temp;
+
+?>
+DONE
+--EXPECTF--
+Test
+--%x.%x
+Content-Disposition: form-data; name="foo"
+
+bar
+--%x.%x
+Content-Disposition: form-data; name="more[0]"
+
+bah
+--%x.%x
+Content-Disposition: form-data; name="more[1]"
+
+baz
+--%x.%x
+Content-Disposition: form-data; name="more[2]"
+
+fuz
+--%x.%x
+Content-Disposition: form-data; name="upload"; filename="%s"
+Content-Transfer-Encoding: binary
+Content-Type: text/plain
+
+<?php
+echo "Test\n";
+
+$temp = new http\Message\Body;
+$temp->addForm(
+       array(
+               "foo" => "bar",
+               "more" => array(
+                       "bah", "baz", "fuz"
+               ),
+       ),
+       array(
+               array(
+                       "file" => __FILE__,
+                       "name" => "upload",
+                       "type" => "text/plain",
+               )
+       )
+);
+
+echo $temp;
+
+?>
+DONE
+
+--%x.%x--
+DONE
diff --git a/tests/messagebody005.phpt b/tests/messagebody005.phpt
new file mode 100644 (file)
index 0000000..72f402d
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+message body add part
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$temp = new http\Message\Body;
+var_dump($temp->getBoundary());
+$temp->addPart(new http\Message("This: is a header\n\nand this is the data\n"));
+var_dump($temp->getBoundary());
+echo $temp;
+
+?>
+DONE
+--EXPECTF--
+Test
+NULL
+string(%d) "%x.%x"
+--%x.%x
+This: is a header
+Content-Length: 21
+
+and this is the data
+
+--%x.%x--
+DONE
diff --git a/tests/messagebody006.phpt b/tests/messagebody006.phpt
new file mode 100644 (file)
index 0000000..a02057e
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+message body etag
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--INI--
+http.etag.mode = crc32b
+--FILE--
+<?php
+echo "Test\n";
+
+$file = new http\Message\Body(fopen(__FILE__, "r"));
+$temp = new http\Message\Body;
+$s = stat(__FILE__);
+var_dump(
+       sprintf(
+               "%lx-%lx-%lx", 
+               $s["ino"],$s["mtime"],$s["size"]
+       ) === $file->etag()
+);
+var_dump($temp->etag());
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+string(8) "00000000"
+DONE
diff --git a/tests/messagebody007.phpt b/tests/messagebody007.phpt
new file mode 100644 (file)
index 0000000..dc010da
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+message body to stream
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = new http\Message\Body(fopen(__FILE__,"r"));
+$file->toStream($f = fopen("php://temp", "w")); 
+fseek($f, 0, SEEK_SET);
+var_dump(file_get_contents(__FILE__) === stream_get_contents($f));
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/messagebody008.phpt b/tests/messagebody008.phpt
new file mode 100644 (file)
index 0000000..cb9612c
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+message body to callback
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = new http\Message\Body(fopen(__FILE__,"r"));
+$s = "";
+$file->toCallback(
+       function($body, $string) use (&$s) { $s.=$string; }
+);
+var_dump($s === (string) $file);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/messagebody009.phpt b/tests/messagebody009.phpt
new file mode 100644 (file)
index 0000000..a7a7f43
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+message body clone
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = new http\Message\Body(fopen(__FILE__,"r"));
+var_dump((string) $file === (string) clone $file);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/messagebody010.phpt b/tests/messagebody010.phpt
new file mode 100644 (file)
index 0000000..b50898d
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+message body resource
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$file = new http\Message\Body(fopen(__FILE__,"r"));
+for($i=0;$i<10;++$i) $stream = $file->getResource();
+var_dump(is_resource($stream));
+$stat = fstat($stream);
+var_dump(filesize(__FILE__) === $stat["size"]);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
index ac52bf7a940c049f7555a83f740551a400f73e2b..5b28deed83a041d1c355fd3e5bc658bceb72f643 100644 (file)
@@ -3,11 +3,12 @@ header params
 --SKIPIF--
 <?php
 include "skipif.inc";
+?>
 --FILE--
 <?php
 echo "Test\n";
 
-$ct = new http\Params("text/html; charset=utf-8");
+$ct = new http\Params("text/html; charset=utf-8", ",", ";", "=", 0);
 
 var_dump(
        isset($ct["text/html"]),
@@ -25,9 +26,10 @@ var_dump(
        $ct["text/json"]["arguments"]["charset"]
 );
 
-var_dump((string) $ct);
+var_dump((string) $ct,$ct);
 
-echo "Done\n";
+?>
+DONE
 --EXPECTF--
 Test
 bool(true)
@@ -37,4 +39,27 @@ bool(false)
 bool(true)
 string(10) "iso-8859-1"
 string(%d) "text/json;charset=iso-8859-1"
-Done
+object(http\Params)#%d (5) {
+  ["params"]=>
+  array(1) {
+    ["text/json"]=>
+    array(2) {
+      ["value"]=>
+      bool(true)
+      ["arguments"]=>
+      array(1) {
+        ["charset"]=>
+        string(10) "iso-8859-1"
+      }
+    }
+  }
+  ["param_sep"]=>
+  string(1) ","
+  ["arg_sep"]=>
+  string(1) ";"
+  ["val_sep"]=>
+  string(1) "="
+  ["flags"]=>
+  int(0)
+}
+DONE
diff --git a/tests/params003.phpt b/tests/params003.phpt
new file mode 100644 (file)
index 0000000..11e2759
--- /dev/null
@@ -0,0 +1,97 @@
+--TEST--
+default params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$s = "foo, bar;arg=0;bla, gotit=0;now";
+$p = new http\Params($s);
+$c = str_replace(" ", "", $s);
+$k = array("foo", "bar", "gotit");
+$a = array("foo"=>"arg", "bar"=>"bla", "gotit"=>"now");
+$r = array (
+       'foo' => 
+       array (
+               'value' => true,
+               'arguments' => 
+               array (
+               ),
+       ),
+       'bar' => 
+       array (
+               'value' => true,
+               'arguments' => 
+               array (
+                       'arg' => '0',
+                       'bla' => true,
+               ),
+       ),
+       'gotit' => 
+       array (
+               'value' => '0',
+               'arguments' => 
+               array (
+                       'now' => true,
+               ),
+       ),
+);
+
+# ---
+
+var_dump(count($p->params));
+
+echo "key exists\n";
+foreach ($k as $key) {
+       var_dump(array_key_exists($key, $p->params));
+}
+
+echo "values\n";
+foreach ($k as $key) {
+       var_dump($p[$key]["value"]);
+}
+
+echo "args\n";
+foreach ($k as $key) {
+       var_dump(count($p[$key]["arguments"]));
+}
+
+echo "arg values\n";
+foreach ($k as $key) {
+       var_dump(@$p[$key]["arguments"][$a[$key]]);
+}
+
+echo "equals\n";
+var_dump($c === (string) $p);
+var_dump($r === $p->params);
+$x = new http\Params($p->params);
+var_dump($r === $x->toArray());
+?>
+DONE
+--EXPECT--
+Test
+int(3)
+key exists
+bool(true)
+bool(true)
+bool(true)
+values
+bool(true)
+bool(true)
+string(1) "0"
+args
+int(0)
+int(2)
+int(1)
+arg values
+NULL
+bool(true)
+bool(true)
+equals
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params004.phpt b/tests/params004.phpt
new file mode 100644 (file)
index 0000000..69075ea
--- /dev/null
@@ -0,0 +1,97 @@
+--TEST--
+custom params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$s = "foo bar.arg:0.bla gotit:0.now";
+$p = new http\Params($s, " ", ".", ":");
+$c = $s;
+$k = array("foo", "bar", "gotit");
+$a = array("foo"=>"arg", "bar"=>"bla", "gotit"=>"now");
+$r = array (
+       'foo' => 
+       array (
+               'value' => true,
+               'arguments' => 
+               array (
+               ),
+       ),
+       'bar' => 
+       array (
+               'value' => true,
+               'arguments' => 
+               array (
+                       'arg' => '0',
+                       'bla' => true,
+               ),
+       ),
+       'gotit' => 
+       array (
+               'value' => '0',
+               'arguments' => 
+               array (
+                       'now' => true,
+               ),
+       ),
+);
+
+# ---
+
+var_dump(count($p->params));
+
+echo "key exists\n";
+foreach ($k as $key) {
+       var_dump(array_key_exists($key, $p->params));
+}
+
+echo "values\n";
+foreach ($k as $key) {
+       var_dump($p[$key]["value"]);
+}
+
+echo "args\n";
+foreach ($k as $key) {
+       var_dump(count($p[$key]["arguments"]));
+}
+
+echo "arg values\n";
+foreach ($k as $key) {
+       var_dump(@$p[$key]["arguments"][$a[$key]]);
+}
+
+echo "equals\n";
+var_dump($c === (string) $p);
+var_dump($r === $p->params);
+$x = new http\Params($p->params);
+var_dump($r === $x->toArray());
+?>
+DONE
+--EXPECT--
+Test
+int(3)
+key exists
+bool(true)
+bool(true)
+bool(true)
+values
+bool(true)
+bool(true)
+string(1) "0"
+args
+int(0)
+int(2)
+int(1)
+arg values
+NULL
+bool(true)
+bool(true)
+equals
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params005.phpt b/tests/params005.phpt
new file mode 100644 (file)
index 0000000..7c64a31
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+quoted params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$p = new http\Params("multipart/form-data; boundary=\"--123\"");
+$c = array(
+       "multipart/form-data" => array(
+               "value" => true,
+               "arguments" => array(
+                       "boundary" => "--123"
+               )
+       )
+);
+var_dump($c === $p->params);
+var_dump("multipart/form-data;boundary=--123" === (string) $p);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params006.phpt b/tests/params006.phpt
new file mode 100644 (file)
index 0000000..f0f0565
--- /dev/null
@@ -0,0 +1,29 @@
+--TEST--
+escaped params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$p = new http\Params("form-data; name=\"upload\"; filename=\"trick\\\"\0\\\"ed\"");
+$c = array(
+       "form-data" => array(
+               "value" => true,
+               "arguments" => array(
+                       "name" => "upload",
+                       "filename" => "trick\"\0\"ed"
+               )
+       )
+);
+var_dump($c === $p->params);
+var_dump("form-data;name=upload;filename=\"trick\\\"\\000\\\"ed\"" === (string) $p);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params007.phpt b/tests/params007.phpt
new file mode 100644 (file)
index 0000000..c56e2fa
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+urlencoded params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1";
+$p = new http\Params($s, "&", "", "=", http\Params::PARSE_URLENCODED);
+$c = array(
+       "foo" => array(
+               "value" => "b\"r",
+               "arguments" => array(),
+       ),
+       "bar" => array(
+               "value" => "b\"z",
+               "arguments" => array(),
+       ),
+       "a[][]" => array(
+               "value" => "1",
+               "arguments" => array(),
+       ),
+);
+var_dump($c === $p->params);
+var_dump("foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1" === (string) $p);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params008.phpt b/tests/params008.phpt
new file mode 100644 (file)
index 0000000..463a96c
--- /dev/null
@@ -0,0 +1,37 @@
+--TEST--
+querystring params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$s = "foo=b%22r&bar=b%22z&a%5B%5D%5B%5D=1";
+$p = new http\Params($s, "&", "", "=", http\Params::PARSE_QUERY);
+$c = array(
+       "foo" => array(
+               "value" => "b\"r",
+               "arguments" => array(),
+       ),
+       "bar" => array(
+               "value" => "b\"z",
+               "arguments" => array(),
+       ),
+       "a" => array(
+               "value" => array(
+                       array("1")
+               ),
+               "arguments" => array(),
+       ),
+);
+var_dump($c === $p->params);
+var_dump("foo=b%22r&bar=b%22z&a%5B0%5D%5B0%5D=1" === (string) $p);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params009.phpt b/tests/params009.phpt
new file mode 100644 (file)
index 0000000..07c58c7
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+empty params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+$p = new http\Params(NULL);
+var_dump(array() === $p->params);
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/params010.phpt b/tests/params010.phpt
new file mode 100644 (file)
index 0000000..ced5e92
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+int key params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$p = new http\Params("0=nothing;1=yes");
+var_dump(array("0" => array("value" => "nothing", "arguments" => array(1=>"yes"))) === $p->params);
+var_dump("0=nothing;1=yes" === $p->toString());
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params011.phpt b/tests/params011.phpt
new file mode 100644 (file)
index 0000000..1f9ecf7
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+bool args params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$p = new http\Params;
+$container = array("value" => false, "arguments" => array("wrong" => false, "correct" => true));
+$p["container"] = $container;
+var_dump("container=0;wrong=0;correct" === $p->toString());
+var_dump(array("container" => $container) === $p->toArray());
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params012.phpt b/tests/params012.phpt
new file mode 100644 (file)
index 0000000..f5a33ca
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+no args params
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$p = new http\Params;
+$p["param"] = true;
+var_dump("param" === $p->toString());
+$p["param"] = false;
+var_dump("param=0" === $p->toString());
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+DONE
diff --git a/tests/params013.phpt b/tests/params013.phpt
new file mode 100644 (file)
index 0000000..d69782a
--- /dev/null
@@ -0,0 +1,79 @@
+--TEST--
+header params rfc5987
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$p = new http\Params("attachment; filename*=IsO-8859-1''d%f6ner.pdf");
+var_dump($p->params, (string) $p);
+$p = new http\Params("bar; title*=iso-8859-1'en'%A3%20rates");
+var_dump($p->params, (string) $p);
+$p = new http\Params("bar; title*=UTF-8''%c2%a3%20and%20%e2%82%ac%20rates");
+var_dump($p->params, (string) $p);
+
+?>
+===DONE===
+--EXPECT--
+Test
+array(1) {
+  ["attachment"]=>
+  array(2) {
+    ["value"]=>
+    bool(true)
+    ["arguments"]=>
+    array(1) {
+      ["*rfc5987*"]=>
+      array(1) {
+        ["filename"]=>
+        array(1) {
+          [""]=>
+          string(10) "döner.pdf"
+        }
+      }
+    }
+  }
+}
+string(42) "attachment;filename*=utf-8''d%C3%B6ner.pdf"
+array(1) {
+  ["bar"]=>
+  array(2) {
+    ["value"]=>
+    bool(true)
+    ["arguments"]=>
+    array(1) {
+      ["*rfc5987*"]=>
+      array(1) {
+        ["title"]=>
+        array(1) {
+          ["en"]=>
+          string(8) "£ rates"
+        }
+      }
+    }
+  }
+}
+string(34) "bar;title*=utf-8'en'%C2%A3%20rates"
+array(1) {
+  ["bar"]=>
+  array(2) {
+    ["value"]=>
+    bool(true)
+    ["arguments"]=>
+    array(1) {
+      ["*rfc5987*"]=>
+      array(1) {
+        ["title"]=>
+        array(1) {
+          [""]=>
+          string(16) "£ and € rates"
+        }
+      }
+    }
+  }
+}
+string(50) "bar;title*=utf-8''%C2%A3%20and%20%E2%82%AC%20rates"
+===DONE===
diff --git a/tests/params014.phpt b/tests/params014.phpt
new file mode 100644 (file)
index 0000000..b61953d
--- /dev/null
@@ -0,0 +1,70 @@
+--TEST--
+header params rfc5987
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+$u = urlencode("ü");
+$s = urlencode("ß");
+$t = "p1*=utf-8''s$u$s,p2*=utf-8''hei$s;a1*=utf-8''a$s;a2*=utf-8''e$s;a3=no,p3=not";
+$p = new http\Params($t);
+var_dump($p->params);
+var_dump((string)$p === $t, (string)$p, $t);
+?>
+===DONE===
+--EXPECT--
+Test
+array(3) {
+  ["p1"]=>
+  array(2) {
+    ["*rfc5987*"]=>
+    array(1) {
+      [""]=>
+      string(5) "süß"
+    }
+    ["arguments"]=>
+    array(0) {
+    }
+  }
+  ["p2"]=>
+  array(2) {
+    ["*rfc5987*"]=>
+    array(1) {
+      [""]=>
+      string(5) "heiß"
+    }
+    ["arguments"]=>
+    array(2) {
+      ["*rfc5987*"]=>
+      array(2) {
+        ["a1"]=>
+        array(1) {
+          [""]=>
+          string(3) "aß"
+        }
+        ["a2"]=>
+        array(1) {
+          [""]=>
+          string(3) "eß"
+        }
+      }
+      ["a3"]=>
+      string(2) "no"
+    }
+  }
+  ["p3"]=>
+  array(2) {
+    ["value"]=>
+    string(3) "not"
+    ["arguments"]=>
+    array(0) {
+    }
+  }
+}
+bool(true)
+string(96) "p1*=utf-8''s%C3%BC%C3%9F,p2*=utf-8''hei%C3%9F;a1*=utf-8''a%C3%9F;a2*=utf-8''e%C3%9F;a3=no,p3=not"
+string(96) "p1*=utf-8''s%C3%BC%C3%9F,p2*=utf-8''hei%C3%9F;a1*=utf-8''a%C3%9F;a2*=utf-8''e%C3%9F;a3=no,p3=not"
+===DONE===
diff --git a/tests/params015.phpt b/tests/params015.phpt
new file mode 100644 (file)
index 0000000..ad3948c
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+header params rfc5987 regression
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+$p = new http\Params(["attachment"=>["filename"=>"foo.bar"]]);
+var_dump($p->params);
+var_dump((string)$p);
+?>
+===DONE===
+--EXPECT--
+Test
+array(1) {
+  ["attachment"]=>
+  array(1) {
+    ["filename"]=>
+    string(7) "foo.bar"
+  }
+}
+string(27) "attachment;filename=foo.bar"
+===DONE===
diff --git a/tests/phpunit.phpt b/tests/phpunit.phpt
deleted file mode 100644 (file)
index 087923e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
---TEST--
-unit tests
---SKIPIF--
-<?php
-include "skipif.inc";
-if (!@include_once "PHPUnit/Autoload.php") die("skip need PHPUnit in include_path");
-?>
---INI--
-date.timezone=Europe/Vienna
---FILE--
-<?php
-require_once "PHPUnit/Autoload.php";
-$c = new PHPUnit_TextUI_Command;
-$c->run(array("--process-isolation", __DIR__."/../phpunit/"));
-?>
---EXPECTF--
-PHPUnit %s by Sebastian Bergmann.
-
-%a
-
-Time: %s, Memory: %s
-
-OK (%d tests, %d assertions)
-
index da17577a3f100126277e44ab80b9974890b496b2..552a71318732377d67714b1e62c1f8f9cb327ffd 100644 (file)
@@ -1,5 +1,9 @@
 --TEST--
 property proxy
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
 --FILE--
 <?php
 
diff --git a/tests/querystring001.phpt b/tests/querystring001.phpt
new file mode 100644 (file)
index 0000000..203be33
--- /dev/null
@@ -0,0 +1,179 @@
+--TEST--
+query string
+--SKIPIF--
+<?php
+include("skipif.inc");
+?>
+--GET--
+str=abc&num=-123&dec=123.123&bool=1&arr[]=1&arr[]=2&ma[l1][l2]=2&ma[l2][l3][l4]=3
+--FILE--
+<?php
+echo "Test\n";
+
+printf("\nGlobal instance:\n");
+$q = http\QueryString::getGlobalInstance();
+printf("%s\n", $q);
+
+printf("\nStandard getters:\n");
+var_dump($q->getString("str"));
+var_dump($q->getInt("num"));
+var_dump($q->getFloat("dec"));
+var_dump($q->getInt("dec"));
+var_dump($q->getFloat("dec"));
+var_dump($q->getBool("bool"));
+var_dump($q->getInt("bool"));
+var_dump($q->getBool("num"));
+var_dump($q->getInt("num"));
+var_dump($q->getArray("arr"));
+var_dump($q->getArray("ma"));
+var_dump($q->getObject("arr"));
+var_dump($q->getObject("ma"));
+
+$s = $q->toString();
+
+printf("\nClone modifications do not alter global instance:\n");
+$q->mod(array("arr" => array(3 => 3)));
+printf("%s\n", $q);
+
+printf("\nClone modifications do not alter standard instance:\n");
+$q2 = new http\QueryString($s);
+$q3 = $q2->mod(array("arr" => array(3 => 3)));
+printf("%s\n%s\n", $q2, $q3);
+#var_dump($q2, $q3);
+
+printf("\nIterator:\n");
+$it = new RecursiveIteratorIterator($q2, RecursiveIteratorIterator::SELF_FIRST);
+foreach ($it as $k => $v) {
+       $i = $it->getDepth()*8;
+       @printf("%{$i}s: %s\n", $k, $v); 
+}
+
+printf("\nReplace a multi dimensional key:\n");
+printf("%s\n", $q2->mod(array("ma" => null))->set(array("ma" => array("l1" => false))));
+
+printf("\nXlate:\n");
+$qu = new http\QueryString("ü=ö");
+printf("utf8:   %s\n", $qu);
+printf("latin1: %s\n", method_exists($qu, "xlate") ? $qu->xlate("utf-8", "latin1") : "%FC=%F6");
+
+printf("\nOffsets:\n");
+var_dump($q2["ma"]);
+$q2["ma"] = array("bye");
+var_dump($q2["ma"]);
+var_dump(isset($q2["ma"]));
+unset($q2["ma"]);
+var_dump(isset($q2["ma"]));
+
+echo "Done\n";
+?>
+--EXPECTF--
+Test
+
+Global instance:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+
+Standard getters:
+string(3) "abc"
+int(-123)
+float(123.123)
+int(123)
+float(123.123)
+bool(true)
+int(1)
+bool(true)
+int(-123)
+array(2) {
+  [0]=>
+  string(1) "1"
+  [1]=>
+  string(1) "2"
+}
+array(2) {
+  ["l1"]=>
+  array(1) {
+    ["l2"]=>
+    string(1) "2"
+  }
+  ["l2"]=>
+  array(1) {
+    ["l3"]=>
+    array(1) {
+      ["l4"]=>
+      string(1) "3"
+    }
+  }
+}
+object(stdClass)#%d (2) {
+  [0]=>
+  string(1) "1"
+  [1]=>
+  string(1) "2"
+}
+object(stdClass)#%d (2) {
+  ["l1"]=>
+  array(1) {
+    ["l2"]=>
+    string(1) "2"
+  }
+  ["l2"]=>
+  array(1) {
+    ["l3"]=>
+    array(1) {
+      ["l4"]=>
+      string(1) "3"
+    }
+  }
+}
+
+Clone modifications do not alter global instance:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+
+Clone modifications do not alter standard instance:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&arr%5B3%5D=3&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
+
+Iterator:
+str: abc
+num: -123
+dec: 123.123
+bool: 1
+arr: Array
+       0: 1
+       1: 2
+ma: Array
+      l1: Array
+              l2: 2
+      l2: Array
+              l3: Array
+                      l4: 3
+
+Replace a multi dimensional key:
+str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D=
+
+Xlate:
+utf8:   %C3%BC=%C3%B6
+latin1: %FC=%F6
+
+Offsets:
+array(2) {
+  ["l1"]=>
+  array(1) {
+    ["l2"]=>
+    string(1) "2"
+  }
+  ["l2"]=>
+  array(1) {
+    ["l3"]=>
+    array(1) {
+      ["l4"]=>
+      string(1) "3"
+    }
+  }
+}
+array(1) {
+  [0]=>
+  string(3) "bye"
+}
+bool(true)
+bool(false)
+Done
diff --git a/tests/querystring002.phpt b/tests/querystring002.phpt
new file mode 100644 (file)
index 0000000..ab82672
--- /dev/null
@@ -0,0 +1,95 @@
+--TEST--
+query string
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$s = "a=b&r[]=0&r[]=1&r[]=2&rr[][]=00&rr[][]=01&1=2";
+$e = "a=b&r%5B0%5D=0&r%5B1%5D=1&r%5B2%5D=2&rr%5B0%5D%5B0%5D=00&rr%5B0%5D%5B1%5D=01&1=2";
+$q = new http\QueryString($s);
+
+var_dump($e === (string) $q);
+var_dump($e === $q->get());
+
+printf("Get defval\n");
+var_dump("nonexistant" === $q->get("unknown", "s", "nonexistant"));
+var_dump(null === $q->get("unknown"));
+
+printf("Get 'a'\n");
+var_dump("b" === $q->get("a"));
+var_dump(0 === $q->get("a", "i"));
+var_dump(array("b") === $q->get("a", "a"));
+var_dump((object)array("scalar" => "b") == $q->get("a", "o"));
+
+printf("Get 'r'\n");
+var_dump(array("0","1","2") === $q->get("r"));
+
+printf("Get 'rr'\n");
+var_dump(array(array("00","01")) === $q->get("rr"));
+
+printf("Get 1\n");
+var_dump(2 == $q->get(1));
+var_dump("2" === $q->get(1, "s"));
+var_dump(2.0 === $q->get(1, "f"));
+var_dump($q->get(1, "b"));
+
+printf("Del 'a'\n");
+var_dump("b" === $q->get("a", http\QueryString::TYPE_STRING, null, true));
+var_dump(null === $q->get("a"));
+
+printf("Del all\n");
+$q->set(array("a" => null, "r" => null, "rr" => null, 1 => null));
+var_dump("" === $q->toString());
+
+$q = new http\QueryString($s);
+
+printf("QSO\n");
+var_dump($e === (string) new http\QueryString($q));
+var_dump(http_build_query(array("e"=>$q->toArray())) === (string) new http\QueryString(array("e" => $q)));
+
+printf("Iterator\n");
+var_dump($q->toArray() === iterator_to_array($q));
+
+printf("Serialize\n");
+var_dump($e === (string) unserialize(serialize($q)));
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+Get defval
+bool(true)
+bool(true)
+Get 'a'
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Get 'r'
+bool(true)
+Get 'rr'
+bool(true)
+Get 1
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+Del 'a'
+bool(true)
+bool(true)
+Del all
+bool(true)
+QSO
+bool(true)
+bool(true)
+Iterator
+bool(true)
+Serialize
+bool(true)
+DONE
diff --git a/tests/querystring_001.phpt b/tests/querystring_001.phpt
deleted file mode 100644 (file)
index 203be33..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
---TEST--
-query string
---SKIPIF--
-<?php
-include("skipif.inc");
-?>
---GET--
-str=abc&num=-123&dec=123.123&bool=1&arr[]=1&arr[]=2&ma[l1][l2]=2&ma[l2][l3][l4]=3
---FILE--
-<?php
-echo "Test\n";
-
-printf("\nGlobal instance:\n");
-$q = http\QueryString::getGlobalInstance();
-printf("%s\n", $q);
-
-printf("\nStandard getters:\n");
-var_dump($q->getString("str"));
-var_dump($q->getInt("num"));
-var_dump($q->getFloat("dec"));
-var_dump($q->getInt("dec"));
-var_dump($q->getFloat("dec"));
-var_dump($q->getBool("bool"));
-var_dump($q->getInt("bool"));
-var_dump($q->getBool("num"));
-var_dump($q->getInt("num"));
-var_dump($q->getArray("arr"));
-var_dump($q->getArray("ma"));
-var_dump($q->getObject("arr"));
-var_dump($q->getObject("ma"));
-
-$s = $q->toString();
-
-printf("\nClone modifications do not alter global instance:\n");
-$q->mod(array("arr" => array(3 => 3)));
-printf("%s\n", $q);
-
-printf("\nClone modifications do not alter standard instance:\n");
-$q2 = new http\QueryString($s);
-$q3 = $q2->mod(array("arr" => array(3 => 3)));
-printf("%s\n%s\n", $q2, $q3);
-#var_dump($q2, $q3);
-
-printf("\nIterator:\n");
-$it = new RecursiveIteratorIterator($q2, RecursiveIteratorIterator::SELF_FIRST);
-foreach ($it as $k => $v) {
-       $i = $it->getDepth()*8;
-       @printf("%{$i}s: %s\n", $k, $v); 
-}
-
-printf("\nReplace a multi dimensional key:\n");
-printf("%s\n", $q2->mod(array("ma" => null))->set(array("ma" => array("l1" => false))));
-
-printf("\nXlate:\n");
-$qu = new http\QueryString("ü=ö");
-printf("utf8:   %s\n", $qu);
-printf("latin1: %s\n", method_exists($qu, "xlate") ? $qu->xlate("utf-8", "latin1") : "%FC=%F6");
-
-printf("\nOffsets:\n");
-var_dump($q2["ma"]);
-$q2["ma"] = array("bye");
-var_dump($q2["ma"]);
-var_dump(isset($q2["ma"]));
-unset($q2["ma"]);
-var_dump(isset($q2["ma"]));
-
-echo "Done\n";
-?>
---EXPECTF--
-Test
-
-Global instance:
-str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
-
-Standard getters:
-string(3) "abc"
-int(-123)
-float(123.123)
-int(123)
-float(123.123)
-bool(true)
-int(1)
-bool(true)
-int(-123)
-array(2) {
-  [0]=>
-  string(1) "1"
-  [1]=>
-  string(1) "2"
-}
-array(2) {
-  ["l1"]=>
-  array(1) {
-    ["l2"]=>
-    string(1) "2"
-  }
-  ["l2"]=>
-  array(1) {
-    ["l3"]=>
-    array(1) {
-      ["l4"]=>
-      string(1) "3"
-    }
-  }
-}
-object(stdClass)#%d (2) {
-  [0]=>
-  string(1) "1"
-  [1]=>
-  string(1) "2"
-}
-object(stdClass)#%d (2) {
-  ["l1"]=>
-  array(1) {
-    ["l2"]=>
-    string(1) "2"
-  }
-  ["l2"]=>
-  array(1) {
-    ["l3"]=>
-    array(1) {
-      ["l4"]=>
-      string(1) "3"
-    }
-  }
-}
-
-Clone modifications do not alter global instance:
-str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
-
-Clone modifications do not alter standard instance:
-str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
-str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&arr%5B3%5D=3&ma%5Bl1%5D%5Bl2%5D=2&ma%5Bl2%5D%5Bl3%5D%5Bl4%5D=3
-
-Iterator:
-str: abc
-num: -123
-dec: 123.123
-bool: 1
-arr: Array
-       0: 1
-       1: 2
-ma: Array
-      l1: Array
-              l2: 2
-      l2: Array
-              l3: Array
-                      l4: 3
-
-Replace a multi dimensional key:
-str=abc&num=-123&dec=123.123&bool=1&arr%5B0%5D=1&arr%5B1%5D=2&ma%5Bl1%5D=
-
-Xlate:
-utf8:   %C3%BC=%C3%B6
-latin1: %FC=%F6
-
-Offsets:
-array(2) {
-  ["l1"]=>
-  array(1) {
-    ["l2"]=>
-    string(1) "2"
-  }
-  ["l2"]=>
-  array(1) {
-    ["l3"]=>
-    array(1) {
-      ["l4"]=>
-      string(1) "3"
-    }
-  }
-}
-array(1) {
-  [0]=>
-  string(3) "bye"
-}
-bool(true)
-bool(false)
-Done
index 0f10264ce5bfe555a9b2d656468159ccda3563a1..28d9a1325ffb9c50a6f8746e611f4eaa12a359b4 100644 (file)
@@ -1,3 +1,15 @@
 <?php
 function _ext($ext) { extension_loaded($ext) or die("skip $ext extension needed\n"); }
 _ext("http");
+
+function skip_online_test($message = "skip test requiring internet connection\n") {
+       if (getenv("SKIP_ONLINE_TESTS")) {
+               die($message);
+       }
+}
+
+function skip_slow_test($message = "skip slow test") {
+       if (getenv("SKIP_SLOW_TESTS")) {
+               die($message);
+       }
+}
index cd792f29688d894a7680498ad88da5534a83941a..5109d3ab60401b3fc1d67bd05cd91d6c079c4809 100644 (file)
@@ -1,7 +1,9 @@
 --TEST--
 url from env
 --SKIPIF--
-<? include "skippif.inc"; ?>
+<?php
+include "skipif.inc";
+?>
 --ENV--
 SERVER_PORT=55555
 HTTP_HOST=example.com
diff --git a/tests/url002.phpt b/tests/url002.phpt
new file mode 100644 (file)
index 0000000..2b31ee9
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+url properties
+--SKIPIF--
+<?php
+include "skipif";
+?>
+--FILE--
+<?php
+echo "Test\n";
+$u = "http://user:pass@www.example.com:8080/path/file.ext".
+                       "?foo=bar&more[]=1&more[]=2#hash";
+
+var_dump($u === (string) new http\Url($u));
+
+$url = new http\Url($u, 
+       array("path" => "changed", "query" => "foo=&added=this"), 
+       http\Url::JOIN_PATH |
+       http\Url::JOIN_QUERY |
+       http\Url::STRIP_AUTH |
+       http\Url::STRIP_FRAGMENT
+);
+
+var_dump($url->scheme);
+var_dump($url->user);
+var_dump($url->pass);
+var_dump($url->host);
+var_dump($url->port);
+var_dump($url->path);
+var_dump($url->query);
+var_dump($url->fragment);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+string(4) "http"
+NULL
+NULL
+string(15) "www.example.com"
+int(8080)
+string(13) "/path/changed"
+string(38) "more%5B0%5D=1&more%5B1%5D=2&added=this"
+NULL
+DONE
diff --git a/tests/url003.phpt b/tests/url003.phpt
new file mode 100644 (file)
index 0000000..b2def7f
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+url modification
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$u = "http://user:pass@www.example.com:8080/path/file.ext".
+                       "?foo=bar&more[]=1&more[]=2#hash";
+
+$tmp = new http\Url($u);
+$mod = $tmp->mod(array("query" => "set=1"), http\Url::REPLACE);
+var_dump($tmp->toArray() != $mod->toArray());
+var_dump("set=1" === $mod->query);
+var_dump("new_fragment" === $tmp->mod("#new_fragment")->fragment);
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+bool(true)
+bool(true)
+DONE
diff --git a/tests/url004.phpt b/tests/url004.phpt
new file mode 100644 (file)
index 0000000..c3055da
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+url as string
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$u = "http://user:pass@www.example.com:8080/path/file.ext".
+                       "?foo=bar&more[]=1&more[]=2#hash";
+
+$url = new http\Url($u);
+var_dump((string) $url == (string) new http\Url((string) $url));
+
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE
diff --git a/tests/url005.phpt b/tests/url005.phpt
new file mode 100644 (file)
index 0000000..f9b6965
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+url as array
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+$u = "http://user:pass@www.example.com:8080/path/file.ext".
+                       "?foo=bar&more[]=1&more[]=2#hash";
+
+$url = new http\Url($u);
+$url2 = new http\Url($url->toArray());
+var_dump($url->toArray() === $url2->toArray());
+?>
+DONE
+--EXPECT--
+Test
+bool(true)
+DONE