--- /dev/null
+package.xml merge=touch
+php_http.h merge=touch
--- /dev/null
+.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
-Copyright (c) 2004-2013, Michael Wallner <mike@iworks.at>.
+Copyright (c) 2004-2014, Michael Wallner <mike@iworks.at>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
* 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
-* revisit error handling
- * ditch http\Object
- * interfacize http\Exception
- * subclass Exceptions
- * zend_throw_exception
\ No newline at end of file
+* CURLOPT_PROXY_HEADER and CURLOPT_HEADEROPT
\ No newline at end of file
Ilia Alshanetsky (ilia at php dot net)
Anatol Belski (ab at php dot net)
Petr Czaderna (petr at hroch dot info)
+ Remi Collet (remi at php dot net)
Benjamin Eberlei (kontakt at beberlei dot de)
David James (james82 at gmail dot com)
Thomas Landro Johnsen (thomas dot l dot johnsen at gmail dot com)
--- /dev/null
+#!/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;
+ }
+}
"php_http_cookie.c php_http_curl.c php_http_client_curl.c " +\r
"php_http_encoding.c php_http_env.c php_http_env_request.c " +\r
"php_http_env_response.c php_http_etag.c php_http_exception.c php_http_filter.c php_http_header_parser.c " +\r
- "php_http_headers.c php_http_info.c php_http_message.c php_http_message_body.c php_http_message_parser.c " +\r
+ "php_http_header.c php_http_info.c php_http_message.c php_http_message_body.c php_http_message_parser.c " +\r
"php_http_misc.c php_http_negotiate.c php_http_object.c php_http_options.c php_http_params.c " +\r
"php_http_querystring.c " +\r
"php_http_strlist.c php_http_url.c php_http_version.c",\r
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], [ ])
}
], [
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])
}
], [
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])
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
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
if test "$PHP_HTTP_LIBEVENT_DIR" = "no"; then
AC_DEFINE([PHP_HTTP_HAVE_EVENT], [0], [ ])
else
- HTTP_HAVE_PHP_EXT([event], [
- AC_MSG_WARN([event support is incompatible with pecl/event; continuing without libevent support])
+ AC_MSG_CHECKING([for event2/event.h])
+ EVENT_DIR=
+ for i in "$PHP_HTTP_LIBEVENT_DIR" /usr/local /usr /opt; do
+ if test -f "$i/include/event.h"; then
+ EVENT_DIR=$i
+ break
+ fi
+ done
+ if test "x$EVENT_DIR" = "x"; then
+ AC_MSG_RESULT([not found])
+ AC_MSG_WARN([continuing without libevent support])
AC_DEFINE([PHP_HTTP_HAVE_EVENT], [0], [ ])
- ], [
- AC_MSG_CHECKING([for event2/event.h])
- EVENT_DIR=
- for i in "$PHP_HTTP_LIBEVENT_DIR" /usr/local /usr /opt; do
- if test -f "$i/include/event.h"; then
- EVENT_DIR=$i
- break
- fi
- done
- if test "x$EVENT_DIR" = "x"; then
- AC_MSG_RESULT([not found])
- AC_MSG_WARN([continuing without libevent support])
- AC_DEFINE([PHP_HTTP_HAVE_EVENT], [0], [ ])
+ else
+ AC_MSG_RESULT([found in $EVENT_DIR])
+
+ AC_MSG_CHECKING([for libevent version, roughly])
+
+ if test -f "$EVENT_DIR/include/event2/event.h"; then
+ 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_MSG_RESULT([found in $EVENT_DIR])
-
- 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}'`"
- AC_DEFINE([PHP_HTTP_HAVE_EVENT2], [1], [ ])
- else
- AC_DEFINE([PHP_HTTP_HAVE_EVENT2], [0], [ ])
- if test -f "$EVENT_DIR/include/evhttp.h" && test -f "$EVENT_DIR/include/evdns.h"; then
- if test -f "$EVENT_DIR/include/evrpc.h"; then
- EVENT_VER="1.4 or greater"
- else
- EVENT_VER="1.2 or greater"
- fi
+ AC_DEFINE([PHP_HTTP_HAVE_EVENT2], [0], [ ])
+ if test -f "$EVENT_DIR/include/evhttp.h" && test -f "$EVENT_DIR/include/evdns.h"; then
+ if test -f "$EVENT_DIR/include/evrpc.h"; then
+ EVENT_VER="1.4 or greater"
else
- EVENT_VER="1.1b or lower"
+ EVENT_VER="1.2 or greater"
fi
+ else
+ EVENT_VER="1.1b or lower"
fi
- AC_DEFINE_UNQUOTED([PHP_HTTP_EVENT_VERSION], ["$EVENT_VER"], [ ])
- AC_MSG_RESULT([$EVENT_VER])
-
- PHP_ADD_INCLUDE($EVENT_DIR/include)
- PHP_ADD_LIBRARY_WITH_PATH(event, $EVENT_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
- AC_DEFINE([PHP_HTTP_HAVE_EVENT], [1], [Have libevent support for cURL])
fi
- ])
+ AC_DEFINE_UNQUOTED([PHP_HTTP_EVENT_VERSION], ["$EVENT_VER"], [ ])
+ AC_MSG_RESULT([$EVENT_VER])
+
+ PHP_ADD_INCLUDE($EVENT_DIR/include)
+ PHP_ADD_LIBRARY_WITH_PATH(event, $EVENT_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
+ AC_DEFINE([PHP_HTTP_HAVE_EVENT], [1], [Have libevent support for cURL])
+ fi
fi
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 ----
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],
'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'
);
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")));
?>
language and charset, as well as a convenient way to send any
arbitrary data with caching and resuming capabilities.
-It provides powerful request functionality, if built with CURL
-support. Parallel requests are available for PHP 5 and greater.
+It provides powerful request functionality with support for
+parallel requests.
+
+Documentation:
+v1: http://php.net/http
+v2: http://devel-m6w6.rhcloud.com/mdref/http
+
+Code Coverage:
+v1: http://dev.iworks.at/ext-http/lcov_html/ext/http/
+v2: http://dev.iworks.at/ext-http/lcov/ext/http/
+
]]></description>
<lead>
<name>Michael Wallner</name>
<email>mike@php.net</email>
<active>yes</active>
</lead>
- <date>2013-08-12</date>
+ <date>2014-08-05</date>
<version>
- <release>2.0.0RC1</release>
- <api>2.0.0</api>
+ <release>2.1.0dev</release>
+ <api>2.1.0</api>
</version>
<stability>
<release>beta</release>
- <api>beta</api>
+ <api>stable</api>
</stability>
<license>BSD, revised</license>
<notes><![CDATA[
-Extended HTTP support. Again. Keep in mind that it's got the major version 2, because it's incompatible with pecl_http v1.
-
-Documentation:
-http://devel-m6w6.rhcloud.com/mdref/http
-
-Code Coverage:
-http://dev.iworks.at/ext-http/lcov/ext/http/
-
+Changes from RC2:
]]></notes>
<contents>
<dir name="/">
<file role="doc" name="LICENSE"/>
<file role="doc" name="CREDITS"/>
+ <file role="doc" name="Exceptions.txt"/>
<file role="doc" name="KnownIssues.txt"/>
<file role="doc" name="ThanksTo.txt"/>
<file role="src" name="config.m4"/>
<file role="test" name="urls.txt"/>
</dir>
<file role="test" name="bug61444.phpt"/>
+ <file role="test" name="bug66388.phpt"/>
<file role="test" name="client001.phpt"/>
<file role="test" name="client002.phpt"/>
<file role="test" name="client003.phpt"/>
<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"/>
<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"/>
<file role="test" name="envresponse012.phpt"/>
<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"/>
<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>
<package>
<name>raphf</name>
<channel>pecl.php.net</channel>
- <min>0.1.0</min>
+ <min>1.0.0</min>
<providesextension>raphf</providesextension>
</package>
<package>
<name>propro</name>
<channel>pecl.php.net</channel>
- <min>0.1.0</min>
+ <min>1.0.0</min>
<providesextension>propro</providesextension>
</package>
</required>
name="with-http-libevent-dir"
prompt="where to find libevent"
default="/usr" />
- <filelist>
- <!-- install as="http.ini" name="docs/http.ini"/>
- <install as="examples/tutorial.txt" name="docs/examples/tutorial.txt"/>
- <install as="pecl/http/.php" name="lib/.php"/ -->
- </filelist>
</extsrcrelease>
<changelog />
</package>
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
#if PHP_HTTP_HAVE_CURL
# include <curl/curl.h>
# if PHP_HTTP_HAVE_EVENT
-# include <event.h>
+# if PHP_HTTP_HAVE_EVENT2
+# include <event2/event.h>
+# include <event2/event_struct.h>
+# else
+# include <event.h>
+# endif
# endif
#endif
#if PHP_HTTP_HAVE_SERF
#endif
#ifdef PHP_HTTP_HAVE_JSON
ZEND_MOD_REQUIRED("json")
-#endif
-#ifdef PHP_HTTP_HAVE_EVENT
- ZEND_MOD_CONFLICTS("event")
#endif
{NULL, NULL, NULL, 0}
};
PHP_RINIT(http),
PHP_RSHUTDOWN(http),
PHP_MINFO(http),
- PHP_HTTP_EXT_VERSION,
+ PHP_PECL_HTTP_VERSION,
STANDARD_MODULE_PROPERTIES
};
php_info_print_table_start();
php_info_print_table_header(2, "HTTP Support", "enabled");
- php_info_print_table_row(2, "Extension Version", PHP_HTTP_EXT_VERSION);
+ php_info_print_table_row(2, "Extension Version", PHP_PECL_HTTP_VERSION);
php_info_print_table_end();
php_info_print_table_start();
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
#ifndef PHP_EXT_HTTP_H
#define PHP_EXT_HTTP_H
-#define PHP_HTTP_EXT_VERSION "2.0.0dev"
+#define PHP_PECL_HTTP_VERSION "2.1.0dev"
extern zend_module_entry http_module_entry;
#define phpext_http_ptr &http_module_entry
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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);
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';
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 */
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)
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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);
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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;
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);
}
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);
}
client->callback.progress.func(client->callback.progress.arg, client, e, progress);
}
+ if (dequeue) {
+ php_http_client_dequeue(client, e->request);
+ }
+
return SUCCESS;
}
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));
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
#if PHP_HTTP_HAVE_CURL
#if PHP_HTTP_HAVE_EVENT
-# include <event.h>
# if !PHP_HTTP_HAVE_EVENT2 && /* just be really sure */ !(LIBEVENT_VERSION_NUMBER >= 0x02000000)
+# include <event.h>
# define event_base_new event_init
# define event_assign(e, b, s, a, cb, d) do {\
event_set(e, s, a, cb, d); \
event_base_set(b, e); \
} while(0)
+# else
+# if PHP_HTTP_HAVE_EVENT2
+# include <event2/event.h>
+# include <event2/event_struct.h>
+# else
+# error "libevent presence is unknown"
+# endif
# endif
# ifndef DBG_EVENTS
# define DBG_EVENTS 0
# 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;
{
php_http_message_body_t *body = ctx;
- if (body) {
- TSRMLS_FETCH_FROM_CTX(body->ts);
- return php_stream_read(php_http_message_body_stream(body), data, len * n);
+ if (body && body->stream_id) {
+ php_stream *s = php_http_message_body_stream(body);
+
+ if (s) {
+ TSRMLS_FETCH_FROM_CTX(body->ts);
+ return php_stream_read(s, data, len * n);
+ } else abort();
}
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;
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)) {
} else {
#if PHP_DEBUG
h->progress.info = data;
+ data[length - 1] = '\0';
#endif
}
if (h->client->callback.progress.func) {
/* 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;
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)
{
{
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;
}
}
}
}
+ } else {
+ php_http_buffer_reset(&curl->options.cookies);
+ if (CURLE_OK != curl_easy_setopt(ch, CURLOPT_COOKIE, NULL)) {
+ return FAILURE;
+ }
}
return SUCCESS;
}
{
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;
}
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 */
/* 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_HTTP_EXT_VERSION " (PHP/" PHP_VERSION ")", 0);
+ ZVAL_STRING(&opt->defval,
+ "PECL_HTTP/" PHP_PECL_HTTP_VERSION " "
+ "PHP/" PHP_VERSION " "
+ "libcurl/" LIBCURL_VERSION
+ , 0);
}
/* resume */
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))) {
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", 0);
+ }
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", 0);
+ }
+ 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))) {
#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
}
}
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);
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;
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;
}
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);
}
}
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))) {
curl_easy_setopt(curl->handle, CURLOPT_READDATA, msg->body);
curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, body_size);
curl_easy_setopt(curl->handle, CURLOPT_POSTFIELDSIZE, body_size);
+ } else {
+ curl_easy_setopt(curl->handle, CURLOPT_IOCTLDATA, NULL);
+ curl_easy_setopt(curl->handle, CURLOPT_READDATA, NULL);
+ curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, 0L);
+ curl_easy_setopt(curl->handle, CURLOPT_POSTFIELDSIZE, 0L);
}
php_http_options_apply(&php_http_curle_options, enqueue->options, curl);
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);
static STATUS php_http_client_curl_exec(php_http_client_t *h)
{
- TSRMLS_FETCH_FROM_CTX(h->ts);
-
#if PHP_HTTP_HAVE_EVENT
php_http_client_curl_t *curl = h->ctx;
+#endif
+ TSRMLS_FETCH_FROM_CTX(h->ts);
+#if PHP_HTTP_HAVE_EVENT
if (curl->useevents) {
php_http_curlm_timeout_callback(CURL_SOCKET_TIMEOUT, /*EV_READ|EV_WRITE*/0, h);
do {
/* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "WinSock error: %d", WSAGetLastError());
#else
- php_error_docref(NULL TSRMLS_CC, E_WARNING, strerror(errno));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
#endif
return FAILURE;
}
PHP_MSHUTDOWN_FUNCTION(http_client_curl)
{
+ php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl"), NULL, 0 TSRMLS_CC);
+ php_persistent_handle_cleanup(ZEND_STRL("http\\Client\\Curl\\Request"), NULL, 0 TSRMLS_CC);
+
php_http_options_dtor(&php_http_curle_options);
+
return SUCCESS;
}
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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);
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);
}
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);
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);
}
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
# elif defined(PHP_HTTP_HAVE_GNUTLS)
# define PHP_HTTP_NEED_GNUTLS_TSL
# include <gcrypt.h>
-# else
-# warning \
- "libcurl was compiled with SSL support, but configure could not determine which" \
- "library was used; thus no SSL crypto locking callbacks will be set, which may " \
- "cause random crashes on SSL requests"
# endif /* PHP_HTTP_HAVE_OPENSSL || PHP_HTTP_HAVE_GNUTLS */
# endif /* PHP_WIN32 */
#endif /* ZTS && PHP_HTTP_HAVE_SSL */
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Data does not seem to be chunked encoded");
memcpy(*decoded, encoded, encoded_len);
*decoded_len = encoded_len;
- decoded[*decoded_len] = '\0';
return encoded + encoded_len;
} else {
efree(*decoded);
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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);
}
}
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)
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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);
+ }
}
}
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
{
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 */
#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) {
}
}
- 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)
}
}
- 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;
}
PHP_HTTP_ENV_RESPONSE_OBJECT_INIT(obj);
- if (obj->body || SUCCESS == php_http_new(NULL, php_http_message_body_class_entry, (php_http_new_t) php_http_message_body_object_new_ex, NULL, (void *) php_http_message_body_init(&obj->message->body, NULL TSRMLS_CC), (void *) &obj->body TSRMLS_CC)) {
- php_http_message_body_append(obj->message->body, ob_str, ob_len);
- RETURN_TRUE;
- }
- RETURN_FALSE;
+ php_http_message_object_init_body_object(obj);
+ php_http_message_body_append(obj->message->body, ob_str, ob_len);
+ RETURN_TRUE;
}
}
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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);
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) parser->stack.elements[parser->stack.top - 1];
}
+
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);
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
#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;
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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) {
}
}
- efree(key);
+ free_alloca(key, free_key);
return ret;
}
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);
}
}
}
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);
}
return SUCCESS;
}
+STATUS php_http_message_object_init_body_object(php_http_message_object_t *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);
+}
+
zend_object_value php_http_message_object_new(zend_class_entry *ce TSRMLS_DC)
{
return php_http_message_object_new_ex(ce, NULL, NULL TSRMLS_CC);
PHP_HTTP_MESSAGE_OBJECT_INIT(obj);
if (!obj->body) {
- php_http_message_body_addref(obj->message->body);
- 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);
+ php_http_message_object_init_body_object(obj);
+
}
if (obj->body) {
RETVAL_OBJVAL(obj->body->zv, 1);
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);
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
void php_http_message_object_prepend(zval *this_ptr, zval *prepend, zend_bool top /* = 1 */ TSRMLS_DC);
void php_http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC);
STATUS php_http_message_object_set_body(php_http_message_object_t *obj, zval *zbody TSRMLS_DC);
+STATUS php_http_message_object_init_body_object(php_http_message_object_t *obj);
zend_object_value php_http_message_object_new(zend_class_entry *ce TSRMLS_DC);
zend_object_value php_http_message_object_new_ex(zend_class_entry *ce, php_http_message_t *msg, php_http_message_object_t **ptr TSRMLS_DC);
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
}
TSRMLS_SET_CTX(body->ts);
+ if (body_ptr) {
+ *body_ptr = body;
+ }
+
return body;
}
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
TSRMLS_SET_CTX(parser->ts);
php_http_header_parser_init(&parser->header TSRMLS_CC);
- zend_stack_init(&parser->stack);
return parser;
}
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);
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) parser->stack.elements[parser->stack.top - 1];
}
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;
}
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);
}
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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;
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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));
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;
}
wasalpha = 0;
}
- }
+ ++i;
+ );
}
return key;
}
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);
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) {
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);
}
}
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
#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;
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;
}
# 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)); \
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)
#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 {
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);
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
} 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;
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);
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);
--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) {
}
}
-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)
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);
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);
}
}
{
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) {
} 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);
}
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)
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) {
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 {
}
}
-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);
}
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);
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)) {
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);
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
} 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;
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
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)
| modification, are permitted provided that the conditions mentioned |
| in the accompanying LICENSE file are met. |
+--------------------------------------------------------------------+
- | Copyright (c) 2004-2013, Michael Wallner <mike@php.net> |
+ | Copyright (c) 2004-2014, Michael Wallner <mike@php.net> |
+--------------------------------------------------------------------+
*/
+++ /dev/null
-<?php
-require_once "PHPUnit/Autoload.php";
-$c = new PHPUnit_TextUI_Command;
-$c->run(array_merge($argv, array(__DIR__."/phpunit/")));
+++ /dev/null
-<?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());
- }
-}
+++ /dev/null
-<?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");
- }
-}
+++ /dev/null
-<?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"]);
- }
-}
+++ /dev/null
-<?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());
- }
-}
+++ /dev/null
-<?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)));
- }
-}
+++ /dev/null
-<?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());
- }
-}
--- /dev/null
+--TEST--
+Bug #66388 (Crash on POST with Content-Length:0 and untouched body)
+--SKIPIF--
+<?php
+include "skipif.inc";
+skip_online_test();
+?>
+--FILE--
+<?php
+
+use http\Client,
+ http\Client\Request;
+
+echo "Test\n";
+
+$client = new Client();
+$request = new Request(
+ 'POST',
+ 'https://api.twitter.com/oauth/request_token',
+ array(
+ 'Content-Length' => 0
+ )
+);
+$client->enqueue($request);
+echo $client->send()->getResponse()->getResponseCode();
+
+?>
+
+===DONE===
+--EXPECT--
+Test
+401
+===DONE===
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
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
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?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
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
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"
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"
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"
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
)
);
-$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);
--- /dev/null
+--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===
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
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
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
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
--SKIPIF--
<?php
include "skipif.inc";
+skip_online_test();
?>
--FILE--
<?php
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
+
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--TEST--
env request body
--SKIPIF--
-<? include "skipif.inc";
+<?php include "skipif.inc"; ?>
--PUT--
Content-Type: skip/me
foo
--FILE--
-<?
+<?php
var_dump((string) \http\Env::getRequestBody());
?>
DONE
--TEST--
env request body
--SKIPIF--
-<? include "skipif.inc";
+<?php include "skipif.inc"; ?>
--PUT--
Content-Type: application/x-www-form-urlencoded
foo=bar&baz=buh
--FILE--
-<?
+<?php
var_dump($_POST);
?>
DONE
--TEST--
env request body
--SKIPIF--
-<? include "skipif.inc";
+<?php include "skipif.inc"; ?>
--PUT--
Content-Type: multipart/form-data;boundary=123
--123
foo=bar&baz=buh
--123--
--FILE--
-<?
+<?php
var_dump($_POST);
var_dump($_FILES);
?>
["type"]=>
string(0) ""
["tmp_name"]=>
- string(14) "%s"
+ string(%d) "%s"
["error"]=>
int(0)
["size"]=>
--TEST--
env request header
--SKIPIF--
-<? include "skipif.inc";
+<?php include "skipif.inc"; ?>
--POST--
a=b
--ENV--
HTTP_HOST=foo.bar
HTTP_ACCEPT=*/*
--FILE--
-<?
+<?php
var_dump(http\Env::getRequestHeader("nono"));
var_dump(http\Env::getRequestHeader("Host"));
var_dump(http\Env::getRequestHeader("content-type"));
-var_dump(http\Env::getRequestHeader());
+$hdr = http\Env::getRequestHeader();
+ksort($hdr);
+var_dump($hdr);
+?>
--EXPECTF--
NULL
string(%d) "foo.bar"
string(%d) "application/x-www-form-urlencoded"
array(4) {
- ["Host"]=>
- string(7) "foo.bar"
["Accept"]=>
string(3) "*/*"
["Content-Length"]=>
string(1) "3"
["Content-Type"]=>
string(33) "application/x-www-form-urlencoded"
+ ["Host"]=>
+ string(7) "foo.bar"
}
$r->send();
?>
---EXPECTHEADERS--
-Content-Type: text/plain
+--EXPECTHEADERSF--
+Content-Type: text/plain%s
--EXPECTF--
php
--TEST--
-env reponse callback
+env response callback
--SKIPIF--
<?php
include "skipif.inc";
--- /dev/null
+--TEST--
+env response send replaced body using multiple ob_start
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+
+$r = new http\Env\Response;
+
+ob_start($r);
+echo "bar";
+ob_end_flush();
+
+$b = $r->getBody();
+$r->setBody(new http\Message\Body);
+
+ob_start($r);
+echo "foo: $b\n";
+ob_end_flush();
+
+$f = fopen("php://memory", "r+");
+
+$r->send($f);
+
+fseek($f, 0, SEEK_SET);
+echo stream_get_contents($f);
+
+?>
+--EXPECT--
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+ETag: "fc8305a1"
+
+foo: bar
--- /dev/null
+--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
[2] => good
)
- [Content-Type] => text/html
+ [Content-Type] => %s
)
Created
--TEST--
ranges
--SKIPIF--
-<? include "skipif.php";
+<?php
+include "skipif.inc";
+?>
--GET--
a=b
--ENV--
$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,
HTTP_X_TEST=test
--COOKIE--
foo=bar
+--INI--
+always_populate_raw_post_data=-1
--FILE--
-<?
+<?php
echo "Test\n";
use http\env\Request as HttpEnvRequest;
echo "stream\n";
var_dump(file_get_contents("php://input"));
-
-echo "Done\n";
+?>
+Done
--EXPECTF--
Test
object(%s)#%d (12) {
--TEST--
multipart message
--SKIPIF--
-<? include "skipif.inc";
+<?php
+include "skipif.inc";
+?>
--FILE--
-<?
+<?php
$m = new http\Message(fopen(__DIR__."/data/message_r_multipart_put.txt","rb"));
if ($m->isMultipart($boundary)) {
var_dump($boundary);
message reversal
--SKIPIF--
<?php
-include "skip.inc";
+include "skipif.inc";
+?>
--FILE--
<?php
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
CUSTOM
-<?
+<?php
$cc = http\Env::negotiate("a, a.b;q=0.9, c.d;q=0, *.* ; q=0.1",
array("a.x", "c.d", "c.e", "a.b"), ".", $ccr);
echo "$cc: "; print_r($ccr);
--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"]),
$ct["text/json"]["arguments"]["charset"]
);
-var_dump((string) $ct);
+var_dump((string) $ct,$ct);
-echo "Done\n";
+?>
+DONE
--EXPECTF--
Test
bool(true)
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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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===
--- /dev/null
+--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===
--- /dev/null
+--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===
+++ /dev/null
---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)
-
--TEST--
property proxy
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
--FILE--
<?php
--- /dev/null
+--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
--- /dev/null
+--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
+++ /dev/null
---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
<?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);
+ }
+}
--TEST--
url from env
--SKIPIF--
-<? include "skippif.inc"; ?>
+<?php
+include "skipif.inc";
+?>
--ENV--
SERVER_PORT=55555
HTTP_HOST=example.com
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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
--- /dev/null
+--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