
git-svn-id: svn://svn.openwrt.org/openwrt/packages@28123 3c298f89-4303-0410-b956-a3cf2f4a3e73
29803 lines
875 KiB
Diff
29803 lines
875 KiB
Diff
--- /dev/null
|
||
+++ b/ext/http/CREDITS
|
||
@@ -0,0 +1,2 @@
|
||
+HTTP extension for PHP
|
||
+Michael Wallner
|
||
--- /dev/null
|
||
+++ b/ext/http/KnownIssues.txt
|
||
@@ -0,0 +1,33 @@
|
||
+Known Issues
|
||
+============
|
||
+$Id: KnownIssues.txt 292753 2009-12-29 12:30:43Z mike $
|
||
+
|
||
+PHP < 5.1.3:
|
||
+ HttpResponse::getHeader() does not work with Apache2 SAPIs.
|
||
+ Using an encoding stream filter on a stream you read from doesn't work.
|
||
+
|
||
+Windows:
|
||
+ If you keep getting "SSL connect error" when trying to issue
|
||
+ requests, try another (newer) libeay32.dll/ssleay32.dll pair.
|
||
+
|
||
+Internals:
|
||
+ Our http_urlencode_hash() does not differentiate between prefixes
|
||
+ for numeric or string keys.
|
||
+ Inflating raw deflated data causes a re-initialization of the inflate
|
||
+ stream where the corresponding window bits are modified to tell libz
|
||
+ to not check for zlib header bytes. This is not preventable AFAICS.
|
||
+ LFS dependant parts of libcurl are left out because of off_t,
|
||
+ respectively off64_t confusion.
|
||
+ Persistent handles and "cookiestore" request option do interfere,
|
||
+ as libcurl saves the cookies to the file on curl_easy_destroy(),
|
||
+ cookies are not saved until the CURL handle will be recycled.
|
||
+ Thus one would either need to
|
||
+ * run PHP with http.persistent.handles.limit = 0
|
||
+ * call http_persistent_handles_clean() every request
|
||
+ * call $HttpRequest->flushCookies(), which is available
|
||
+ since libcurl v7.17.1 and does not work with the
|
||
+ procedural API
|
||
+ Anyway, none of these options is really perfect.
|
||
+ HTTP and Proxy authentication information (username/password) can not be
|
||
+ unset with NULL prior libcurl v7.19.6 and separate options for setting
|
||
+ username and password--which work--are only available since v7.19.6.
|
||
--- /dev/null
|
||
+++ b/ext/http/LICENSE
|
||
@@ -0,0 +1,47 @@
|
||
+Copyright (c) 2004-2010, Michael Wallner <mike@iworks.at>.
|
||
+All rights reserved.
|
||
+
|
||
+Redistribution and use in source and binary forms, with or without
|
||
+modification, are permitted provided that the following conditions are met:
|
||
+
|
||
+ * Redistributions of source code must retain the above copyright notice,
|
||
+ this list of conditions and the following disclaimer.
|
||
+ * Redistributions in binary form must reproduce the above copyright
|
||
+ notice, this list of conditions and the following disclaimer in the
|
||
+ documentation and/or other materials provided with the distribution.
|
||
+
|
||
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
+
|
||
+===============================================================================
|
||
+
|
||
+The date parser in file http_date_api.c is derived from the implementation
|
||
+found in the original libcurl source, licensed under the following conditions:
|
||
+
|
||
+Copyright (c) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>.
|
||
+All rights reserved.
|
||
+
|
||
+Permission to use, copy, modify, and distribute this software for any purpose
|
||
+with or without fee is hereby granted, provided that the above copyright
|
||
+notice and this permission notice appear in all copies.
|
||
+
|
||
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
|
||
+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||
+OR OTHER DEALINGS IN THE SOFTWARE.
|
||
+
|
||
+Except as contained in this notice, the name of a copyright holder shall not
|
||
+be used in advertising or otherwise to promote the sale, use or other dealings
|
||
+in this Software without prior written authorization of the copyright holder.
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/Makefile.frag
|
||
@@ -0,0 +1,23 @@
|
||
+# vim: noet ts=1 sw=1
|
||
+
|
||
+phpincludedir=$(prefix)/include/php
|
||
+
|
||
+install-http: install install-http-headers
|
||
+
|
||
+install-http-headers:
|
||
+ @echo "Installing HTTP headers: $(INSTALL_ROOT)$(phpincludedir)/ext/http/"
|
||
+ @$(mkinstalldirs) $(INSTALL_ROOT)$(phpincludedir)/ext/http
|
||
+ @for f in $(PHP_HTTP_HEADERS); do \
|
||
+ if test -f "$(top_srcdir)/$$f"; then \
|
||
+ $(INSTALL_DATA) $(top_srcdir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
|
||
+ elif test -f "$(top_builddir)/$$f"; then \
|
||
+ $(INSTALL_DATA) $(top_builddir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
|
||
+ elif test -f "$(top_srcdir)/ext/http/$$f"; then \
|
||
+ $(INSTALL_DATA) $(top_srcdir)/ext/http/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
|
||
+ elif test -f "$(top_builddir)/ext/http/$$f"; then \
|
||
+ $(INSTALL_DATA) $(top_builddir)/ext/http/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
|
||
+ else \
|
||
+ echo "WTF? $$f"; \
|
||
+ fi \
|
||
+ done;
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/ThanksTo.txt
|
||
@@ -0,0 +1,20 @@
|
||
+Thanks To
|
||
+=========
|
||
+$Id: ThanksTo.txt 275653 2009-02-12 13:11:05Z mike $
|
||
+
|
||
+People who repeatedly reported issues with this extension in a manner
|
||
+so they could be fixed in a reasonable way, or suggested useful features
|
||
+to implement, in alphabetical order:
|
||
+
|
||
+ Ilia Alshanetsky (ilia at php dot net)
|
||
+ Petr Czaderna (petr at hroch dot info)
|
||
+ David James (james82 at gmail dot com)
|
||
+ Thomas Landro Johnsen (thomas dot l dot johnsen at gmail dot com)
|
||
+ Clay Loveless (clay at killersoft dot com)
|
||
+ Felipe Pena (felipe at php dot net)
|
||
+ David Sklar (sklar at sklar dot com)
|
||
+ Travis Swicegood (travis at mashery dot com)
|
||
+ Alexey Zakhlestin (indeyets at gmail dot com)
|
||
+ Alexander Zhuravlev (zaa at zaa dot pp dot ru)
|
||
+
|
||
+Thanks a lot!
|
||
--- /dev/null
|
||
+++ b/ext/http/config.m4
|
||
@@ -0,0 +1,5 @@
|
||
+dnl phpize stub of config9.m4 for pecl/http
|
||
+dnl $Id: config.m4 214417 2006-06-07 21:05:34Z mike $
|
||
+dnl vim: noet ts=1 sw=1
|
||
+
|
||
+sinclude(config9.m4)
|
||
--- /dev/null
|
||
+++ b/ext/http/config.w32
|
||
@@ -0,0 +1,129 @@
|
||
+// config.w32 for pecl/http
|
||
+// $Id: config.w32 287971 2009-09-02 14:36:08Z pajoye $
|
||
+
|
||
+ARG_ENABLE("http", "whether to enable extended HTTP support", "no");
|
||
+
|
||
+function check_for_main_ext(ext, header)
|
||
+{
|
||
+ if (!header) {
|
||
+ header = "php_"+ ext +".h";
|
||
+ }
|
||
+
|
||
+ /* When in configure, we're always in the root of PHP source */
|
||
+ var ext_path = "ext\\" + ext;
|
||
+
|
||
+ STDOUT.Write("Checking for ext/"+ ext +" ... ");
|
||
+
|
||
+ if (FSO.FileExists(ext_path + "\\" + header)) {
|
||
+ STDOUT.WriteLine(ext_path);
|
||
+ return ext_path;
|
||
+ }
|
||
+
|
||
+ STDOUT.WriteLine("<not found>");
|
||
+ return false;
|
||
+}
|
||
+
|
||
+function check_for_pecl_ext(ext, header)
|
||
+{
|
||
+ if (!header) {
|
||
+ header = "php_"+ ext +".h";
|
||
+ }
|
||
+
|
||
+ var g;
|
||
+ var s = ext +"\\"+ header;
|
||
+
|
||
+ STDOUT.Write("Checking for pecl/"+ ext +" ... ");
|
||
+ if ( (g = glob(configure_module_dirname +"\\..\\"+ s)) ||
|
||
+ (g = glob(configure_module_dirname +"\\..\\..\\..\\pecl\\"+ s))) {
|
||
+ var f = g[0].substr(0, g[0].length - header.length - 1);
|
||
+ STDOUT.WriteLine(f);
|
||
+ return f;
|
||
+ }
|
||
+ STDOUT.WriteLine("<not found>");
|
||
+ return false;
|
||
+}
|
||
+
|
||
+if (PHP_HTTP != "no") {
|
||
+
|
||
+ EXTENSION("http",
|
||
+ "missing.c http.c http_functions.c http_exception_object.c "+
|
||
+ "http_util_object.c http_message_object.c http_requestpool_object.c "+
|
||
+ "http_request_object.c http_response_object.c "+
|
||
+ "http_api.c http_cache_api.c http_request_pool_api.c "+
|
||
+ "http_request_api.c http_date_api.c http_headers_api.c "+
|
||
+ "http_message_api.c http_send_api.c http_url_api.c "+
|
||
+ "http_info_api.c http_request_method_api.c http_encoding_api.c "+
|
||
+ "http_filter_api.c http_request_body_api.c http_querystring_object.c "+
|
||
+ "http_deflatestream_object.c http_inflatestream_object.c "+
|
||
+ "http_cookie_api.c http_querystring_api.c http_request_datashare_api.c "+
|
||
+ "http_requestdatashare_object.c http_request_info.c http_persistent_handle_api.c",
|
||
+ null,
|
||
+ "/I\"" + configure_module_dirname + "/phpstr\"");
|
||
+ ADD_SOURCES(configure_module_dirname + "/phpstr", "phpstr.c", "http");
|
||
+ AC_DEFINE("HAVE_HTTP", 1, "Have extended HTTP support");
|
||
+ AC_DEFINE("HTTP_SHARED_DEPS", 1, "Depend on shared extensions");
|
||
+
|
||
+ AC_DEFINE("HAVE_GETHOSTNAME", 1);
|
||
+ AC_DEFINE("HAVE_GETSERVBYPORT", 1);
|
||
+ AC_DEFINE("HAVE_GETSERVBYNAME", 1);
|
||
+
|
||
+ if (PHP_DEBUG != "no") {
|
||
+ ADD_FLAG("CFLAGS_HTTP", "/W3");
|
||
+ }
|
||
+
|
||
+ if (CHECK_HEADER_ADD_INCLUDE('zlib.h', 'CFLAGS_HTTP', '..\\zlib;' + php_usual_include_suspects)) {
|
||
+ AC_DEFINE('HTTP_HAVE_ZLIB', 1, "Have zlib library");
|
||
+ ADD_FLAG("LDFLAGS_HTTP", "/FORCE:MULTIPLE");
|
||
+ } else {
|
||
+ WARNING("zlib encoding functions not enabled; libraries and headers not found");
|
||
+ }
|
||
+
|
||
+ if (typeof(PHP_HASH) != "undefined" && PHP_HASH != "no") {
|
||
+ var f;
|
||
+
|
||
+ if ((f = check_for_pecl_ext("hash")) || (f = check_for_main_ext("hash"))) {
|
||
+ ADD_FLAG("CFLAGS_HTTP", '/I "' + f + '" /DHTTP_HAVE_PHP_HASH_H=1');
|
||
+ ADD_EXTENSION_DEP("http", "hash", true);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (PHP_SESSION != "no") {
|
||
+ ADD_EXTENSION_DEP("http", "session", true);
|
||
+ }
|
||
+
|
||
+ if (PHP_ICONV != "no") {
|
||
+ ADD_EXTENSION_DEP("http", "iconv", true);
|
||
+ }
|
||
+
|
||
+ CURL_LIB="libcurl_a.lib;libcurl.lib;" + (PHP_DEBUG != "no" ? "libcurld.lib":"libcurl.lib");
|
||
+ if (CHECK_HEADER_ADD_INCLUDE("curl/curl.h", "CFLAGS_HTTP") &&
|
||
+ CHECK_HEADER_ADD_INCLUDE("openssl/crypto.h", "CFLAGS_HTTP") &&
|
||
+ CHECK_LIB(CURL_LIB, "http", PHP_HTTP) &&
|
||
+ CHECK_LIB("ssleay32.lib", "http", PHP_HTTP) &&
|
||
+ CHECK_LIB("libeay32.lib", "http", PHP_HTTP) &&
|
||
+ CHECK_LIB("zlib.lib;zlib_a.lib", "http", PHP_HTTP) &&
|
||
+ CHECK_LIB("winmm.lib", "http", PHP_HTTP)) {
|
||
+ AC_DEFINE("HTTP_HAVE_CURL", 1, "Have CURL library");
|
||
+ AC_DEFINE("HTTP_HAVE_SSL", 1, "Have SSL");
|
||
+ AC_DEFINE("HAVE_CURL_MULTI_STRERROR", 1, "");
|
||
+ AC_DEFINE("HAVE_CURL_SHARE_STRERROR", 1, "");
|
||
+ AC_DEFINE("HAVE_CURL_EASY_STRERROR", 1, "");
|
||
+ AC_DEFINE("HAVE_CURL_EASY_RESET", 1, "");
|
||
+ AC_DEFINE("HAVE_CURL_GETFORMDATA", 1, "");
|
||
+ AC_DEFINE("HAVE_CURL_FORMGET", 1, "");
|
||
+ AC_DEFINE("HAVE_CURL_MULTI_SETOPT", 1, "");
|
||
+ AC_DEFINE("HAVE_CURL_MULTI_TIMEOUT", 1, "");
|
||
+ } else {
|
||
+ WARNING("curl convenience functions not enabled; libraries and headers not found");
|
||
+ }
|
||
+/*
|
||
+// MAGIC_LIB = PHP_DEBUG != "no" ? "libmagic-staticd.lib":"libmagic-static.lib";
|
||
+// if (CHECK_HEADER_ADD_INCLUDE("magic.h", "CFLAGS_HTTP") &&
|
||
+// CHECK_LIB(MAGIC_LIB, "http", PHP_HTTP)) {
|
||
+// AC_DEFINE("HTTP_HAVE_MAGIC", 1, "Have magic library");
|
||
+// AC_DEFINE("USE_MAGIC_STATIC", "", "");
|
||
+// } else {
|
||
+// WARNING("content type guessing not enabled; libraries and headers not found");
|
||
+// }
|
||
+*/
|
||
+}
|
||
--- /dev/null
|
||
+++ b/ext/http/config9.m4
|
||
@@ -0,0 +1,468 @@
|
||
+dnl config.m4 for pecl/http
|
||
+dnl $Id: config9.m4 242664 2007-09-18 19:13:37Z mike $
|
||
+dnl vim: noet ts=1 sw=1
|
||
+
|
||
+PHP_ARG_ENABLE([http], [whether to enable extended HTTP support],
|
||
+[ --enable-http Enable extended HTTP support])
|
||
+PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared],
|
||
+[ --with-http-shared-deps
|
||
+ HTTP: disable to not depend on extensions like hash,
|
||
+ iconv and session (when built shared)], $PHP_HTTP, $PHP_HTTP)
|
||
+PHP_ARG_WITH([http-curl-requests], [whether to enable cURL HTTP request support],
|
||
+[ --with-http-curl-requests[=LIBCURLDIR]
|
||
+ HTTP: with cURL request support], $PHP_HTTP, $PHP_HTTP)
|
||
+PHP_ARG_WITH([http-curl-libevent], [whether to enable libevent support fur cURL],
|
||
+[ --with-http-curl-libevent[=LIBEVENTDIR]
|
||
+ HTTP: libevent install directory], $PHP_HTTP_CURL_REQUESTS, "")
|
||
+PHP_ARG_WITH([http-zlib-compression], [whether to enable zlib encodings support],
|
||
+[ --with-http-zlib-compression[=LIBZDIR]
|
||
+ HTTP: with zlib encodings support], $PHP_HTTP, $PHP_HTTP)
|
||
+PHP_ARG_WITH([http-magic-mime], [whether to enable response content type guessing],
|
||
+[ --with-http-magic-mime[=LIBMAGICDIR]
|
||
+ HTTP: with magic mime response content type guessing], "no", "no")
|
||
+
|
||
+if test "$PHP_HTTP" != "no"; then
|
||
+
|
||
+ ifdef([AC_PROG_EGREP], [
|
||
+ AC_PROG_EGREP
|
||
+ ], [
|
||
+ AC_CHECK_PROG(EGREP, egrep, egrep)
|
||
+ ])
|
||
+ ifdef([AC_PROG_SED], [
|
||
+ AC_PROG_SED
|
||
+ ], [
|
||
+ ifdef([LT_AC_PROG_SED], [
|
||
+ LT_AC_PROG_SED
|
||
+ ], [
|
||
+ AC_CHECK_PROG(SED, sed, sed)
|
||
+ ])
|
||
+ ])
|
||
+
|
||
+ AC_PROG_CPP
|
||
+
|
||
+ if test "$PHP_HTTP_SHARED_DEPS" != "no"; then
|
||
+ AC_DEFINE([HTTP_SHARED_DEPS], [1], [ ])
|
||
+ else
|
||
+ AC_DEFINE([HTTP_SHARED_DEPS], [0], [ ])
|
||
+ fi
|
||
+
|
||
+ dnl
|
||
+ dnl HTTP_SHARED_DEP(name[, code-if-yes[, code-if-not]])
|
||
+ dnl
|
||
+ AC_DEFUN([HTTP_SHARED_DEP], [
|
||
+ extname=$1
|
||
+ haveext=$[HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)
|
||
+
|
||
+ AC_MSG_CHECKING([whether to add a dependency on ext/$extname])
|
||
+ if test "$PHP_HTTP_SHARED_DEPS" = "no"; then
|
||
+ AC_MSG_RESULT([no])
|
||
+ $3
|
||
+ elif test "$haveext"; then
|
||
+ AC_MSG_RESULT([yes])
|
||
+ ifdef([PHP_ADD_EXTENSION_DEP], [
|
||
+ PHP_ADD_EXTENSION_DEP([http], $1, true)
|
||
+ ])
|
||
+ $2
|
||
+ else
|
||
+ AC_MSG_RESULT([no])
|
||
+ $3
|
||
+ fi
|
||
+ ])
|
||
+
|
||
+ dnl
|
||
+ dnl HTTP_HAVE_PHP_EXT(name[, code-if-yes[, code-if-not]])
|
||
+ dnl
|
||
+ AC_DEFUN([HTTP_HAVE_PHP_EXT], [
|
||
+ extname=$1
|
||
+ haveext=$[PHP_]translit($1,a-z_-,A-Z__)
|
||
+
|
||
+ AC_MSG_CHECKING([for ext/$extname support])
|
||
+ if test -x "$PHP_EXECUTABLE"; then
|
||
+ grepext=`$PHP_EXECUTABLE -m | $EGREP ^$extname\$`
|
||
+ if test "$grepext" = "$extname"; then
|
||
+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=1
|
||
+ AC_MSG_RESULT([yes])
|
||
+ $2
|
||
+ else
|
||
+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=
|
||
+ AC_MSG_RESULT([no])
|
||
+ $3
|
||
+ fi
|
||
+ elif test "$haveext" != "no" && test "x$haveext" != "x"; then
|
||
+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=1
|
||
+ AC_MSG_RESULT([yes])
|
||
+ $2
|
||
+ else
|
||
+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=
|
||
+ AC_MSG_RESULT([no])
|
||
+ $3
|
||
+ fi
|
||
+ ])
|
||
+
|
||
+ dnl
|
||
+ dnl odd PHP4 fix
|
||
+ dnl
|
||
+ if test "x$PHP_LIBDIR" = "x"; then
|
||
+ PHP_LIBDIR=lib
|
||
+ fi
|
||
+
|
||
+dnl ----
|
||
+dnl STDC
|
||
+dnl ----
|
||
+ AC_CHECK_HEADERS([netdb.h unistd.h])
|
||
+ PHP_CHECK_FUNC(gethostname, nsl)
|
||
+ PHP_CHECK_FUNC(getdomainname, nsl)
|
||
+ PHP_CHECK_FUNC(getservbyport, nsl)
|
||
+ PHP_CHECK_FUNC(getservbyname, nsl)
|
||
+
|
||
+dnl ----
|
||
+dnl ZLIB
|
||
+dnl ----
|
||
+ if test "$PHP_HTTP_ZLIB_COMPRESSION" != "no"; then
|
||
+ AC_MSG_CHECKING([for zlib.h])
|
||
+ ZLIB_DIR=
|
||
+ for i in "$PHP_HTTP_ZLIB_COMPRESSION" "$PHP_ZLIB_DIR" "$PHP_ZLIB" /usr/local /usr /opt; do
|
||
+ if test -f "$i/include/zlib.h"; then
|
||
+ ZLIB_DIR=$i
|
||
+ break;
|
||
+ fi
|
||
+ done
|
||
+ if test "x$ZLIB_DIR" = "x"; then
|
||
+ AC_MSG_RESULT([not found])
|
||
+ AC_MSG_ERROR([could not find zlib.h])
|
||
+ else
|
||
+ AC_MSG_RESULT([found in $ZLIB_DIR])
|
||
+ AC_MSG_CHECKING([for zlib version >= 1.2.0.4])
|
||
+ ZLIB_VERSION=`$EGREP "define ZLIB_VERSION" $ZLIB_DIR/include/zlib.h | $SED -e 's/[[^0-9\.]]//g'`
|
||
+ AC_MSG_RESULT([$ZLIB_VERSION])
|
||
+ if test `echo $ZLIB_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*1000000 + $2*10000 + $3*100 + $4}'` -lt 1020004; then
|
||
+ AC_MSG_ERROR([libz version greater or equal to 1.2.0.4 required])
|
||
+ else
|
||
+ PHP_ADD_INCLUDE($ZLIB_DIR/include)
|
||
+ PHP_ADD_LIBRARY_WITH_PATH(z, $ZLIB_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
|
||
+ AC_DEFINE([HTTP_HAVE_ZLIB], [1], [Have zlib support])
|
||
+ fi
|
||
+ fi
|
||
+ fi
|
||
+
|
||
+dnl ----
|
||
+dnl CURL
|
||
+dnl ----
|
||
+ if test "$PHP_HTTP_CURL_REQUESTS" != "no"; then
|
||
+ AC_MSG_CHECKING([for curl/curl.h])
|
||
+ CURL_DIR=
|
||
+ for i in "$PHP_HTTP_CURL_REQUESTS" /usr/local /usr /opt; do
|
||
+ if test -f "$i/include/curl/curl.h"; then
|
||
+ CURL_DIR=$i
|
||
+ break
|
||
+ fi
|
||
+ done
|
||
+ if test "x$CURL_DIR" = "x"; then
|
||
+ AC_MSG_RESULT([not found])
|
||
+ AC_MSG_ERROR([could not find curl/curl.h])
|
||
+ else
|
||
+ AC_MSG_RESULT([found in $CURL_DIR])
|
||
+ fi
|
||
+
|
||
+ AC_MSG_CHECKING([for curl-config])
|
||
+ CURL_CONFIG=
|
||
+ for i in "$CURL_DIR/bin/curl-config" "$CURL_DIR/curl-config" `which curl-config`; do
|
||
+ if test -x "$i"; then
|
||
+ CURL_CONFIG=$i
|
||
+ break
|
||
+ fi
|
||
+ done
|
||
+ if test "x$CURL_CONFIG" = "x"; then
|
||
+ AC_MSG_RESULT([not found])
|
||
+ AC_MSG_ERROR([could not find curl-config])
|
||
+ else
|
||
+ AC_MSG_RESULT([found: $CURL_CONFIG])
|
||
+ fi
|
||
+
|
||
+ dnl Debian stable has currently 7.13.2 (this is not a typo)
|
||
+ AC_MSG_CHECKING([for curl version >= 7.12.3])
|
||
+ CURL_VERSION=`$CURL_CONFIG --version | $SED -e 's/[[^0-9\.]]//g'`
|
||
+ AC_MSG_RESULT([$CURL_VERSION])
|
||
+ if test `echo $CURL_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*10000 + $2*100 + $3}'` -lt 71203; then
|
||
+ AC_MSG_ERROR([libcurl version greater or equal to 7.12.3 required])
|
||
+ fi
|
||
+
|
||
+ dnl
|
||
+ dnl compile tests
|
||
+ dnl
|
||
+
|
||
+ save_INCLUDES="$INCLUDES"
|
||
+ INCLUDES=
|
||
+ save_LIBS="$LIBS"
|
||
+ LIBS=
|
||
+ save_CFLAGS="$CFLAGS"
|
||
+ CFLAGS=`$CURL_CONFIG --cflags`
|
||
+ save_LDFLAGS="$LDFLAGS"
|
||
+ LDFLAGS=`$CURL_CONFIG --libs`
|
||
+ LDFLAGS="$LDFLAGS $ld_runpath_switch$CURL_DIR/$PHP_LIBDIR"
|
||
+
|
||
+ AC_MSG_CHECKING([for SSL support in libcurl])
|
||
+ CURL_SSL=`$CURL_CONFIG --feature | $EGREP SSL`
|
||
+ if test "$CURL_SSL" = "SSL"; then
|
||
+ AC_MSG_RESULT([yes])
|
||
+ AC_DEFINE([HTTP_HAVE_SSL], [1], [ ])
|
||
+
|
||
+ AC_MSG_CHECKING([for openssl 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->ssl_version && *data->ssl_version) {
|
||
+ const char *ptr = data->ssl_version;
|
||
+ while(*ptr == ' ') ++ptr;
|
||
+ return strncasecmp(ptr, "OpenSSL", sizeof("OpenSSL")-1);
|
||
+ }
|
||
+ return 1;
|
||
+ }
|
||
+ ], [
|
||
+ AC_MSG_RESULT([yes])
|
||
+ AC_CHECK_HEADER([openssl/crypto.h], [
|
||
+ AC_DEFINE([HTTP_HAVE_OPENSSL], [1], [ ])
|
||
+ ])
|
||
+ ], [
|
||
+ AC_MSG_RESULT([no])
|
||
+ ], [
|
||
+ AC_MSG_RESULT([no])
|
||
+ ])
|
||
+
|
||
+ AC_MSG_CHECKING([for gnutls 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->ssl_version && *data->ssl_version) {
|
||
+ const char *ptr = data->ssl_version;
|
||
+ while(*ptr == ' ') ++ptr;
|
||
+ return strncasecmp(ptr, "GnuTLS", sizeof("GnuTLS")-1);
|
||
+ }
|
||
+ return 1;
|
||
+ }
|
||
+ ], [
|
||
+ AC_MSG_RESULT([yes])
|
||
+ AC_CHECK_HEADER([gcrypt.h], [
|
||
+ AC_DEFINE([HTTP_HAVE_GNUTLS], [1], [ ])
|
||
+ ])
|
||
+ ], [
|
||
+ AC_MSG_RESULT([no])
|
||
+ ], [
|
||
+ AC_MSG_RESULT([no])
|
||
+ ])
|
||
+ else
|
||
+ AC_MSG_RESULT([no])
|
||
+ fi
|
||
+
|
||
+ INCLUDES="$save_INCLUDES"
|
||
+ LIBS="$save_LIBS"
|
||
+ CFLAGS="$save_CFLAGS"
|
||
+ LDFLAGS="$save_LDFLAGS"
|
||
+
|
||
+ 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
|
||
+ if test -f "$i"; then
|
||
+ CURL_CAINFO="$i"
|
||
+ break
|
||
+ fi
|
||
+ done
|
||
+ if test "x$CURL_CAINFO" = "x"; then
|
||
+ AC_MSG_RESULT([not found])
|
||
+ else
|
||
+ AC_MSG_RESULT([$CURL_CAINFO])
|
||
+ AC_DEFINE_UNQUOTED([HTTP_CURL_CAINFO], ["$CURL_CAINFO"], [path to bundled SSL CA info])
|
||
+ fi
|
||
+
|
||
+ 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)
|
||
+ AC_DEFINE([HTTP_HAVE_CURL], [1], [Have cURL support])
|
||
+
|
||
+ PHP_CHECK_LIBRARY(curl, curl_share_strerror,
|
||
+ [AC_DEFINE([HAVE_CURL_SHARE_STRERROR], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+ PHP_CHECK_LIBRARY(curl, curl_multi_strerror,
|
||
+ [AC_DEFINE([HAVE_CURL_MULTI_STRERROR], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+ PHP_CHECK_LIBRARY(curl, curl_easy_strerror,
|
||
+ [AC_DEFINE([HAVE_CURL_EASY_STRERROR], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+ PHP_CHECK_LIBRARY(curl, curl_easy_reset,
|
||
+ [AC_DEFINE([HAVE_CURL_EASY_RESET], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+ PHP_CHECK_LIBRARY(curl, curl_formget,
|
||
+ [AC_DEFINE([HAVE_CURL_FORMGET], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+ PHP_CHECK_LIBRARY(curl, curl_multi_setopt,
|
||
+ [AC_DEFINE([HAVE_CURL_MULTI_SETOPT], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+ PHP_CHECK_LIBRARY(curl, curl_multi_timeout,
|
||
+ [AC_DEFINE([HAVE_CURL_MULTI_TIMEOUT], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+
|
||
+ dnl ----
|
||
+ dnl EVENT
|
||
+ dnl ----
|
||
+
|
||
+ if test "$PHP_HTTP_CURL_LIBEVENT" != "no"; then
|
||
+ HTTP_HAVE_PHP_EXT([event], [
|
||
+ AC_MSG_WARN([event support is incompatible with pecl/event; continuing without libevent support])
|
||
+ ], [
|
||
+ AC_MSG_CHECKING([for event.h])
|
||
+ EVENT_DIR=
|
||
+ for i in "$PHP_HTTP_CURL_LIBEVENT" /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])
|
||
+ else
|
||
+ AC_MSG_RESULT([found in $EVENT_DIR])
|
||
+
|
||
+ AC_MSG_CHECKING([for libevent version, roughly])
|
||
+ EVENT_VER="1.1b or lower"
|
||
+ 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
|
||
+ fi
|
||
+ AC_DEFINE_UNQUOTED([HTTP_EVENT_VERSION], ["$EVENT_VER"], [ ])
|
||
+ AC_MSG_RESULT([$EVENT_VER])
|
||
+
|
||
+ AC_MSG_CHECKING([for libcurl version >= 7.16.0])
|
||
+ AC_MSG_RESULT([$CURL_VERSION])
|
||
+ if test `echo $CURL_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*10000 + $2*100 + $3}'` -lt 71600; then
|
||
+ AC_MSG_WARN([libcurl version greater or equal to 7.16.0 required; continuing without libevent support])
|
||
+ else
|
||
+ PHP_ADD_INCLUDE($EVENT_DIR/include)
|
||
+ PHP_ADD_LIBRARY_WITH_PATH(event, $EVENT_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
|
||
+ AC_DEFINE([HTTP_HAVE_EVENT], [1], [Have libevent support for cURL])
|
||
+ PHP_CHECK_LIBRARY(curl, curl_multi_socket_action,
|
||
+ [AC_DEFINE([HAVE_CURL_MULTI_SOCKET_ACTION], [1], [ ])], [ ],
|
||
+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
|
||
+ )
|
||
+ fi
|
||
+ fi
|
||
+ ])
|
||
+ fi
|
||
+ fi
|
||
+
|
||
+dnl ----
|
||
+dnl MAGIC
|
||
+dnl ----
|
||
+ if test "$PHP_HTTP_MAGIC_MIME" != "no"; then
|
||
+ AC_MSG_CHECKING([for magic.h])
|
||
+ MAGIC_DIR=
|
||
+ for i in "$PHP_HTTP_MAGIC_MIME" /usr/local /usr /opt; do
|
||
+ if test -f "$i/include/magic.h"; then
|
||
+ MAGIC_DIR=$i
|
||
+ break
|
||
+ fi
|
||
+ done
|
||
+ if test "x$MAGIC_DIR" = "x"; then
|
||
+ AC_MSG_RESULT([not found])
|
||
+ AC_MSG_ERROR([could not find magic.h])
|
||
+ else
|
||
+ AC_MSG_RESULT([found in $MAGIC_DIR])
|
||
+ fi
|
||
+
|
||
+ PHP_ADD_INCLUDE($MAGIC_DIR/include)
|
||
+ PHP_ADD_LIBRARY_WITH_PATH(magic, $MAGIC_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
|
||
+ AC_DEFINE([HTTP_HAVE_MAGIC], [1], [Have magic mime support])
|
||
+ fi
|
||
+
|
||
+dnl ----
|
||
+dnl HASH
|
||
+dnl ----
|
||
+ HTTP_HAVE_PHP_EXT([hash], [
|
||
+ AC_MSG_CHECKING([for php_hash.h])
|
||
+ HTTP_EXT_HASH_INCDIR=
|
||
+ for i in `echo $INCLUDES | $SED -e's/-I//g'` $abs_srcdir ../hash; do
|
||
+ if test -d $i; then
|
||
+ if test -f $i/php_hash.h; then
|
||
+ HTTP_EXT_HASH_INCDIR=$i
|
||
+ break
|
||
+ elif test -f $i/ext/hash/php_hash.h; then
|
||
+ HTTP_EXT_HASH_INCDIR=$i/ext/hash
|
||
+ break
|
||
+ fi
|
||
+ fi
|
||
+ done
|
||
+ if test "x$HTTP_EXT_HASH_INCDIR" = "x"; then
|
||
+ AC_MSG_RESULT([not found])
|
||
+ else
|
||
+ AC_MSG_RESULT([$HTTP_EXT_HASH_INCDIR])
|
||
+ AC_DEFINE([HTTP_HAVE_PHP_HASH_H], [1], [Have ext/hash support])
|
||
+ PHP_ADD_INCLUDE([$HTTP_EXT_HASH_INCDIR])
|
||
+ fi
|
||
+ ])
|
||
+
|
||
+dnl ----
|
||
+dnl ICONV
|
||
+dnl ----
|
||
+ HTTP_HAVE_PHP_EXT([iconv])
|
||
+
|
||
+dnl ----
|
||
+dnl SESSION
|
||
+dnl ----
|
||
+ HTTP_HAVE_PHP_EXT([session])
|
||
+
|
||
+dnl ----
|
||
+dnl DONE
|
||
+dnl ----
|
||
+ PHP_HTTP_SOURCES="missing.c http.c http_functions.c phpstr/phpstr.c \
|
||
+ http_util_object.c http_message_object.c http_request_object.c http_request_pool_api.c \
|
||
+ http_response_object.c http_exception_object.c http_requestpool_object.c \
|
||
+ http_api.c http_cache_api.c http_request_api.c http_request_info.c http_date_api.c \
|
||
+ http_headers_api.c http_message_api.c http_send_api.c http_url_api.c \
|
||
+ http_info_api.c http_request_method_api.c http_encoding_api.c \
|
||
+ http_filter_api.c http_request_body_api.c http_querystring_object.c \
|
||
+ http_deflatestream_object.c http_inflatestream_object.c http_cookie_api.c \
|
||
+ http_querystring_api.c http_request_datashare_api.c http_requestdatashare_object.c \
|
||
+ http_persistent_handle_api.c"
|
||
+
|
||
+ PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared)
|
||
+
|
||
+ dnl shared extension deps
|
||
+ HTTP_SHARED_DEP([hash])
|
||
+ HTTP_SHARED_DEP([iconv])
|
||
+ HTTP_SHARED_DEP([session])
|
||
+
|
||
+ PHP_ADD_BUILD_DIR($ext_builddir/phpstr, 1)
|
||
+ PHP_SUBST([HTTP_SHARED_LIBADD])
|
||
+
|
||
+ PHP_HTTP_HEADERS="php_http_std_defs.h php_http.h php_http_api.h php_http_cache_api.h \
|
||
+ php_http_date_api.h php_http_headers_api.h php_http_info_api.h php_http_message_api.h \
|
||
+ php_http_request_api.h php_http_request_method_api.h php_http_send_api.h php_http_url_api.h \
|
||
+ php_http_encoding_api.h phpstr/phpstr.h missing.h php_http_request_body_api.h \
|
||
+ php_http_exception_object.h php_http_message_object.h php_http_request_object.h \
|
||
+ php_http_requestpool_object.h php_http_response_object.h php_http_util_object.h \
|
||
+ php_http_querystring_object.h php_http_deflatestream_object.h php_http_inflatestream_object.h \
|
||
+ php_http_cookie_api.h php_http_querystring_api.h php_http_request_datashare_api.h php_http_requestdatashare_object.h \
|
||
+ php_http_persistent_handle_api.h"
|
||
+ ifdef([PHP_INSTALL_HEADERS], [
|
||
+ PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS)
|
||
+ ], [
|
||
+ PHP_SUBST([PHP_HTTP_HEADERS])
|
||
+ PHP_ADD_MAKEFILE_FRAGMENT
|
||
+ ])
|
||
+
|
||
+ AC_DEFINE([HAVE_HTTP], [1], [Have extended HTTP support])
|
||
+fi
|
||
--- /dev/null
|
||
+++ b/ext/http/docs/examples/tutorial.txt
|
||
@@ -0,0 +1,175 @@
|
||
+
|
||
+A Beginners Tutorial
|
||
+--------------------
|
||
+$Revision: 208773 $
|
||
+
|
||
+
|
||
+- GET Queries
|
||
+
|
||
+ The HttpRequest class can be used to execute any HTTP request method.
|
||
+ The following example shows a simple GET request where a few query
|
||
+ parameters are supplied. Additionally potential cookies will be
|
||
+ read from and written to a file.
|
||
+
|
||
+<?php
|
||
+$r = new HttpRequest('http://www.google.com/search');
|
||
+
|
||
+// store Googles cookies in a dedicated file
|
||
+touch('google.txt');
|
||
+$r->setOptions(
|
||
+ array( 'cookiestore' => 'google.txt',
|
||
+ )
|
||
+);
|
||
+
|
||
+$r->setQueryData(
|
||
+ array( 'q' => '+"pecl_http" -msg -cvs -list',
|
||
+ 'hl' => 'de'
|
||
+ )
|
||
+);
|
||
+
|
||
+// HttpRequest::send() returns an HttpMessage object
|
||
+// of type HttpMessage::TYPE_RESPONSE or throws an exception
|
||
+try {
|
||
+ print $r->send()->getBody();
|
||
+} catch (HttpException $e) {
|
||
+ print $e;
|
||
+}
|
||
+?>
|
||
+
|
||
+- Multipart Posts
|
||
+
|
||
+ The following example shows an multipart POST request, with two form
|
||
+ fields and an image that's supposed to be uploaded to the server.
|
||
+ It's a bad habit as well as common practice to issue a redirect after
|
||
+ an received POST request, so we'll allow a redirect by enabling the
|
||
+ redirect option.
|
||
+
|
||
+<?php
|
||
+$r = new HttpRequest('http://dev.iworks.at/.print_request.php', HTTP_METH_POST);
|
||
+
|
||
+// if redirects is set to true, a single redirect is allowed;
|
||
+// one can set any reasonable count of allowed redirects
|
||
+$r->setOptions(
|
||
+ array( 'cookies' => array('MyCookie' => 'has a value'),
|
||
+ 'redirect' => true,
|
||
+ )
|
||
+);
|
||
+
|
||
+// common form data
|
||
+$r->setPostFields(
|
||
+ array( 'name' => 'Mike',
|
||
+ 'mail' => 'mike@php.net',
|
||
+ )
|
||
+);
|
||
+// add the file to post (form name, file name, file type)
|
||
+touch('profile.jpg');
|
||
+$r->addPostFile('image', 'profile.jpg', 'image/jpeg');
|
||
+
|
||
+try {
|
||
+ print $r->send()->getBody();
|
||
+} catch (HttpException $e) {
|
||
+ print $e;
|
||
+}
|
||
+?>
|
||
+
|
||
+- Parallel Requests
|
||
+
|
||
+ It's possible to execute several HttpRequests in parallel with the
|
||
+ HttpRequestPool class. HttpRequests to send, do not need to perform
|
||
+ the same request method, but can only be attached to one HttpRequestPool
|
||
+ at the same time.
|
||
+
|
||
+<?php
|
||
+try {
|
||
+ $p = new HttpRequestPool;
|
||
+ // if you want to set _any_ options of the HttpRequest object,
|
||
+ // you need to do so *prior attaching* to the request pool!
|
||
+ $p->attach(new HttpRequest('http://pear.php.net', HTTP_METH_HEAD));
|
||
+ $p->attach(new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD));
|
||
+} catch (HttpException $e) {
|
||
+ print $e;
|
||
+ exit;
|
||
+}
|
||
+
|
||
+try {
|
||
+ $p->send();
|
||
+ // HttpRequestPool implements an iterator over attached HttpRequest objects
|
||
+ foreach ($p as $r) {
|
||
+ echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
|
||
+ }
|
||
+} catch (HttpException $e) {
|
||
+ print $e;
|
||
+}
|
||
+?>
|
||
+
|
||
+- Parallel Requests?
|
||
+
|
||
+ You can use a more advanced approach by using the protected interface of
|
||
+ the HttpRequestPool class. This allows you to perform some other tasks
|
||
+ while the requests are executed.
|
||
+
|
||
+<?php
|
||
+class Pool extends HttpRequestPool
|
||
+{
|
||
+ public function __construct()
|
||
+ {
|
||
+ parent::__construct(
|
||
+ new HttpRequest('http://pear.php.net', HTTP_METH_HEAD),
|
||
+ new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD)
|
||
+ );
|
||
+
|
||
+ // HttpRequestPool methods socketPerform() and socketSelect() are
|
||
+ // protected; one could use this approach to do something else
|
||
+ // while the requests are being executed
|
||
+ print "Executing requests";
|
||
+ for ($i = 0; $this->socketPerform(); $i++) {
|
||
+ $i % 10 or print ".";
|
||
+ if (!$this->socketSelect()) {
|
||
+ throw new HttpException("Socket error!");
|
||
+ }
|
||
+ }
|
||
+ print "\nDone!\n";
|
||
+ }
|
||
+}
|
||
+
|
||
+try {
|
||
+ foreach (new Pool as $r) {
|
||
+ echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
|
||
+ }
|
||
+} catch (HttpException $ex) {
|
||
+ print $e;
|
||
+}
|
||
+?>
|
||
+
|
||
+- Cached Responses
|
||
+
|
||
+ One of the main key features of HttpResponse is HTTP caching. HttpResponse
|
||
+ will calculate an ETag based on the http.etag_mode INI setting as well as
|
||
+ it will determine the last modification time of the sent entity. It uses
|
||
+ those two indicators to decide if the cache entry on the client side is
|
||
+ still valid and will emit an "304 Not Modified" response if applicable.
|
||
+
|
||
+<?php
|
||
+HttpResponse::setCacheControl('public');
|
||
+HttpResponse::setCache(true);
|
||
+HttpResponse::capture();
|
||
+
|
||
+print "This will be cached until content changes!\n";
|
||
+print "Note that this approach will only save the clients download time.\n";
|
||
+?>
|
||
+
|
||
+- Bandwidth Throttling
|
||
+
|
||
+ HttpResponse supports a basic throttling mechanism, which is enabled by
|
||
+ setting a throttle delay and a buffer size. PHP will sleep the specified
|
||
+ amount of seconds after each sent chunk of specified bytes.
|
||
+
|
||
+<?php
|
||
+// send 5000 bytes every 0.2 seconds, i.e. max ~25kByte/s
|
||
+HttpResponse::setThrottleDelay(0.2);
|
||
+HttpResponse::setBufferSize(5000);
|
||
+HttpResponse::setCache(true);
|
||
+HttpResponse::setContentType('application/x-zip');
|
||
+HttpResponse::setFile('../archive.zip');
|
||
+HttpResponse::send();
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/docs/http.ini
|
||
@@ -0,0 +1,61 @@
|
||
+; example INI file for pecl/http
|
||
+; $Id: http.ini 229420 2007-02-09 14:19:40Z mike $
|
||
+
|
||
+[http]
|
||
+; enable if you want to transform all errors to exceptions (PHP >= 5 only)
|
||
+;http.only_exceptions = 1
|
||
+
|
||
+; disable if you don't want php to exit in case of redirects and cache hits;
|
||
+; a "NULL" output handler will be started instead, which discards all output
|
||
+;http.force_exit = 0
|
||
+
|
||
+; disable if you don't want 404 Not found status messages being sent,
|
||
+; if a file attempted to be sent with http_send_file() etc. cannot be found
|
||
+;http.send.not_found_404 = 0
|
||
+
|
||
+; the hashing algorithm with wich ETags are generated (MD5, SHA1, CRC32B);
|
||
+; if ext/hash is available, this can be set to any hash algorithm ext/hash supports
|
||
+; MD5 is the default and fallback algorithm
|
||
+;http.etag.mode = "MD5"
|
||
+
|
||
+; allowed request methods
|
||
+; by default PHP ignores unkown request methods
|
||
+; PHP will exit with a response status of 405 and an Allow header
|
||
+; if it encounters a request method not contained in the specified list
|
||
+;http.request.methods.allowed = "HEAD, GET, POST"
|
||
+
|
||
+; custom request methods
|
||
+;http.request.methods.custom = "KICK, BANN"
|
||
+
|
||
+; log file for positive cache hits
|
||
+;http.log.cache =
|
||
+
|
||
+; log file for redirects
|
||
+;http.log.redirect =
|
||
+
|
||
+; log file for responses with http_send_file() etc. where the file's not been found
|
||
+;http.log.not_found =
|
||
+
|
||
+; log file for requests with an unallowed request method
|
||
+;http.log.allowed_methods =
|
||
+
|
||
+; composite log file (i.e. log all messages to this file)
|
||
+;http.log.composite =
|
||
+
|
||
+; automatically deflate content if requested/supported by client
|
||
+;http.send.deflate.start_auto = 1
|
||
+;http.send.deflate.start_flags = HTTP_DEFLATE_LEVEL_DEF
|
||
+
|
||
+; automatically inflate sent content
|
||
+;http.send.inflate.start_auto = 0
|
||
+;http.send.inflate.start_flags =
|
||
+
|
||
+; global HttpRequestDataShare settings
|
||
+;http.request.datashare.cookie = 0
|
||
+;http.request.datashare.dns = 1
|
||
+
|
||
+; limit of idle persistent handles per provider
|
||
+;http.persistent.handles.limit = -1
|
||
+
|
||
+; default ident of persistent handles
|
||
+;http.persistent.handles.ident = "GLOBAL"
|
||
--- /dev/null
|
||
+++ b/ext/http/http.c
|
||
@@ -0,0 +1,546 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http.c 300300 2010-06-09 07:29:35Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_CURL
|
||
+#define HTTP_WANT_EVENT
|
||
+#define HTTP_WANT_ZLIB
|
||
+#define HTTP_WANT_MAGIC
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_ini.h"
|
||
+#include "ext/standard/info.h"
|
||
+#include "zend_extensions.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_cache_api.h"
|
||
+#include "php_http_cookie_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_filter_api.h"
|
||
+#include "php_http_message_api.h"
|
||
+#include "php_http_persistent_handle_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_datashare_api.h"
|
||
+#include "php_http_request_method_api.h"
|
||
+#include "php_http_request_pool_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+
|
||
+#include "php_http_deflatestream_object.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_inflatestream_object.h"
|
||
+#include "php_http_message_object.h"
|
||
+#include "php_http_querystring_object.h"
|
||
+#include "php_http_request_object.h"
|
||
+#include "php_http_requestdatashare_object.h"
|
||
+#include "php_http_requestpool_object.h"
|
||
+#include "php_http_response_object.h"
|
||
+#include "php_http_util_object.h"
|
||
+
|
||
+ZEND_DECLARE_MODULE_GLOBALS(http);
|
||
+HTTP_DECLARE_ARG_PASS_INFO();
|
||
+
|
||
+#ifdef COMPILE_DL_HTTP
|
||
+ZEND_GET_MODULE(http)
|
||
+#endif
|
||
+
|
||
+/* {{{ http_functions[] */
|
||
+zend_function_entry http_functions[] = {
|
||
+ PHP_FE(http_date, NULL)
|
||
+ PHP_FE(http_build_url, http_arg_pass_ref_4)
|
||
+ PHP_FE(http_build_str, NULL)
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ PHP_FALIAS(http_build_query, http_build_str, NULL)
|
||
+#endif
|
||
+ PHP_FE(http_negotiate_language, http_arg_pass_ref_2)
|
||
+ PHP_FE(http_negotiate_charset, http_arg_pass_ref_2)
|
||
+ PHP_FE(http_negotiate_content_type, http_arg_pass_ref_2)
|
||
+ PHP_FE(http_negotiate, http_arg_pass_ref_3)
|
||
+ PHP_FE(http_redirect, NULL)
|
||
+ PHP_FE(http_throttle, NULL)
|
||
+ PHP_FE(http_send_status, NULL)
|
||
+ PHP_FE(http_send_last_modified, NULL)
|
||
+ PHP_FE(http_send_content_type, NULL)
|
||
+ PHP_FE(http_send_content_disposition, NULL)
|
||
+ PHP_FE(http_match_modified, NULL)
|
||
+ PHP_FE(http_match_etag, NULL)
|
||
+ PHP_FE(http_cache_last_modified, NULL)
|
||
+ PHP_FE(http_cache_etag, NULL)
|
||
+ PHP_FE(http_send_data, NULL)
|
||
+ PHP_FE(http_send_file, NULL)
|
||
+ PHP_FE(http_send_stream, NULL)
|
||
+ PHP_FE(http_chunked_decode, NULL)
|
||
+ PHP_FE(http_parse_message, NULL)
|
||
+ PHP_FE(http_parse_headers, NULL)
|
||
+ PHP_FE(http_parse_cookie, NULL)
|
||
+ PHP_FE(http_build_cookie, NULL)
|
||
+ PHP_FE(http_parse_params, NULL)
|
||
+ PHP_FE(http_get_request_headers, NULL)
|
||
+ PHP_FE(http_get_request_body, NULL)
|
||
+ PHP_FE(http_get_request_body_stream, NULL)
|
||
+ PHP_FE(http_match_request_header, NULL)
|
||
+ PHP_FE(http_persistent_handles_count, NULL)
|
||
+ PHP_FE(http_persistent_handles_clean, NULL)
|
||
+ PHP_FE(http_persistent_handles_ident, NULL)
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+ PHP_FE(http_get, http_arg_pass_ref_3)
|
||
+ PHP_FE(http_head, http_arg_pass_ref_3)
|
||
+ PHP_FE(http_post_data, http_arg_pass_ref_4)
|
||
+ PHP_FE(http_post_fields, http_arg_pass_ref_5)
|
||
+ PHP_FE(http_put_data, http_arg_pass_ref_4)
|
||
+ PHP_FE(http_put_file, http_arg_pass_ref_4)
|
||
+ PHP_FE(http_put_stream, http_arg_pass_ref_4)
|
||
+ PHP_FE(http_request, http_arg_pass_ref_5)
|
||
+ PHP_FE(http_request_body_encode, NULL)
|
||
+#endif
|
||
+ PHP_FE(http_request_method_register, NULL)
|
||
+ PHP_FE(http_request_method_unregister, NULL)
|
||
+ PHP_FE(http_request_method_exists, NULL)
|
||
+ PHP_FE(http_request_method_name, NULL)
|
||
+ PHP_FE(ob_etaghandler, NULL)
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ PHP_FE(http_deflate, NULL)
|
||
+ PHP_FE(http_inflate, NULL)
|
||
+ PHP_FE(ob_deflatehandler, NULL)
|
||
+ PHP_FE(ob_inflatehandler, NULL)
|
||
+#endif
|
||
+ PHP_FE(http_support, NULL)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+PHP_MINIT_FUNCTION(http);
|
||
+PHP_MSHUTDOWN_FUNCTION(http);
|
||
+PHP_RINIT_FUNCTION(http);
|
||
+PHP_RSHUTDOWN_FUNCTION(http);
|
||
+PHP_MINFO_FUNCTION(http);
|
||
+
|
||
+/* {{{ http_module_dep */
|
||
+#if ZEND_EXTENSION_API_NO >= 220050617
|
||
+static zend_module_dep http_module_deps[] = {
|
||
+# ifdef HTTP_HAVE_SPL
|
||
+ ZEND_MOD_REQUIRED("spl")
|
||
+# endif
|
||
+# ifdef HTTP_HAVE_HASH
|
||
+ ZEND_MOD_REQUIRED("hash")
|
||
+# endif
|
||
+# ifdef HTTP_HAVE_SESSION
|
||
+ ZEND_MOD_REQUIRED("session")
|
||
+# endif
|
||
+# ifdef HTTP_HAVE_ICONV
|
||
+ ZEND_MOD_REQUIRED("iconv")
|
||
+# endif
|
||
+# ifdef HTTP_HAVE_EVENT
|
||
+ ZEND_MOD_CONFLICTS("event")
|
||
+#endif
|
||
+ {NULL, NULL, NULL, 0}
|
||
+};
|
||
+#endif
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_module_entry */
|
||
+zend_module_entry http_module_entry = {
|
||
+#if ZEND_EXTENSION_API_NO >= 220050617
|
||
+ STANDARD_MODULE_HEADER_EX, NULL,
|
||
+ http_module_deps,
|
||
+#else
|
||
+ STANDARD_MODULE_HEADER,
|
||
+#endif
|
||
+ "http",
|
||
+ http_functions,
|
||
+ PHP_MINIT(http),
|
||
+ PHP_MSHUTDOWN(http),
|
||
+ PHP_RINIT(http),
|
||
+ PHP_RSHUTDOWN(http),
|
||
+ PHP_MINFO(http),
|
||
+ PHP_HTTP_VERSION,
|
||
+ STANDARD_MODULE_PROPERTIES
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+int http_module_number;
|
||
+
|
||
+/* {{{ http_globals */
|
||
+static void http_globals_init_once(zend_http_globals *G)
|
||
+{
|
||
+ memset(G, 0, sizeof(zend_http_globals));
|
||
+}
|
||
+
|
||
+#define http_globals_init(g) _http_globals_init((g) TSRMLS_CC)
|
||
+static inline void _http_globals_init(zend_http_globals *G TSRMLS_DC)
|
||
+{
|
||
+#ifdef HTTP_HAVE_SAPI_RTIME
|
||
+ G->request.time = sapi_get_request_time(TSRMLS_C);
|
||
+#else
|
||
+ G->request.time = time(NULL);
|
||
+#endif
|
||
+ G->send.buffer_size = 0;
|
||
+ G->read_post_data = 0;
|
||
+}
|
||
+
|
||
+#define http_globals_free(g) _http_globals_free((g) TSRMLS_CC)
|
||
+static inline void _http_globals_free(zend_http_globals *G TSRMLS_DC)
|
||
+{
|
||
+ if (G->request.headers) {
|
||
+ zend_hash_destroy(G->request.headers);
|
||
+ FREE_HASHTABLE(G->request.headers);
|
||
+ G->request.headers = NULL;
|
||
+ }
|
||
+ STR_SET(G->send.content_type, NULL);
|
||
+ STR_SET(G->send.unquoted_etag, NULL);
|
||
+ if (G->server_var) {
|
||
+ zval_ptr_dtor(&G->server_var);
|
||
+ G->server_var = NULL;
|
||
+ }
|
||
+}
|
||
+
|
||
+#if defined(ZTS) && defined(PHP_DEBUG)
|
||
+#if ZTS && PHP_DEBUG
|
||
+zend_http_globals *http_globals(void)
|
||
+{
|
||
+ TSRMLS_FETCH();
|
||
+ return HTTP_G;
|
||
+}
|
||
+#endif
|
||
+#endif
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static inline void http_check_allowed_methods(char *) */
|
||
+#define http_check_allowed_methods(m) _http_check_allowed_methods((m) TSRMLS_CC)
|
||
+static inline void _http_check_allowed_methods(const char *methods TSRMLS_DC)
|
||
+{
|
||
+ if (*methods && SG(request_info).request_method) {
|
||
+ if (SUCCESS != http_check_method_ex(SG(request_info).request_method, methods)) {
|
||
+ char *header;
|
||
+ spprintf(&header, 0, "Allow: %s", methods);
|
||
+ http_exit(405, header);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_INI */
|
||
+PHP_INI_MH(http_update_allowed_methods)
|
||
+{
|
||
+ if (*new_value) {
|
||
+ http_check_allowed_methods(new_value);
|
||
+ }
|
||
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
|
||
+}
|
||
+PHP_INI_MH(http_update_persistent_handle_ident)
|
||
+{
|
||
+ HTTP_G->persistent.handles.ident.h = zend_hash_func(new_value, HTTP_G->persistent.handles.ident.l = new_value_length+1);
|
||
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
|
||
+}
|
||
+
|
||
+#ifndef ZEND_ENGINE_2
|
||
+# define OnUpdateLong OnUpdateInt
|
||
+#endif
|
||
+
|
||
+PHP_INI_BEGIN()
|
||
+ HTTP_PHP_INI_ENTRY("http.etag.mode", "MD5", PHP_INI_ALL, OnUpdateString, etag.mode)
|
||
+ HTTP_PHP_INI_ENTRY("http.log.cache", "", PHP_INI_ALL, OnUpdateString, log.cache)
|
||
+ HTTP_PHP_INI_ENTRY("http.log.redirect", "", PHP_INI_ALL, OnUpdateString, log.redirect)
|
||
+ HTTP_PHP_INI_ENTRY("http.log.not_found", "", PHP_INI_ALL, OnUpdateString, log.not_found)
|
||
+ HTTP_PHP_INI_ENTRY("http.log.allowed_methods", "", PHP_INI_ALL, OnUpdateString, log.allowed_methods)
|
||
+ HTTP_PHP_INI_ENTRY("http.log.composite", "", PHP_INI_ALL, OnUpdateString, log.composite)
|
||
+ HTTP_PHP_INI_ENTRY("http.request.methods.allowed", "", PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
|
||
+ HTTP_PHP_INI_ENTRY("http.request.methods.custom", "", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, request.methods.custom)
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
|
||
+ HTTP_PHP_INI_ENTRY("http.request.datashare.cookie", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.cookie)
|
||
+ HTTP_PHP_INI_ENTRY("http.request.datashare.dns", "1", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.dns)
|
||
+ HTTP_PHP_INI_ENTRY("http.request.datashare.ssl", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.ssl)
|
||
+ HTTP_PHP_INI_ENTRY("http.request.datashare.connect", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.connect)
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ HTTP_PHP_INI_ENTRY("http.send.inflate.start_auto", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, send.inflate.start_auto)
|
||
+ HTTP_PHP_INI_ENTRY("http.send.inflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.inflate.start_flags)
|
||
+ HTTP_PHP_INI_ENTRY("http.send.deflate.start_auto", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, send.deflate.start_auto)
|
||
+ HTTP_PHP_INI_ENTRY("http.send.deflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.deflate.start_flags)
|
||
+#endif
|
||
+ HTTP_PHP_INI_ENTRY("http.persistent.handles.limit", "-1", PHP_INI_SYSTEM, OnUpdateLong, persistent.handles.limit)
|
||
+ HTTP_PHP_INI_ENTRY("http.persistent.handles.ident", "GLOBAL", PHP_INI_ALL, http_update_persistent_handle_ident, persistent.handles.ident.s)
|
||
+ HTTP_PHP_INI_ENTRY("http.send.not_found_404", "1", PHP_INI_ALL, OnUpdateBool, send.not_found_404)
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ HTTP_PHP_INI_ENTRY("http.only_exceptions", "0", PHP_INI_ALL, OnUpdateBool, only_exceptions)
|
||
+#endif
|
||
+ HTTP_PHP_INI_ENTRY("http.force_exit", "1", PHP_INI_ALL, OnUpdateBool, force_exit)
|
||
+PHP_INI_END()
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_MINIT_FUNCTION */
|
||
+PHP_MINIT_FUNCTION(http)
|
||
+{
|
||
+ http_module_number = module_number;
|
||
+ ZEND_INIT_MODULE_GLOBALS(http, http_globals_init_once, NULL);
|
||
+ REGISTER_INI_ENTRIES();
|
||
+
|
||
+ if (0
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_persistent_handle) /* first */
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_cookie)
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_encoding)
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_request)
|
||
+# ifdef ZEND_ENGINE_2
|
||
+# endif
|
||
+#endif
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_request_method)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_send)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_support)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_url)
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_filter)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_exception_object)
|
||
+# ifdef HTTP_HAVE_ZLIB
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_deflatestream_object)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_inflatestream_object)
|
||
+# endif
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_message_object)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_querystring_object)
|
||
+# ifdef HTTP_HAVE_CURL
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_request_datashare)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_request_pool)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_request_object)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_requestdatashare_object)
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_requestpool_object)
|
||
+# endif
|
||
+# ifndef WONKY
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_response_object)
|
||
+# endif
|
||
+ || SUCCESS != PHP_MINIT_CALL(http_util_object)
|
||
+#endif
|
||
+ ) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_MSHUTDOWN_FUNCTION */
|
||
+PHP_MSHUTDOWN_FUNCTION(http)
|
||
+{
|
||
+ UNREGISTER_INI_ENTRIES();
|
||
+
|
||
+ if (0
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_request)
|
||
+# ifdef ZEND_ENGINE_2
|
||
+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_request_datashare)
|
||
+# endif
|
||
+#endif
|
||
+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_message_object)
|
||
+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_persistent_handle) /* last */
|
||
+ ) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_RINIT_FUNCTION */
|
||
+PHP_RINIT_FUNCTION(http)
|
||
+{
|
||
+ http_globals_init(HTTP_G);
|
||
+
|
||
+ if (HTTP_G->request.methods.allowed && *HTTP_G->request.methods.allowed) {
|
||
+ http_check_allowed_methods(HTTP_G->request.methods.allowed);
|
||
+ }
|
||
+
|
||
+ if (0
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ || SUCCESS != PHP_RINIT_CALL(http_encoding)
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+# ifdef ZEND_ENGINE_2
|
||
+# ifdef HTTP_HAVE_EVENT
|
||
+ || SUCCESS != PHP_RINIT_CALL(http_request_pool)
|
||
+# endif
|
||
+ || SUCCESS != PHP_RINIT_CALL(http_request_datashare)
|
||
+# endif
|
||
+#endif
|
||
+ || SUCCESS != PHP_RINIT_CALL(http_request_method)
|
||
+ ) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_RSHUTDOWN_FUNCTION */
|
||
+PHP_RSHUTDOWN_FUNCTION(http)
|
||
+{
|
||
+ STATUS status = SUCCESS;
|
||
+
|
||
+ if (0
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ || SUCCESS != PHP_RSHUTDOWN_CALL(http_encoding)
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+# ifdef ZEND_ENGINE_2
|
||
+ || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_datashare)
|
||
+# endif
|
||
+#endif
|
||
+ || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_method)
|
||
+ ) {
|
||
+ status = FAILURE;
|
||
+ }
|
||
+
|
||
+ http_globals_free(HTTP_G);
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ PHP_MINFO_FUNCTION */
|
||
+PHP_MINFO_FUNCTION(http)
|
||
+{
|
||
+ php_info_print_table_start();
|
||
+ {
|
||
+ php_info_print_table_header(2, "HTTP Support", "enabled");
|
||
+ php_info_print_table_row(2, "Extension Version", PHP_HTTP_VERSION);
|
||
+ php_info_print_table_row(2, "Registered Classes",
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ "none"
|
||
+#else
|
||
+ "HttpUtil, "
|
||
+ "HttpMessage, "
|
||
+# ifdef HTTP_HAVE_CURL
|
||
+ "HttpRequest, "
|
||
+ "HttpRequestPool, "
|
||
+ "HttpRequestDataShare, "
|
||
+# endif
|
||
+# ifdef HTTP_HAVE_ZLIB
|
||
+ "HttpDeflateStream, "
|
||
+ "HttpInflateStream, "
|
||
+# endif
|
||
+# ifndef WONKY
|
||
+ "HttpResponse, "
|
||
+# endif
|
||
+ "HttpQueryString"
|
||
+#endif
|
||
+ );
|
||
+ php_info_print_table_row(2, "Output Handlers", "ob_deflatehandler, ob_inflatehandler, ob_etaghandler");
|
||
+ php_info_print_table_row(2, "Stream Filters",
|
||
+#ifndef ZEND_ENGINE_2
|
||
+ "none"
|
||
+#else
|
||
+ "http.chunked_decode, http.chunked_encode, http.deflate, http.inflate"
|
||
+#endif
|
||
+ );
|
||
+ }
|
||
+ php_info_print_table_end();
|
||
+
|
||
+ php_info_print_table_start();
|
||
+ php_info_print_table_header(3, "Used Library", "Compiled", "Linked");
|
||
+ {
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+ curl_version_info_data *cv = curl_version_info(CURLVERSION_NOW);
|
||
+ php_info_print_table_row(3, "libcurl", LIBCURL_VERSION, cv->version);
|
||
+#else
|
||
+ php_info_print_table_row(2, "libcurl", "disabled", "disabled");
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+ php_info_print_table_row(3, "libevent", HTTP_EVENT_VERSION, event_get_version());
|
||
+#else
|
||
+ php_info_print_table_row(3, "libevent", "disabled", "disabled");
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ php_info_print_table_row(3, "libz", ZLIB_VERSION, zlibVersion());
|
||
+#else
|
||
+ php_info_print_table_row(3, "libz", "disabled", "disabled");
|
||
+#endif
|
||
+#if defined(HTTP_HAVE_MAGIC)
|
||
+ php_info_print_table_row(3, "libmagic", "unknown", "unknown");
|
||
+#else
|
||
+ php_info_print_table_row(3, "libmagic", "disabled", "disabled");
|
||
+#endif
|
||
+ }
|
||
+ php_info_print_table_end();
|
||
+
|
||
+ php_info_print_table_start();
|
||
+ php_info_print_table_colspan_header(4, "Persistent Handles");
|
||
+ php_info_print_table_header(4, "Provider", "Ident", "Used", "Free");
|
||
+ {
|
||
+ HashTable *ht;
|
||
+ HashPosition pos1, pos2;
|
||
+ HashKey provider = initHashKey(0), ident = initHashKey(0);
|
||
+ zval **val, **sub, **zused, **zfree;
|
||
+
|
||
+ if ((ht = http_persistent_handle_statall()) && zend_hash_num_elements(ht)) {
|
||
+ FOREACH_HASH_KEYVAL(pos1, ht, provider, val) {
|
||
+ if (zend_hash_num_elements(Z_ARRVAL_PP(val))) {
|
||
+ FOREACH_KEYVAL(pos2, *val, ident, sub) {
|
||
+ if ( SUCCESS == zend_hash_find(Z_ARRVAL_PP(sub), ZEND_STRS("used"), (void *) &zused) &&
|
||
+ SUCCESS == zend_hash_find(Z_ARRVAL_PP(sub), ZEND_STRS("free"), (void *) &zfree)) {
|
||
+ zval *used = http_zsep(IS_STRING, *zused);
|
||
+ zval *free = http_zsep(IS_STRING, *zfree);
|
||
+ php_info_print_table_row(4, provider.str, ident.str, Z_STRVAL_P(used), Z_STRVAL_P(free));
|
||
+ zval_ptr_dtor(&used);
|
||
+ zval_ptr_dtor(&free);
|
||
+ } else {
|
||
+ php_info_print_table_row(4, provider.str, ident.str, "0", "0");
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ php_info_print_table_row(4, provider.str, "N/A", "0", "0");
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ php_info_print_table_row(4, "N/A", "N/A", "0", "0");
|
||
+ }
|
||
+ if (ht) {
|
||
+ zend_hash_destroy(ht);
|
||
+ FREE_HASHTABLE(ht);
|
||
+ }
|
||
+ }
|
||
+ php_info_print_table_end();
|
||
+
|
||
+ php_info_print_table_start();
|
||
+ php_info_print_table_colspan_header(2, "Request Methods");
|
||
+ {
|
||
+ HashPosition pos;
|
||
+ phpstr *methods = phpstr_new();
|
||
+ char **name;
|
||
+
|
||
+ FOREACH_HASH_VAL(pos, &HTTP_G->request.methods.registered, name) {
|
||
+ if (pos->h) {
|
||
+ phpstr_appendf(methods, "%s, ", *name);
|
||
+ }
|
||
+ }
|
||
+ phpstr_fix(methods);
|
||
+ php_info_print_table_row(2, "Registered", PHPSTR_VAL(methods));
|
||
+ php_info_print_table_row(2, "Allowed", *HTTP_G->request.methods.allowed ? HTTP_G->request.methods.allowed : "(ANY)");
|
||
+ phpstr_free(&methods);
|
||
+ }
|
||
+ php_info_print_table_end();
|
||
+
|
||
+ DISPLAY_INI_ENTRIES();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http.dsp
|
||
@@ -0,0 +1,257 @@
|
||
+# Microsoft Developer Studio Project File - Name="http" - Package Owner=<4>
|
||
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||
+# ** DO NOT EDIT **
|
||
+
|
||
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||
+
|
||
+CFG=http - Win32 Release_TS
|
||
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||
+!MESSAGE use the Export Makefile command and run
|
||
+!MESSAGE
|
||
+!MESSAGE NMAKE /f "http.mak".
|
||
+!MESSAGE
|
||
+!MESSAGE You can specify a configuration when running NMAKE
|
||
+!MESSAGE by defining the macro CFG on the command line. For example:
|
||
+!MESSAGE
|
||
+!MESSAGE NMAKE /f "http.mak" CFG="http - Win32 Release_TS"
|
||
+!MESSAGE
|
||
+!MESSAGE Possible choices for configuration are:
|
||
+!MESSAGE
|
||
+!MESSAGE "http - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
|
||
+!MESSAGE "http - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
|
||
+!MESSAGE
|
||
+
|
||
+# Begin Project
|
||
+# PROP AllowPerConfigDependencies 0
|
||
+# PROP Scc_ProjName ""
|
||
+# PROP Scc_LocalPath ""
|
||
+CPP=cl.exe
|
||
+MTL=midl.exe
|
||
+RSC=rc.exe
|
||
+
|
||
+!IF "$(CFG)" == "http - Win32 Release_TS"
|
||
+
|
||
+# PROP BASE Use_MFC 0
|
||
+# PROP BASE Use_Debug_Libraries 0
|
||
+# PROP BASE Output_Dir "Release_TS"
|
||
+# PROP BASE Intermediate_Dir "Release_TS"
|
||
+# PROP BASE Ignore_Export_Lib 0
|
||
+# PROP BASE Target_Dir ""
|
||
+# PROP Use_MFC 0
|
||
+# PROP Use_Debug_Libraries 0
|
||
+# PROP Output_Dir "Release_TS"
|
||
+# PROP Intermediate_Dir "Release_TS"
|
||
+# PROP Ignore_Export_Lib 0
|
||
+# PROP Target_Dir ""
|
||
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_HTTP" /D ZTS=1 /YX /FD /c
|
||
+# ADD CPP /nologo /Gd /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HTTP_EXPORTS" /D "COMPILE_DL_HTTP" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_HTTP=1 /D HTTP_HAVE_CURL=1 /D HAVE_CURL_EASY_STRERROR=1 /D HAVE_CURL_SHARE_STRERROR=1 /D HAVE_CURL_MULTI_STRERROR=1 /D HAVE_CURL_EASY_RESET=1 /D HAVE_CURL_FORMGET=1 /D HAVE_GETHOSTNAME=1 /D HAVE_GETSERVBYPORT=1 /D HAVE_GETSERVBYNAME=1 /D "_WINSOCKAPI_=" /FR /YX /FD /c
|
||
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
|
||
+# ADD RSC /l 0x406 /d "NDEBUG"
|
||
+BSC32=bscmake.exe
|
||
+# ADD BASE BSC32 /nologo
|
||
+# ADD BSC32 /nologo
|
||
+LINK32=link.exe
|
||
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386
|
||
+# ADD LINK32 libcurl.lib ssleay32.lib libeay32.lib zlib.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib wsock32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_http.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" /libpath:"..\..\..\php_build\curl\lib" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline"
|
||
+
|
||
+!ELSEIF "$(CFG)" == "http - Win32 Debug_TS"
|
||
+
|
||
+# PROP BASE Use_MFC 0
|
||
+# PROP BASE Use_Debug_Libraries 0
|
||
+# PROP BASE Output_Dir "Debug_TS"
|
||
+# PROP BASE Intermediate_Dir "Debug_TS"
|
||
+# PROP BASE Ignore_Export_Lib 0
|
||
+# PROP BASE Target_Dir ""
|
||
+# PROP Use_MFC 0
|
||
+# PROP Use_Debug_Libraries 0
|
||
+# PROP Output_Dir "Debug_TS"
|
||
+# PROP Intermediate_Dir "Debug_TS"
|
||
+# PROP Ignore_Export_Lib 0
|
||
+# PROP Target_Dir ""
|
||
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_HTTP" /D ZTS=1 /YX /FD /c
|
||
+# ADD CPP /nologo /MDd /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HTTP_EXPORTS" /D "COMPILE_DL_HTTP" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_HTTP=1 /D HTTP_HAVE_CURL=1 /D HAVE_CURL_EASY_STRERROR=1 /D HAVE_CURL_SHARE_STRERROR=1 /D HAVE_CURL_MULTI_STRERROR=1 /D HAVE_CURL_EASY_RESET=1 /D HAVE_CURL_FORMGET=1 /D HAVE_GETHOSTNAME=1 /D HAVE_GETSERVBYPORT=1 /D HAVE_GETSERVBYNAME=1 /D "_WINSOCKAPI_=" /YX /FD /c
|
||
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
|
||
+# ADD RSC /l 0x406 /d "NDEBUG"
|
||
+BSC32=bscmake.exe
|
||
+# ADD BASE BSC32 /nologo
|
||
+# ADD BSC32 /nologo
|
||
+LINK32=link.exe
|
||
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386
|
||
+# ADD LINK32 libcurl.lib ssleay32.lib libeay32.lib zlib.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts_debug.lib wsock32.lib /nologo /dll /machine:I386 /out:"..\..\Debug_TS/http.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\curl\lib" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline"
|
||
+
|
||
+!ENDIF
|
||
+
|
||
+# Begin Target
|
||
+
|
||
+# Name "http - Win32 Release_TS"
|
||
+# Name "http - Win32 Debug_TS"
|
||
+# Begin Group "Source Files"
|
||
+
|
||
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_encoding_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_request_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_request_info.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_request_body_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_request_method_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_functions.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_persistent_handle_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_cache_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_cookie_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_date_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_headers_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_message_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_send_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_url_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_querystring_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\http_info_api.c
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\phpstr\phpstr.c
|
||
+# End Source File
|
||
+# End Group
|
||
+# Begin Group "Header Files"
|
||
+
|
||
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_encoding_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_request_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_request_int.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_request_body_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_request_method_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_persistent_handle_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_cache_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_cookie_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_date_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_message_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_send_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_headers_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_url_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_querystring_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_info_api.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\php_http_std_defs.h
|
||
+# End Source File
|
||
+# Begin Source File
|
||
+
|
||
+SOURCE=.\phpstr\phpstr.h
|
||
+# End Source File
|
||
+# End Group
|
||
+# Begin Group "Resource Files"
|
||
+
|
||
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||
+# End Group
|
||
+# End Target
|
||
+# End Project
|
||
--- /dev/null
|
||
+++ b/ext/http/http_api.c
|
||
@@ -0,0 +1,745 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_api.c 310302 2011-04-18 08:24:49Z rrichards $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_output.h"
|
||
+#include "ext/standard/url.h"
|
||
+#include "ext/standard/php_lcg.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+# include "php_http_exception_object.h"
|
||
+#endif
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_support)
|
||
+{
|
||
+ HTTP_LONG_CONSTANT("HTTP_SUPPORT", HTTP_SUPPORT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_REQUESTS", HTTP_SUPPORT_REQUESTS);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_MAGICMIME", HTTP_SUPPORT_MAGICMIME);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_ENCODINGS", HTTP_SUPPORT_ENCODINGS);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_SSLREQUESTS", HTTP_SUPPORT_SSLREQUESTS);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_EVENTS", HTTP_SUPPORT_EVENTS);
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_COMMA", HTTP_PARAMS_ALLOW_COMMA);
|
||
+ HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_FAILURE", HTTP_PARAMS_ALLOW_FAILURE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_PARAMS_RAISE_ERROR", HTTP_PARAMS_RAISE_ERROR);
|
||
+ HTTP_LONG_CONSTANT("HTTP_PARAMS_DEFAULT", HTTP_PARAMS_DEFAULT);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API long _http_support(long feature)
|
||
+{
|
||
+ long support = HTTP_SUPPORT;
|
||
+
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+ support |= HTTP_SUPPORT_REQUESTS;
|
||
+# ifdef HTTP_HAVE_SSL
|
||
+ support |= HTTP_SUPPORT_SSLREQUESTS;
|
||
+# endif
|
||
+# ifdef HTTP_HAVE_EVENT
|
||
+ support |= HTTP_SUPPORT_EVENTS;
|
||
+# endif
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_MAGIC
|
||
+ support |= HTTP_SUPPORT_MAGICMIME;
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ support |= HTTP_SUPPORT_ENCODINGS;
|
||
+#endif
|
||
+
|
||
+ if (feature) {
|
||
+ return (feature == (support & feature));
|
||
+ }
|
||
+ return support;
|
||
+}
|
||
+
|
||
+/* char *pretty_key(char *, size_t, zend_bool, zend_bool) */
|
||
+char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
|
||
+{
|
||
+ size_t i;
|
||
+ int wasalpha;
|
||
+
|
||
+ if (key && key_len) {
|
||
+ if ((wasalpha = HTTP_IS_CTYPE(alpha, key[0]))) {
|
||
+ key[0] = (char) (uctitle ? HTTP_TO_CTYPE(upper, key[0]) : HTTP_TO_CTYPE(lower, key[0]));
|
||
+ }
|
||
+ for (i = 1; i < key_len; i++) {
|
||
+ if (HTTP_IS_CTYPE(alpha, key[i])) {
|
||
+ key[i] = (char) (((!wasalpha) && uctitle) ? HTTP_TO_CTYPE(upper, key[i]) : HTTP_TO_CTYPE(lower, key[i]));
|
||
+ wasalpha = 1;
|
||
+ } else {
|
||
+ if (xhyphen && (key[i] == '_')) {
|
||
+ key[i] = '-';
|
||
+ }
|
||
+ wasalpha = 0;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ return key;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_boundary(char *, size_t) */
|
||
+size_t _http_boundary(char *buf, size_t buf_len TSRMLS_DC)
|
||
+{
|
||
+ return snprintf(buf, buf_len, "%lu%0.9f", (ulong) HTTP_G->request.time, (float) php_combined_lcg(TSRMLS_C));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_error(long, long, char*) */
|
||
+void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...)
|
||
+{
|
||
+ va_list args;
|
||
+
|
||
+ va_start(args, format);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if ((type == E_THROW) || (GLOBAL_ERROR_HANDLING == EH_THROW)) {
|
||
+ char *message;
|
||
+ zend_class_entry *ce = http_exception_get_for_code(code);
|
||
+
|
||
+ http_try {
|
||
+ vspprintf(&message, 0, format, args);
|
||
+ zend_throw_exception(ce, message, code TSRMLS_CC);
|
||
+ efree(message);
|
||
+ } http_catch(GLOBAL_EXCEPTION_CLASS ? GLOBAL_EXCEPTION_CLASS : HTTP_EX_DEF_CE);
|
||
+ } else
|
||
+#endif
|
||
+ php_verror(NULL, "", type, format, args TSRMLS_CC);
|
||
+ va_end(args);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+static inline void copy_bt_args(zval *from, zval *to TSRMLS_DC)
|
||
+{
|
||
+ zval **args, **trace_0, *old_trace_0, *trace = NULL;
|
||
+
|
||
+ if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), from, "trace", lenof("trace"), 0 TSRMLS_CC))) {
|
||
+ if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) {
|
||
+ old_trace_0 = *trace_0;
|
||
+ if (Z_TYPE_PP(trace_0) == IS_ARRAY && SUCCESS == zend_hash_find(Z_ARRVAL_PP(trace_0), "args", sizeof("args"), (void *) &args)) {
|
||
+ if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), to, "trace", lenof("trace"), 0 TSRMLS_CC))) {
|
||
+ if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) {
|
||
+ ZVAL_ADDREF(*args);
|
||
+ add_assoc_zval(*trace_0, "args", *args);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/* {{{ zval *http_exception_wrap(zval *, zval *, zend_class_entry *) */
|
||
+zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ int inner = 1;
|
||
+ char *message;
|
||
+ zval *sub_exception, *tmp_exception;
|
||
+
|
||
+ if (!new_exception) {
|
||
+ MAKE_STD_ZVAL(new_exception);
|
||
+ object_init_ex(new_exception, ce);
|
||
+
|
||
+ zend_update_property(ce, new_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC);
|
||
+ copy_bt_args(old_exception, new_exception TSRMLS_CC);
|
||
+
|
||
+ sub_exception = old_exception;
|
||
+
|
||
+ while ((sub_exception = zend_read_property(Z_OBJCE_P(sub_exception), sub_exception, "innerException", lenof("innerException"), 0 TSRMLS_CC)) && Z_TYPE_P(sub_exception) == IS_OBJECT) {
|
||
+ ++inner;
|
||
+ }
|
||
+
|
||
+ spprintf(&message, 0, "Exception caused by %d inner exception(s)", inner);
|
||
+ zend_update_property_string(ZEND_EXCEPTION_GET_DEFAULT(), new_exception, "message", lenof("message"), message TSRMLS_CC);
|
||
+ efree(message);
|
||
+ } else {
|
||
+ sub_exception = new_exception;
|
||
+ tmp_exception = new_exception;
|
||
+
|
||
+ while ((tmp_exception = zend_read_property(Z_OBJCE_P(tmp_exception), tmp_exception, "innerException", lenof("innerException"), 0 TSRMLS_CC)) && Z_TYPE_P(tmp_exception) == IS_OBJECT) {
|
||
+ sub_exception = tmp_exception;
|
||
+ }
|
||
+
|
||
+ zend_update_property(Z_OBJCE_P(sub_exception), sub_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC);
|
||
+ copy_bt_args(old_exception, new_exception TSRMLS_CC);
|
||
+ copy_bt_args(old_exception, sub_exception TSRMLS_CC);
|
||
+ }
|
||
+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
|
||
+ Z_ADDREF_P(old_exception);
|
||
+ zend_exception_set_previous(new_exception, old_exception TSRMLS_CC);
|
||
+#endif
|
||
+ zval_ptr_dtor(&old_exception);
|
||
+ return new_exception;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_object_new(zend_object_value *, const char *, uint, http_object_new_t, zend_class_entry *, void *, void **) */
|
||
+STATUS _http_object_new(zend_object_value *ov, const char *cname_str, uint cname_len, http_object_new_t create, zend_class_entry *parent_ce, void *intern_ptr, void **obj_ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_class_entry *ce = parent_ce;
|
||
+
|
||
+ if (cname_str && cname_len) {
|
||
+ if (!(ce = zend_fetch_class(HTTP_ZAPI_CONST_CAST(char *) cname_str, cname_len, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC))) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ if (!instanceof_function(ce, parent_ce TSRMLS_CC)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Class %s does not extend %s", cname_str, parent_ce->name);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ *ov = create(ce, intern_ptr, obj_ptr TSRMLS_CC);
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+#endif /* ZEND_ENGINE_2 */
|
||
+
|
||
+/* {{{ void http_log(char *, char *, char *) */
|
||
+void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC)
|
||
+{
|
||
+ time_t now;
|
||
+ struct tm nowtm;
|
||
+ char datetime[20] = {0};
|
||
+
|
||
+ now = HTTP_G->request.time;
|
||
+ strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", php_localtime_r(&now, &nowtm));
|
||
+
|
||
+#define HTTP_LOG_WRITE(file, type, msg) \
|
||
+ if (file && *file) { \
|
||
+ php_stream *log = php_stream_open_wrapper_ex(file, "ab", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT); \
|
||
+ \
|
||
+ if (log) { \
|
||
+ php_stream_printf(log TSRMLS_CC, "%s\t[%s]\t%s\t<%s>%s", datetime, type, msg, SG(request_info).request_uri, PHP_EOL); \
|
||
+ php_stream_close(log); \
|
||
+ } \
|
||
+ \
|
||
+ }
|
||
+
|
||
+ HTTP_LOG_WRITE(file, ident, message);
|
||
+ HTTP_LOG_WRITE(HTTP_G->log.composite, ident, message);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+static void http_ob_blackhole(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
|
||
+{
|
||
+ *handled_output = ecalloc(1,1);
|
||
+ *handled_output_len = 0;
|
||
+}
|
||
+
|
||
+/* {{{ STATUS http_exit(int, char*, char*) */
|
||
+STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC)
|
||
+{
|
||
+ if ( (send_header && (SUCCESS != http_send_status_header(status, header))) ||
|
||
+ (status && (SUCCESS != http_send_status(status)))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Failed to exit with status/header: %d - %s", status, STR_PTR(header));
|
||
+ STR_FREE(header);
|
||
+ STR_FREE(body);
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (!php_ob_handler_used("zlib output compression") && !php_ob_handler_used("ob_gzhandler") && !OG(ob_lock)) {
|
||
+ php_end_ob_buffers(0 TSRMLS_CC);
|
||
+ }
|
||
+ if ((SUCCESS == sapi_send_headers(TSRMLS_C)) && body) {
|
||
+ PHPWRITE(body, strlen(body));
|
||
+ }
|
||
+
|
||
+ switch (status) {
|
||
+ case 301: http_log(HTTP_G->log.redirect, "301-REDIRECT", header); break;
|
||
+ case 302: http_log(HTTP_G->log.redirect, "302-REDIRECT", header); break;
|
||
+ case 303: http_log(HTTP_G->log.redirect, "303-REDIRECT", header); break;
|
||
+ case 305: http_log(HTTP_G->log.redirect, "305-REDIRECT", header); break;
|
||
+ case 307: http_log(HTTP_G->log.redirect, "307-REDIRECT", header); break;
|
||
+ case 304: http_log(HTTP_G->log.cache, "304-CACHE", header); break;
|
||
+ case 404: http_log(HTTP_G->log.not_found, "404-NOTFOUND", NULL); break;
|
||
+ case 405: http_log(HTTP_G->log.allowed_methods, "405-ALLOWED", header); break;
|
||
+ default: http_log(NULL, header, body); break;
|
||
+ }
|
||
+
|
||
+ STR_FREE(header);
|
||
+ STR_FREE(body);
|
||
+
|
||
+ if (HTTP_G->force_exit) {
|
||
+ zend_bailout();
|
||
+ } else {
|
||
+ php_ob_set_internal_handler(http_ob_blackhole, 4096, "blackhole", 0 TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_check_method(char *) */
|
||
+STATUS _http_check_method_ex(const char *method, const char *methods)
|
||
+{
|
||
+ const char *found;
|
||
+
|
||
+ if ( (found = strstr(methods, method)) &&
|
||
+ (found == method || !HTTP_IS_CTYPE(alpha, found[-1])) &&
|
||
+ (strlen(found) >= strlen(method) && !HTTP_IS_CTYPE(alpha, found[strlen(method)]))) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ zval *http_get_server_var_ex(char *, size_t) */
|
||
+PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC)
|
||
+{
|
||
+ zval **hsv, **var;
|
||
+ char *env;
|
||
+
|
||
+ /* if available, this is a lot faster than accessing $_SERVER */
|
||
+ if (sapi_module.getenv) {
|
||
+ if ((!(env = sapi_module.getenv((char *) key, key_len TSRMLS_CC))) || (check && !*env)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ if (HTTP_G->server_var) {
|
||
+ zval_ptr_dtor(&HTTP_G->server_var);
|
||
+ }
|
||
+ MAKE_STD_ZVAL(HTTP_G->server_var);
|
||
+ ZVAL_STRING(HTTP_G->server_var, env, 1);
|
||
+ return HTTP_G->server_var;
|
||
+ }
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
|
||
+#endif
|
||
+
|
||
+ if ((SUCCESS != zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(hsv), HTTP_ZAPI_CONST_CAST(char *) key, key_len + 1, (void *) &var))) {
|
||
+ return NULL;
|
||
+ }
|
||
+ if (check && !((Z_TYPE_PP(var) == IS_STRING) && Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
|
||
+ return NULL;
|
||
+ }
|
||
+ return *var;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_get_request_body(char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC)
|
||
+{
|
||
+ *length = 0;
|
||
+ *body = NULL;
|
||
+
|
||
+ if (SG(request_info).raw_post_data) {
|
||
+ *length = SG(request_info).raw_post_data_length;
|
||
+ *body = SG(request_info).raw_post_data;
|
||
+
|
||
+ if (dup) {
|
||
+ *body = estrndup(*body, *length);
|
||
+ }
|
||
+ return SUCCESS;
|
||
+ } else if (sapi_module.read_post && !HTTP_G->read_post_data) {
|
||
+ char *buf = emalloc(4096);
|
||
+ int len;
|
||
+
|
||
+ HTTP_G->read_post_data = 1;
|
||
+
|
||
+ while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
|
||
+ SG(read_post_bytes) += len;
|
||
+ *body = erealloc(*body, *length + len + 1);
|
||
+ memcpy(*body + *length, buf, len);
|
||
+ *length += len;
|
||
+ (*body)[*length] = '\0';
|
||
+ if (len < 4096) {
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ efree(buf);
|
||
+
|
||
+ /* check for error */
|
||
+ if (len < 0) {
|
||
+ STR_FREE(*body);
|
||
+ *length = 0;
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ SG(request_info).raw_post_data = *body;
|
||
+ SG(request_info).raw_post_data_length = *length;
|
||
+
|
||
+ if (dup) {
|
||
+ *body = estrndup(*body, *length);
|
||
+ }
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ php_stream *http_get_request_body_stream(void) */
|
||
+PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D)
|
||
+{
|
||
+ php_stream *s = NULL;
|
||
+
|
||
+ if (SG(request_info).raw_post_data) {
|
||
+ s = php_stream_open_wrapper("php://input", "rb", 0, NULL);
|
||
+ } else if (sapi_module.read_post && !HTTP_G->read_post_data) {
|
||
+ HTTP_G->read_post_data = 1;
|
||
+
|
||
+ if ((s = php_stream_temp_new())) {
|
||
+ char *buf = emalloc(4096);
|
||
+ int len;
|
||
+
|
||
+ while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
|
||
+ php_stream_write(s, buf, len);
|
||
+ if (len < 4096) {
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ efree(buf);
|
||
+
|
||
+ if (len < 0) {
|
||
+ php_stream_close(s);
|
||
+ s = NULL;
|
||
+ } else {
|
||
+ php_stream_rewind(s);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return s;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_parse_params_default_callback(...) */
|
||
+PHP_HTTP_API void _http_parse_params_default_callback(void *arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
|
||
+{
|
||
+ char *kdup;
|
||
+ zval tmp, *entry;
|
||
+ HashTable *ht = (HashTable *) arg;
|
||
+
|
||
+ if (ht) {
|
||
+ INIT_ZARR(tmp, ht);
|
||
+
|
||
+ if (vallen) {
|
||
+ MAKE_STD_ZVAL(entry);
|
||
+ array_init(entry);
|
||
+ if (keylen) {
|
||
+ kdup = estrndup(key, keylen);
|
||
+ add_assoc_stringl_ex(entry, kdup, keylen + 1, (char *) val, vallen, 1);
|
||
+ efree(kdup);
|
||
+ } else {
|
||
+ add_next_index_stringl(entry, (char *) val, vallen, 1);
|
||
+ }
|
||
+ add_next_index_zval(&tmp, entry);
|
||
+ } else {
|
||
+ add_next_index_stringl(&tmp, (char *) key, keylen, 1);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_parse_params(const char *, HashTable *) */
|
||
+PHP_HTTP_API STATUS _http_parse_params_ex(const char *param, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC)
|
||
+{
|
||
+#define ST_QUOTE 1
|
||
+#define ST_VALUE 2
|
||
+#define ST_KEY 3
|
||
+#define ST_ASSIGN 4
|
||
+#define ST_ADD 5
|
||
+
|
||
+ int st = ST_KEY, keylen = 0, vallen = 0;
|
||
+ char *s, *c, *key = NULL, *val = NULL;
|
||
+
|
||
+ for(c = s = estrdup(param);;) {
|
||
+ continued:
|
||
+#if 0
|
||
+ {
|
||
+ char *tk = NULL, *tv = NULL;
|
||
+
|
||
+ if (key) {
|
||
+ if (keylen) {
|
||
+ tk= estrndup(key, keylen);
|
||
+ } else {
|
||
+ tk = ecalloc(1, 7);
|
||
+ memcpy(tk, key, 3);
|
||
+ tk[3]='.'; tk[4]='.'; tk[5]='.';
|
||
+ }
|
||
+ }
|
||
+ if (val) {
|
||
+ if (vallen) {
|
||
+ tv = estrndup(val, vallen);
|
||
+ } else {
|
||
+ tv = ecalloc(1, 7);
|
||
+ memcpy(tv, val, 3);
|
||
+ tv[3]='.'; tv[4]='.'; tv[5]='.';
|
||
+ }
|
||
+ }
|
||
+ fprintf(stderr, "[%6s] %c \"%s=%s\"\n",
|
||
+ (
|
||
+ st == ST_QUOTE ? "QUOTE" :
|
||
+ st == ST_VALUE ? "VALUE" :
|
||
+ st == ST_KEY ? "KEY" :
|
||
+ st == ST_ASSIGN ? "ASSIGN" :
|
||
+ st == ST_ADD ? "ADD":
|
||
+ "HUH?"
|
||
+ ), *c?*c:'0', tk, tv
|
||
+ );
|
||
+ STR_FREE(tk); STR_FREE(tv);
|
||
+ }
|
||
+#endif
|
||
+ switch (st) {
|
||
+ case ST_QUOTE:
|
||
+ quote:
|
||
+ if (*c == '"') {
|
||
+ if (*(c-1) == '\\') {
|
||
+ memmove(c-1, c, strlen(c)+1);
|
||
+ goto quote;
|
||
+ } else {
|
||
+ goto add;
|
||
+ }
|
||
+ } else {
|
||
+ if (!val) {
|
||
+ val = c;
|
||
+ }
|
||
+ if (!*c) {
|
||
+ --val;
|
||
+ st = ST_ADD;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case ST_VALUE:
|
||
+ switch (*c) {
|
||
+ case '"':
|
||
+ if (!val) {
|
||
+ st = ST_QUOTE;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case ' ':
|
||
+ break;
|
||
+
|
||
+ case ';':
|
||
+ case '\0':
|
||
+ goto add;
|
||
+ break;
|
||
+ case ',':
|
||
+ if (flags & HTTP_PARAMS_ALLOW_COMMA) {
|
||
+ goto add;
|
||
+ }
|
||
+ default:
|
||
+ if (!val) {
|
||
+ val = c;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case ST_KEY:
|
||
+ switch (*c) {
|
||
+ case ',':
|
||
+ if (flags & HTTP_PARAMS_ALLOW_COMMA) {
|
||
+ goto allow_comma;
|
||
+ }
|
||
+ case '\r':
|
||
+ case '\n':
|
||
+ case '\t':
|
||
+ case '\013':
|
||
+ case '\014':
|
||
+ goto failure;
|
||
+ break;
|
||
+
|
||
+ case ' ':
|
||
+ if (key) {
|
||
+ keylen = c - key;
|
||
+ st = ST_ASSIGN;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case ';':
|
||
+ case '\0':
|
||
+ allow_comma:
|
||
+ if (key) {
|
||
+ keylen = c-- - key;
|
||
+ st = ST_ADD;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case ':':
|
||
+ if (!(flags & HTTP_PARAMS_COLON_SEPARATOR)) {
|
||
+ goto not_separator;
|
||
+ }
|
||
+ if (key) {
|
||
+ keylen = c - key;
|
||
+ st = ST_VALUE;
|
||
+ } else {
|
||
+ goto failure;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case '=':
|
||
+ if (flags & HTTP_PARAMS_COLON_SEPARATOR) {
|
||
+ goto not_separator;
|
||
+ }
|
||
+ if (key) {
|
||
+ keylen = c - key;
|
||
+ st = ST_VALUE;
|
||
+ } else {
|
||
+ goto failure;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ not_separator:
|
||
+ if (!key) {
|
||
+ key = c;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case ST_ASSIGN:
|
||
+ if (*c == '=') {
|
||
+ st = ST_VALUE;
|
||
+ } else if (!*c || *c == ';' || ((flags & HTTP_PARAMS_ALLOW_COMMA) && *c == ',')) {
|
||
+ st = ST_ADD;
|
||
+ } else if (*c != ' ') {
|
||
+ goto failure;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case ST_ADD:
|
||
+ add:
|
||
+ if (val) {
|
||
+ vallen = c - val;
|
||
+ if (st != ST_QUOTE) {
|
||
+ while (val[vallen-1] == ' ') --vallen;
|
||
+ }
|
||
+ } else {
|
||
+ val = "";
|
||
+ vallen = 0;
|
||
+ }
|
||
+
|
||
+ cb(cb_arg, key, keylen, val, vallen TSRMLS_CC);
|
||
+
|
||
+ st = ST_KEY;
|
||
+ key = val = NULL;
|
||
+ keylen = vallen = 0;
|
||
+ break;
|
||
+ }
|
||
+ if (*c) {
|
||
+ ++c;
|
||
+ } else if (st == ST_ADD) {
|
||
+ goto add;
|
||
+ } else {
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ efree(s);
|
||
+ return SUCCESS;
|
||
+
|
||
+failure:
|
||
+ if (flags & HTTP_PARAMS_RAISE_ERROR) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Unexpected character (%c) at pos %tu of %zu", *c, c-s, strlen(s));
|
||
+ }
|
||
+ if (flags & HTTP_PARAMS_ALLOW_FAILURE) {
|
||
+ if (st == ST_KEY) {
|
||
+ if (key) {
|
||
+ keylen = c - key;
|
||
+ } else {
|
||
+ key = c;
|
||
+ }
|
||
+ } else {
|
||
+ --c;
|
||
+ }
|
||
+ st = ST_ADD;
|
||
+ goto continued;
|
||
+ }
|
||
+ efree(s);
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ array_join */
|
||
+int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_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;
|
||
+
|
||
+ dst = va_arg(args, HashTable *);
|
||
+ flags = va_arg(args, int);
|
||
+
|
||
+ if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
|
||
+ if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
|
||
+ key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
|
||
+ zend_hash_find(dst, key, hash_key->nKeyLength, (void *) &data);
|
||
+ } else {
|
||
+ zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data);
|
||
+ }
|
||
+
|
||
+ ZVAL_ADDREF(*value);
|
||
+ if (data) {
|
||
+ add_next_index_zval(http_zset(IS_ARRAY, *data), *value);
|
||
+ } else if (key) {
|
||
+ zend_hash_add(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);
|
||
+ }
|
||
+
|
||
+ if (key) {
|
||
+ efree(key);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return ZEND_HASH_APPLY_KEEP;
|
||
+}
|
||
+
|
||
+int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
|
||
+{
|
||
+ int flags;
|
||
+ char *key = NULL;
|
||
+ HashTable *dst;
|
||
+ zval **value = (zval **) pDest;
|
||
+
|
||
+ dst = va_arg(args, HashTable *);
|
||
+ flags = va_arg(args, int);
|
||
+
|
||
+ if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
|
||
+ ZVAL_ADDREF(*value);
|
||
+ if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
|
||
+ key = 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);
|
||
+ efree(key);
|
||
+ } else {
|
||
+ zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) value, sizeof(zval *), NULL);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return ZEND_HASH_APPLY_KEEP;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_cache_api.c
|
||
@@ -0,0 +1,256 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_cache_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_output.h"
|
||
+#include "php_streams.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_cache_api.h"
|
||
+#include "php_http_date_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+
|
||
+/* {{{ char *http_etag(void *, size_t, http_send_mode) */
|
||
+PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC)
|
||
+{
|
||
+ void *ctx = http_etag_init();
|
||
+
|
||
+ if (data_mode == SEND_DATA) {
|
||
+ http_etag_update(ctx, data_ptr, data_len);
|
||
+ } else {
|
||
+ STATUS ss = FAILURE;
|
||
+ php_stream_statbuf ssb;
|
||
+
|
||
+ if (data_mode == SEND_RSRC) {
|
||
+ ss = php_stream_stat((php_stream *) data_ptr, &ssb);
|
||
+ } else {
|
||
+ ss = php_stream_stat_path((char *) data_ptr, &ssb);
|
||
+ }
|
||
+
|
||
+ if (SUCCESS != ss) {
|
||
+ efree(ctx);
|
||
+ return NULL;
|
||
+ } else {
|
||
+ size_t ssb_len;
|
||
+ char ssb_buf[128];
|
||
+
|
||
+ ssb_len = snprintf(ssb_buf, sizeof(ssb_buf), "%ld=%ld=%ld", (long) ssb.sb.st_mtime,
|
||
+ (long) ssb.sb.st_ino,
|
||
+ (long) ssb.sb.st_size);
|
||
+ http_etag_update(ctx, ssb_buf, ssb_len);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return http_etag_finish(ctx);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ time_t http_last_modified(void *, http_send_mode) */
|
||
+PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC)
|
||
+{
|
||
+ php_stream_statbuf ssb;
|
||
+
|
||
+ switch (data_mode) {
|
||
+ case SEND_DATA: return HTTP_G->request.time;
|
||
+ case SEND_RSRC: return php_stream_stat((php_stream *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime;
|
||
+ default: return php_stream_stat_path((char *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ zend_bool http_match_last_modified(char *, time_t) */
|
||
+PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC)
|
||
+{
|
||
+ zend_bool retval;
|
||
+ zval *zmodified;
|
||
+ char *modified, *chr_ptr;
|
||
+
|
||
+ if (!(zmodified = http_get_server_var(entry, 1))) {
|
||
+ return !enforce_presence;
|
||
+ }
|
||
+
|
||
+ modified = estrndup(Z_STRVAL_P(zmodified), Z_STRLEN_P(zmodified));
|
||
+ if ((chr_ptr = strrchr(modified, ';'))) {
|
||
+ chr_ptr = 0;
|
||
+ }
|
||
+
|
||
+ retval = (t <= http_parse_date_ex(modified, 1));
|
||
+ efree(modified);
|
||
+ return retval;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ zend_bool http_match_etag(char *, char *) */
|
||
+PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC)
|
||
+{
|
||
+ zval *zetag;
|
||
+ char *quoted_etag;
|
||
+ zend_bool result;
|
||
+
|
||
+ if (!(zetag = http_get_server_var_ex(entry, strlen(entry)+1, 1))) {
|
||
+ return !enforce_presence;
|
||
+ }
|
||
+
|
||
+ if (NULL != strchr(Z_STRVAL_P(zetag), '*')) {
|
||
+ return 1;
|
||
+ }
|
||
+
|
||
+ spprintf("ed_etag, 0, "\"%s\"", etag);
|
||
+ if (!strchr(Z_STRVAL_P(zetag), ',')) {
|
||
+ result = !strcmp(Z_STRVAL_P(zetag), quoted_etag);
|
||
+ } else {
|
||
+ result = (NULL != strstr(Z_STRVAL_P(zetag), quoted_etag));
|
||
+ }
|
||
+ efree(quoted_etag);
|
||
+
|
||
+ return result;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_cache_last_modified(time_t, time_t, char *, size_t) */
|
||
+PHP_HTTP_API STATUS _http_cache_last_modified(time_t last_modified,
|
||
+ time_t send_modified, const char *cache_control, size_t cc_len TSRMLS_DC)
|
||
+{
|
||
+ char *sent_header = NULL;
|
||
+
|
||
+ if (SG(headers_sent)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (SUCCESS != http_send_last_modified_ex(send_modified, &sent_header)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", last_modified)) {
|
||
+ http_exit_ex(304, sent_header, NULL, 0);
|
||
+ } else {
|
||
+ STR_FREE(sent_header);
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_cache_etag(char *, size_t, char *, size_t) */
|
||
+PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len,
|
||
+ const char *cache_control, size_t cc_len TSRMLS_DC)
|
||
+{
|
||
+ char *sent_header = NULL;
|
||
+
|
||
+ if (SG(headers_sent)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (etag_len) {
|
||
+ if (SUCCESS != http_send_etag_ex(etag, etag_len, &sent_header)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
|
||
+ http_exit_ex(304, sent_header, NULL, 0);
|
||
+ } else {
|
||
+ STR_FREE(sent_header);
|
||
+ }
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ /* start ob_etaghandler */
|
||
+ return http_start_ob_etaghandler();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D)
|
||
+{
|
||
+ /* already running? */
|
||
+ if (php_ob_handler_used("ob_etaghandler" TSRMLS_CC)) {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "ob_etaghandler can only be used once");
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ HTTP_G->etag.started = 1;
|
||
+ return php_start_ob_buffer_named("ob_etaghandler", HTTP_G->send.buffer_size, 0 TSRMLS_CC);
|
||
+}
|
||
+
|
||
+PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D)
|
||
+{
|
||
+ if (HTTP_G->etag.started) {
|
||
+ HTTP_G->etag.started = 0;
|
||
+ if (HTTP_G->etag.ctx) {
|
||
+ efree(HTTP_G->etag.ctx);
|
||
+ HTTP_G->etag.ctx = NULL;
|
||
+ }
|
||
+ return 1;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/* {{{ void http_ob_etaghandler(char *, uint, char **, uint *, int) */
|
||
+void _http_ob_etaghandler(char *output, uint output_len,
|
||
+ char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
|
||
+{
|
||
+ /* passthru */
|
||
+ *handled_output_len = output_len;
|
||
+ *handled_output = estrndup(output, output_len);
|
||
+
|
||
+ /* are we supposed to run? */
|
||
+ if (HTTP_G->etag.started) {
|
||
+ /* initialize the etag context */
|
||
+ if (mode & PHP_OUTPUT_HANDLER_START) {
|
||
+ HTTP_G->etag.ctx = http_etag_init();
|
||
+ }
|
||
+
|
||
+ /* update */
|
||
+ http_etag_update(HTTP_G->etag.ctx, output, output_len);
|
||
+
|
||
+ /* finish */
|
||
+ if (mode & PHP_OUTPUT_HANDLER_END) {
|
||
+ char *sent_header = NULL;
|
||
+ char *etag = http_etag_finish(HTTP_G->etag.ctx);
|
||
+
|
||
+ HTTP_G->etag.ctx = NULL;
|
||
+
|
||
+ http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
|
||
+ http_send_etag_ex(etag, strlen(etag), &sent_header);
|
||
+
|
||
+ if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
|
||
+ /* force exit; ob within ob does not work */
|
||
+ HTTP_G->force_exit = 1;
|
||
+ http_exit_ex(304, sent_header, etag, 0);
|
||
+ }
|
||
+
|
||
+ STR_FREE(sent_header);
|
||
+ STR_FREE(etag);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: sw=4 ts=4 fdm=marker
|
||
+ * vim<600: sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_cookie_api.c
|
||
@@ -0,0 +1,371 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_cookie_api.c 298662 2010-04-27 13:42:32Z mike $ */
|
||
+
|
||
+#include "php_http.h"
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_date_api.h"
|
||
+#include "php_http_cookie_api.h"
|
||
+
|
||
+#include "ext/standard/url.h"
|
||
+
|
||
+/* {{{ PHP_MINIT_FUNCTION(http_cookie) */
|
||
+PHP_MINIT_FUNCTION(http_cookie)
|
||
+{
|
||
+ HTTP_LONG_CONSTANT("HTTP_COOKIE_PARSE_RAW", HTTP_COOKIE_PARSE_RAW);
|
||
+ HTTP_LONG_CONSTANT("HTTP_COOKIE_SECURE", HTTP_COOKIE_SECURE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_COOKIE_HTTPONLY", HTTP_COOKIE_HTTPONLY);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_cookie_list *http_cookie_list_init(http_cookie_list *) */
|
||
+PHP_HTTP_API http_cookie_list *_http_cookie_list_init(http_cookie_list *list ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ if (!list) {
|
||
+ list = emalloc_rel(sizeof(http_cookie_list));
|
||
+ }
|
||
+
|
||
+ zend_hash_init(&list->cookies, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_init(&list->extras, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+
|
||
+ list->path = NULL;
|
||
+ list->domain = NULL;
|
||
+ list->expires = 0;
|
||
+ list->flags = 0;
|
||
+
|
||
+ return list;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_cookie_list_dtor(http_cookie_list *) */
|
||
+PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC)
|
||
+{
|
||
+ if (list) {
|
||
+ zend_hash_destroy(&list->cookies);
|
||
+ zend_hash_destroy(&list->extras);
|
||
+
|
||
+ STR_SET(list->path, NULL);
|
||
+ STR_SET(list->domain, NULL);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_cookie_list_free(http_cookie_list **) */
|
||
+PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC)
|
||
+{
|
||
+ if (list) {
|
||
+ http_cookie_list_dtor(*list);
|
||
+ efree(*list);
|
||
+ *list = NULL;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ const char *http_cookie_list_get_cookie(http_cookie_list *, const char*, size_t) */
|
||
+PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC)
|
||
+{
|
||
+ zval **cookie = NULL;
|
||
+ if ((SUCCESS != zend_hash_find(&list->cookies, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &cookie)) || (Z_TYPE_PP(cookie) != IS_STRING)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ return Z_STRVAL_PP(cookie);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ const char *http_cookie_list_get_extra(http_cookie_list *, const char *, size_t) */
|
||
+PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC)
|
||
+{
|
||
+ zval **extra = NULL;
|
||
+ if ((SUCCESS != zend_hash_find(&list->extras, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &extra)) || (Z_TYPE_PP(extra) != IS_STRING)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ return Z_STRVAL_PP(extra);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_cookie_list_add_cookie(http_cookie_list *, const char *, size_t, const char *, size_t) */
|
||
+PHP_HTTP_API void _http_cookie_list_add_cookie(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC)
|
||
+{
|
||
+ zval *cookie_value;
|
||
+ char *key = estrndup(name, name_len);
|
||
+ MAKE_STD_ZVAL(cookie_value);
|
||
+ ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
|
||
+ zend_hash_update(&list->cookies, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
|
||
+ efree(key);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_cookie_list_add_extr(http_cookie_list *, const char *, size_t, const char *, size_t) */
|
||
+PHP_HTTP_API void _http_cookie_list_add_extra(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC)
|
||
+{
|
||
+ zval *cookie_value;
|
||
+ char *key = estrndup(name, name_len);
|
||
+ MAKE_STD_ZVAL(cookie_value);
|
||
+ ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
|
||
+ zend_hash_update(&list->extras, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
|
||
+ efree(key);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+typedef struct _http_parse_param_cb_arg_t {
|
||
+ http_cookie_list *list;
|
||
+ long flags;
|
||
+ char **allowed_extras;
|
||
+} http_parse_param_cb_arg;
|
||
+
|
||
+/* {{{ static void http_parse_cookie_callback */
|
||
+static void http_parse_cookie_callback(void *ptr, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
|
||
+{
|
||
+ http_parse_param_cb_arg *arg = (http_parse_param_cb_arg *) ptr;
|
||
+
|
||
+#define _KEY_IS(s) (keylen == lenof(s) && !strncasecmp(key, (s), keylen))
|
||
+ if _KEY_IS("path") {
|
||
+ STR_SET(arg->list->path, estrndup(val, vallen));
|
||
+ } else if _KEY_IS("domain") {
|
||
+ STR_SET(arg->list->domain, estrndup(val, vallen));
|
||
+ } else if _KEY_IS("expires") {
|
||
+ char *date = estrndup(val, vallen);
|
||
+ arg->list->expires = http_parse_date(date);
|
||
+ efree(date);
|
||
+ } else if _KEY_IS("secure") {
|
||
+ arg->list->flags |= HTTP_COOKIE_SECURE;
|
||
+ } else if _KEY_IS("httpOnly") {
|
||
+ arg->list->flags |= HTTP_COOKIE_HTTPONLY;
|
||
+ } else {
|
||
+ /* check for extra */
|
||
+ if (arg->allowed_extras) {
|
||
+ char **ae = arg->allowed_extras;
|
||
+
|
||
+ for (; *ae; ++ae) {
|
||
+ if ((size_t) keylen == strlen(*ae) && !strncasecmp(key, *ae, keylen)) {
|
||
+ if (arg->flags & HTTP_COOKIE_PARSE_RAW) {
|
||
+ http_cookie_list_add_extra(arg->list, key, keylen, val, vallen);
|
||
+ } else {
|
||
+ char *dec = estrndup(val, vallen);
|
||
+ int declen = php_url_decode(dec, vallen);
|
||
+
|
||
+ http_cookie_list_add_extra(arg->list, key, keylen, dec, declen);
|
||
+ efree(dec);
|
||
+ }
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ /* new cookie */
|
||
+ if (arg->flags & HTTP_COOKIE_PARSE_RAW) {
|
||
+ http_cookie_list_add_cookie(arg->list, key, keylen, val, vallen);
|
||
+ } else {
|
||
+ char *dec = estrndup(val, vallen);
|
||
+ int declen = php_url_decode(dec, vallen);
|
||
+
|
||
+ http_cookie_list_add_cookie(arg->list, key, keylen, dec, declen);
|
||
+ efree(dec);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_cookie_list *http_parse_cookie(char *, long) */
|
||
+PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list *list, const char *string, long flags, char **allowed_extras TSRMLS_DC)
|
||
+{
|
||
+ int free_list = !list;
|
||
+ http_parse_param_cb_arg arg;
|
||
+
|
||
+ list = http_cookie_list_init(list);
|
||
+
|
||
+ arg.list = list;
|
||
+ arg.flags = flags;
|
||
+ arg.allowed_extras = allowed_extras;
|
||
+
|
||
+ if (SUCCESS != http_parse_params_ex(string, HTTP_PARAMS_RAISE_ERROR, http_parse_cookie_callback, &arg)) {
|
||
+ if (free_list) {
|
||
+ http_cookie_list_free(&list);
|
||
+ } else {
|
||
+ http_cookie_list_dtor(list);
|
||
+ }
|
||
+ list = NULL;
|
||
+ }
|
||
+
|
||
+ return list;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_cookie_list_tostruct(http_cookie_list *, zval *) */
|
||
+PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC)
|
||
+{
|
||
+ zval array, *cookies, *extras;
|
||
+
|
||
+ INIT_ZARR(array, HASH_OF(strct));
|
||
+
|
||
+ MAKE_STD_ZVAL(cookies);
|
||
+ array_init(cookies);
|
||
+ zend_hash_copy(Z_ARRVAL_P(cookies), &list->cookies, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ add_assoc_zval(&array, "cookies", cookies);
|
||
+
|
||
+ MAKE_STD_ZVAL(extras);
|
||
+ array_init(extras);
|
||
+ zend_hash_copy(Z_ARRVAL_P(extras), &list->extras, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ add_assoc_zval(&array, "extras", extras);
|
||
+
|
||
+ add_assoc_long(&array, "flags", list->flags);
|
||
+ add_assoc_long(&array, "expires", (long) list->expires);
|
||
+ add_assoc_string(&array, "path", STR_PTR(list->path), 1);
|
||
+ add_assoc_string(&array, "domain", STR_PTR(list->domain), 1);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_cookie_list *http_cookie_list_fromstruct(http_cookie_list *, zval *strct) */
|
||
+PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC)
|
||
+{
|
||
+ zval **tmp, *cpy;
|
||
+ HashTable *ht = HASH_OF(strct);
|
||
+
|
||
+ list = http_cookie_list_init(list);
|
||
+
|
||
+ if (SUCCESS == zend_hash_find(ht, "cookies", sizeof("cookies"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
|
||
+ zend_hash_copy(&list->cookies, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ }
|
||
+ if (SUCCESS == zend_hash_find(ht, "extras", sizeof("extras"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
|
||
+ zend_hash_copy(&list->extras, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ }
|
||
+ if (SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &tmp)) {
|
||
+ switch (Z_TYPE_PP(tmp)) {
|
||
+ case IS_LONG:
|
||
+ list->flags = Z_LVAL_PP(tmp);
|
||
+ break;
|
||
+ case IS_DOUBLE:
|
||
+ list->flags = (long) Z_DVAL_PP(tmp);
|
||
+ break;
|
||
+ case IS_STRING:
|
||
+ cpy = http_zsep(IS_LONG, *tmp);
|
||
+ list->flags = Z_LVAL_P(cpy);
|
||
+ zval_ptr_dtor(&cpy);
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ if (SUCCESS == zend_hash_find(ht, "expires", sizeof("expires"), (void *) &tmp)) {
|
||
+ switch (Z_TYPE_PP(tmp)) {
|
||
+ case IS_LONG:
|
||
+ list->expires = Z_LVAL_PP(tmp);
|
||
+ break;
|
||
+ case IS_DOUBLE:
|
||
+ list->expires = (long) Z_DVAL_PP(tmp);
|
||
+ break;
|
||
+ case IS_STRING:
|
||
+ cpy = http_zsep(IS_LONG, *tmp);
|
||
+ if (Z_LVAL_P(cpy)) {
|
||
+ list->expires = Z_LVAL_P(cpy);
|
||
+ } else {
|
||
+ time_t expires = http_parse_date(Z_STRVAL_PP(tmp));
|
||
+ if (expires > 0) {
|
||
+ list->expires = expires;
|
||
+ }
|
||
+ }
|
||
+ zval_ptr_dtor(&cpy);
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
|
||
+ list->path = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
|
||
+ }
|
||
+ if (SUCCESS == zend_hash_find(ht, "domain", sizeof("domain"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
|
||
+ list->domain = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
|
||
+ }
|
||
+
|
||
+ return list;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ inline append_encoded */
|
||
+static inline void append_encoded(phpstr *buf, const char *key, size_t key_len, const char *val, size_t val_len)
|
||
+{
|
||
+ char *enc_str[2];
|
||
+ int enc_len[2];
|
||
+
|
||
+ enc_str[0] = php_url_encode(key, key_len, &enc_len[0]);
|
||
+ enc_str[1] = php_url_encode(val, val_len, &enc_len[1]);
|
||
+
|
||
+ phpstr_append(buf, enc_str[0], enc_len[0]);
|
||
+ phpstr_appends(buf, "=");
|
||
+ phpstr_append(buf, enc_str[1], enc_len[1]);
|
||
+ phpstr_appends(buf, "; ");
|
||
+
|
||
+ efree(enc_str[0]);
|
||
+ efree(enc_str[1]);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_cookie_list_tostring(http_cookie_list *, char **, size_t *) */
|
||
+PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC)
|
||
+{
|
||
+ phpstr buf;
|
||
+ zval **val;
|
||
+ HashKey key = initHashKey(0);
|
||
+ HashPosition pos;
|
||
+
|
||
+ phpstr_init(&buf);
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos, &list->cookies, key, val) {
|
||
+ if (key.type == HASH_KEY_IS_STRING && key.len) {
|
||
+ zval *tmp = http_zsep(IS_STRING, *val);
|
||
+ append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
|
||
+ zval_ptr_dtor(&tmp);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (list->domain && *list->domain) {
|
||
+ phpstr_appendf(&buf, "domain=%s; ", list->domain);
|
||
+ }
|
||
+ if (list->path && *list->path) {
|
||
+ phpstr_appendf(&buf, "path=%s; ", list->path);
|
||
+ }
|
||
+ if (list->expires) {
|
||
+ char *date = http_date(list->expires);
|
||
+ phpstr_appendf(&buf, "expires=%s; ", date);
|
||
+ efree(date);
|
||
+ }
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) {
|
||
+ if (key.type == HASH_KEY_IS_STRING && key.len) {
|
||
+ zval *tmp = http_zsep(IS_STRING, *val);
|
||
+ append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (list->flags & HTTP_COOKIE_SECURE) {
|
||
+ phpstr_appends(&buf, "secure; ");
|
||
+ }
|
||
+ if (list->flags & HTTP_COOKIE_HTTPONLY) {
|
||
+ phpstr_appends(&buf, "httpOnly; ");
|
||
+ }
|
||
+
|
||
+ phpstr_fix(&buf);
|
||
+ *str = PHPSTR_VAL(&buf);
|
||
+ *len = PHPSTR_LEN(&buf);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/http_date_api.c
|
||
@@ -0,0 +1,357 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_date_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_date_api.h"
|
||
+
|
||
+static inline int check_day(const char *day, size_t len);
|
||
+static inline int check_month(const char *month);
|
||
+static inline int check_tzone(const char *tzone);
|
||
+static inline time_t parse_date(const char *month);
|
||
+
|
||
+/* {{{ day/month names */
|
||
+static const char *days[] = {
|
||
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||
+};
|
||
+static const char *wkdays[] = {
|
||
+ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
|
||
+};
|
||
+static const char *weekdays[] = {
|
||
+ "Monday", "Tuesday", "Wednesday",
|
||
+ "Thursday", "Friday", "Saturday", "Sunday"
|
||
+};
|
||
+static const char *months[] = {
|
||
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||
+};
|
||
+enum assume_next {
|
||
+ DATE_MDAY,
|
||
+ DATE_YEAR,
|
||
+ DATE_TIME
|
||
+};
|
||
+#define DS -60
|
||
+static const struct time_zone {
|
||
+ const char *name;
|
||
+ const int offset;
|
||
+} time_zones[] = {
|
||
+ {"GMT", 0}, /* Greenwich Mean */
|
||
+ {"UTC", 0}, /* Universal (Coordinated) */
|
||
+ {"WET", 0}, /* Western European */
|
||
+ {"BST", 0 DS}, /* British Summer */
|
||
+ {"WAT", 60}, /* West Africa */
|
||
+ {"AST", 240}, /* Atlantic Standard */
|
||
+ {"ADT", 240 DS},/* Atlantic Daylight */
|
||
+ {"EST", 300}, /* Eastern Standard */
|
||
+ {"EDT", 300 DS},/* Eastern Daylight */
|
||
+ {"CST", 360}, /* Central Standard */
|
||
+ {"CDT", 360 DS},/* Central Daylight */
|
||
+ {"MST", 420}, /* Mountain Standard */
|
||
+ {"MDT", 420 DS},/* Mountain Daylight */
|
||
+ {"PST", 480}, /* Pacific Standard */
|
||
+ {"PDT", 480 DS},/* Pacific Daylight */
|
||
+ {"YST", 540}, /* Yukon Standard */
|
||
+ {"YDT", 540 DS},/* Yukon Daylight */
|
||
+ {"HST", 600}, /* Hawaii Standard */
|
||
+ {"HDT", 600 DS},/* Hawaii Daylight */
|
||
+ {"CAT", 600}, /* Central Alaska */
|
||
+ {"AHST", 600}, /* Alaska-Hawaii Standard */
|
||
+ {"NT", 660}, /* Nome */
|
||
+ {"IDLW", 720}, /* International Date Line West */
|
||
+ {"CET", -60}, /* Central European */
|
||
+ {"MET", -60}, /* Middle European */
|
||
+ {"MEWT", -60}, /* Middle European Winter */
|
||
+ {"MEST", -60 DS},/* Middle European Summer */
|
||
+ {"CEST", -60 DS},/* Central European Summer */
|
||
+ {"MESZ", -60 DS},/* Middle European Summer */
|
||
+ {"FWT", -60}, /* French Winter */
|
||
+ {"FST", -60 DS},/* French Summer */
|
||
+ {"EET", -120}, /* Eastern Europe, USSR Zone 1 */
|
||
+ {"WAST", -420}, /* West Australian Standard */
|
||
+ {"WADT", -420 DS},/* West Australian Daylight */
|
||
+ {"CCT", -480}, /* China Coast, USSR Zone 7 */
|
||
+ {"JST", -540}, /* Japan Standard, USSR Zone 8 */
|
||
+ {"EAST", -600}, /* Eastern Australian Standard */
|
||
+ {"EADT", -600 DS},/* Eastern Australian Daylight */
|
||
+ {"GST", -600}, /* Guam Standard, USSR Zone 9 */
|
||
+ {"NZT", -720}, /* New Zealand */
|
||
+ {"NZST", -720}, /* New Zealand Standard */
|
||
+ {"NZDT", -720 DS},/* New Zealand Daylight */
|
||
+ {"IDLE", -720}, /* International Date Line East */
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ Day/Month/TZ checks for http_parse_date()
|
||
+ Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
|
||
+static inline int check_day(const char *day, size_t len)
|
||
+{
|
||
+ int i;
|
||
+ const char * const *check = (len > 3) ? &weekdays[0] : &wkdays[0];
|
||
+ for (i = 0; i < 7; i++) {
|
||
+ if (!strcmp(day, check[0])) {
|
||
+ return i;
|
||
+ }
|
||
+ check++;
|
||
+ }
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+static inline int check_month(const char *month)
|
||
+{
|
||
+ int i;
|
||
+ const char * const *check = &months[0];
|
||
+ for (i = 0; i < 12; i++) {
|
||
+ if (!strcmp(month, check[0])) {
|
||
+ return i;
|
||
+ }
|
||
+ check++;
|
||
+ }
|
||
+ return -1;
|
||
+}
|
||
+
|
||
+/* return the time zone offset between GMT and the input one, in number
|
||
+ of seconds or -1 if the timezone wasn't found/legal */
|
||
+
|
||
+static inline int check_tzone(const char *tzone)
|
||
+{
|
||
+ unsigned i;
|
||
+ const struct time_zone *check = time_zones;
|
||
+ for (i = 0; i < sizeof(time_zones) / sizeof(time_zones[0]); i++) {
|
||
+ if (!strcmp(tzone, check->name)) {
|
||
+ return check->offset * 60;
|
||
+ }
|
||
+ check++;
|
||
+ }
|
||
+ return -1;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ char *http_date(time_t) */
|
||
+PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC)
|
||
+{
|
||
+ char *date = NULL;
|
||
+ struct tm *gmtime = NULL, tmbuf;
|
||
+
|
||
+ memset(&tmbuf, 0, sizeof(tmbuf));
|
||
+ if ((gmtime = php_gmtime_r(&t, &tmbuf))) {
|
||
+ spprintf(&date, 0,
|
||
+ "%s, %02d %s %04d %02d:%02d:%02d GMT",
|
||
+ days[gmtime->tm_wday], gmtime->tm_mday,
|
||
+ months[gmtime->tm_mon], gmtime->tm_year + 1900,
|
||
+ gmtime->tm_hour, gmtime->tm_min, gmtime->tm_sec
|
||
+ );
|
||
+ }
|
||
+
|
||
+ return date;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ time_t http_parse_date(char *) */
|
||
+PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC)
|
||
+{
|
||
+ time_t t = parse_date(date);
|
||
+
|
||
+ if (-1 == t && !silent) {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Could not parse date: %s", date);
|
||
+ }
|
||
+
|
||
+ return t;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* time_t parse_date(char *)
|
||
+ Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
|
||
+static inline time_t parse_date(const char *date)
|
||
+{
|
||
+ time_t t = 0;
|
||
+ int tz_offset = -1, year = -1, month = -1, monthday = -1, weekday = -1,
|
||
+ hours = -1, minutes = -1, seconds = -1;
|
||
+ struct tm tm;
|
||
+ enum assume_next dignext = DATE_MDAY;
|
||
+ const char *indate = date;
|
||
+
|
||
+ int part = 0; /* max 6 parts */
|
||
+
|
||
+ while (*date && (part < 6)) {
|
||
+ int found = 0;
|
||
+
|
||
+ while (*date && !HTTP_IS_CTYPE(alnum, *date)) {
|
||
+ date++;
|
||
+ }
|
||
+
|
||
+ if (HTTP_IS_CTYPE(alpha, *date)) {
|
||
+ /* a name coming up */
|
||
+ char buf[32] = "";
|
||
+ size_t len;
|
||
+ sscanf(date, "%31[A-Za-z]", buf);
|
||
+ len = strlen(buf);
|
||
+
|
||
+ if (weekday == -1) {
|
||
+ weekday = check_day(buf, len);
|
||
+ if (weekday != -1) {
|
||
+ found = 1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!found && (month == -1)) {
|
||
+ month = check_month(buf);
|
||
+ if (month != -1) {
|
||
+ found = 1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!found && (tz_offset == -1)) {
|
||
+ /* this just must be a time zone string */
|
||
+ tz_offset = check_tzone(buf);
|
||
+ if (tz_offset != -1) {
|
||
+ found = 1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!found) {
|
||
+ return -1; /* bad string */
|
||
+ }
|
||
+ date += len;
|
||
+ }
|
||
+ else if (HTTP_IS_CTYPE(digit, *date)) {
|
||
+ /* a digit */
|
||
+ int val;
|
||
+ char *end;
|
||
+ if ((seconds == -1) &&
|
||
+ (3 == sscanf(date, "%02d:%02d:%02d", &hours, &minutes, &seconds))) {
|
||
+ /* time stamp! */
|
||
+ date += 8;
|
||
+ found = 1;
|
||
+ }
|
||
+ else {
|
||
+ val = (int) strtol(date, &end, 10);
|
||
+
|
||
+ if ((tz_offset == -1) && ((end - date) == 4) && (val < 1300) &&
|
||
+ (indate < date) && ((date[-1] == '+' || date[-1] == '-'))) {
|
||
+ /* four digits and a value less than 1300 and it is preceeded with
|
||
+ a plus or minus. This is a time zone indication. */
|
||
+ found = 1;
|
||
+ tz_offset = (val / 100 * 60 + val % 100) * 60;
|
||
+
|
||
+ /* the + and - prefix indicates the local time compared to GMT,
|
||
+ this we need ther reversed math to get what we want */
|
||
+ tz_offset = date[-1] == '+' ? -tz_offset : tz_offset;
|
||
+ }
|
||
+
|
||
+ if (((end - date) == 8) && (year == -1) && (month == -1) && (monthday == -1)) {
|
||
+ /* 8 digits, no year, month or day yet. This is YYYYMMDD */
|
||
+ found = 1;
|
||
+ year = val / 10000;
|
||
+ month = (val % 10000) / 100 - 1; /* month is 0 - 11 */
|
||
+ monthday = val % 100;
|
||
+ }
|
||
+
|
||
+ if (!found && (dignext == DATE_MDAY) && (monthday == -1)) {
|
||
+ if ((val > 0) && (val < 32)) {
|
||
+ monthday = val;
|
||
+ found = 1;
|
||
+ }
|
||
+ dignext = DATE_YEAR;
|
||
+ }
|
||
+
|
||
+ if (!found && (dignext == DATE_YEAR) && (year == -1)) {
|
||
+ year = val;
|
||
+ found = 1;
|
||
+ if (year < 1900) {
|
||
+ year += year > 70 ? 1900 : 2000;
|
||
+ }
|
||
+ if(monthday == -1) {
|
||
+ dignext = DATE_MDAY;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!found) {
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ date = end;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ part++;
|
||
+ }
|
||
+
|
||
+ if (-1 == seconds) {
|
||
+ seconds = minutes = hours = 0; /* no time, make it zero */
|
||
+ }
|
||
+
|
||
+ if ((-1 == monthday) || (-1 == month) || (-1 == year)) {
|
||
+ /* lacks vital info, fail */
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ if (sizeof(time_t) < 5) {
|
||
+ /* 32 bit time_t can only hold dates to the beginning of 2038 */
|
||
+ if (year > 2037) {
|
||
+ return 0x7fffffff;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ tm.tm_sec = seconds;
|
||
+ tm.tm_min = minutes;
|
||
+ tm.tm_hour = hours;
|
||
+ tm.tm_mday = monthday;
|
||
+ tm.tm_mon = month;
|
||
+ tm.tm_year = year - 1900;
|
||
+ tm.tm_wday = 0;
|
||
+ tm.tm_yday = 0;
|
||
+ tm.tm_isdst = 0;
|
||
+
|
||
+ t = mktime(&tm);
|
||
+
|
||
+ /* time zone adjust */
|
||
+ if (t != -1) {
|
||
+ struct tm *gmt, keeptime2;
|
||
+ long delta;
|
||
+ time_t t2;
|
||
+
|
||
+ if((gmt = php_gmtime_r(&t, &keeptime2))) {
|
||
+ tm = *gmt; /* MSVC quirks */
|
||
+ } else {
|
||
+ return -1; /* illegal date/time */
|
||
+ }
|
||
+
|
||
+ t2 = mktime(&tm);
|
||
+
|
||
+ /* Add the time zone diff (between the given timezone and GMT) and the
|
||
+ diff between the local time zone and GMT. */
|
||
+ delta = (tz_offset != -1 ? tz_offset : 0) + (t - t2);
|
||
+
|
||
+ if((delta > 0) && (t + delta < t)) {
|
||
+ return -1; /* time_t overflow */
|
||
+ }
|
||
+
|
||
+ t += delta;
|
||
+ }
|
||
+
|
||
+ return t;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: sw=4 ts=4 fdm=marker
|
||
+ * vim<600: sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_deflatestream_object.c
|
||
@@ -0,0 +1,312 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_deflatestream_object.c 300299 2010-06-09 06:23:16Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_ZLIB
|
||
+#include "php_http.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB)
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_deflatestream_object.h"
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpDeflateStream, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpDeflateStream, method, 0)
|
||
+#define HTTP_DEFLATE_ME(method, visibility) PHP_ME(HttpDeflateStream, method, HTTP_ARGS(HttpDeflateStream, method), visibility)
|
||
+
|
||
+HTTP_BEGIN_ARGS(__construct, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(factory, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+ HTTP_ARG_VAL(class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(update, 1)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(flush, 0)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(finish, 0)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+#define THIS_CE http_deflatestream_object_ce
|
||
+zend_class_entry *http_deflatestream_object_ce;
|
||
+zend_function_entry http_deflatestream_object_fe[] = {
|
||
+ HTTP_DEFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
|
||
+ HTTP_DEFLATE_ME(update, ZEND_ACC_PUBLIC)
|
||
+ HTTP_DEFLATE_ME(flush, ZEND_ACC_PUBLIC)
|
||
+ HTTP_DEFLATE_ME(finish, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_DEFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+static zend_object_handlers http_deflatestream_object_handlers;
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_deflatestream_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS_EX(HttpDeflateStream, http_deflatestream_object, NULL, 0);
|
||
+ http_deflatestream_object_handlers.clone_obj = _http_deflatestream_object_clone_obj;
|
||
+
|
||
+#ifndef WONKY
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_GZIP")-1, HTTP_DEFLATE_TYPE_GZIP TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ZLIB")-1, HTTP_DEFLATE_TYPE_ZLIB TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RAW")-1, HTTP_DEFLATE_TYPE_RAW TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_DEF")-1, HTTP_DEFLATE_LEVEL_DEF TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MIN")-1, HTTP_DEFLATE_LEVEL_MIN TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MAX")-1, HTTP_DEFLATE_LEVEL_MAX TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_DEF")-1, HTTP_DEFLATE_STRATEGY_DEF TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FILT")-1, HTTP_DEFLATE_STRATEGY_FILT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_HUFF")-1, HTTP_DEFLATE_STRATEGY_HUFF TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_RLE")-1, HTTP_DEFLATE_STRATEGY_RLE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FIXED")-1, HTTP_DEFLATE_STRATEGY_FIXED TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
|
||
+#endif
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ return http_deflatestream_object_new_ex(ce, NULL, NULL);
|
||
+}
|
||
+
|
||
+zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ http_deflatestream_object *o;
|
||
+
|
||
+ o = ecalloc(1, sizeof(http_deflatestream_object));
|
||
+ o->zo.ce = ce;
|
||
+
|
||
+ if (ptr) {
|
||
+ *ptr = o;
|
||
+ }
|
||
+
|
||
+ if (s) {
|
||
+ o->stream = s;
|
||
+ }
|
||
+
|
||
+ ALLOC_HASHTABLE(OBJ_PROP(o));
|
||
+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+
|
||
+ ov.handle = putObject(http_deflatestream_object, o);
|
||
+ ov.handlers = &http_deflatestream_object_handlers;
|
||
+
|
||
+ return ov;
|
||
+}
|
||
+
|
||
+zend_object_value _http_deflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
|
||
+{
|
||
+ http_encoding_stream *s;
|
||
+ zend_object_value new_ov;
|
||
+ http_deflatestream_object *new_obj = NULL;
|
||
+ getObject(http_deflatestream_object, old_obj);
|
||
+
|
||
+ s = ecalloc(1, sizeof(http_encoding_stream));
|
||
+ s->flags = old_obj->stream->flags;
|
||
+ deflateCopy(&s->stream, &old_obj->stream->stream);
|
||
+ s->stream.opaque = phpstr_dup(s->stream.opaque);
|
||
+
|
||
+ new_ov = http_deflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
|
||
+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||
+
|
||
+ return new_ov;
|
||
+}
|
||
+
|
||
+void _http_deflatestream_object_free(zend_object *object TSRMLS_DC)
|
||
+{
|
||
+ http_deflatestream_object *o = (http_deflatestream_object *) object;
|
||
+
|
||
+ if (o->stream) {
|
||
+ http_encoding_deflate_stream_free(&o->stream);
|
||
+ }
|
||
+ freeObject(o);
|
||
+}
|
||
+
|
||
+/* {{{ proto void HttpDeflateStream::__construct([int flags = 0])
|
||
+ Creates a new HttpDeflateStream object instance. */
|
||
+PHP_METHOD(HttpDeflateStream, __construct)
|
||
+{
|
||
+ long flags = 0;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
|
||
+ getObject(http_deflatestream_object, obj);
|
||
+
|
||
+ if (!obj->stream) {
|
||
+ obj->stream = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
|
||
+ } else {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpDeflateStream cannot be initialized twice");
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpDeflateStream HttpDeflateStream::factory([int flags[, string class = "HttpDeflateStream"]])
|
||
+ Creates a new HttpDeflateStream object instance. */
|
||
+PHP_METHOD(HttpDeflateStream, factory)
|
||
+{
|
||
+ long flags = 0;
|
||
+ char *cn = NULL;
|
||
+ int cl = 0;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
|
||
+ zend_object_value ov;
|
||
+ http_encoding_stream *s = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
|
||
+
|
||
+ if (SUCCESS == http_object_new(&ov, cn, cl, _http_deflatestream_object_new_ex, http_deflatestream_object_ce, s, NULL)) {
|
||
+ RETVAL_OBJVAL(ov, 0);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpDeflateStream::update(string data)
|
||
+ Passes more data through the deflate stream. */
|
||
+PHP_METHOD(HttpDeflateStream, update)
|
||
+{
|
||
+ int data_len;
|
||
+ size_t encoded_len = 0;
|
||
+ char *data, *encoded = NULL;
|
||
+ getObject(http_deflatestream_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (SUCCESS == http_encoding_deflate_stream_update(obj->stream, data, data_len, &encoded, &encoded_len)) {
|
||
+ RETURN_STRINGL(encoded, encoded_len, 0);
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpDeflateStream::flush([string data])
|
||
+ Flushes the deflate stream. */
|
||
+PHP_METHOD(HttpDeflateStream, flush)
|
||
+{
|
||
+ int data_len = 0;
|
||
+ size_t updated_len = 0, encoded_len = 0;
|
||
+ char *updated = NULL, *encoded = NULL, *data = NULL;
|
||
+ getObject(http_deflatestream_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (data_len) {
|
||
+ if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (SUCCESS == http_encoding_deflate_stream_flush(obj->stream, &encoded, &encoded_len)) {
|
||
+ if (updated_len) {
|
||
+ updated = erealloc(updated, updated_len + encoded_len + 1);
|
||
+ updated[updated_len + encoded_len] = '\0';
|
||
+ memcpy(updated + updated_len, encoded, encoded_len);
|
||
+ STR_FREE(encoded);
|
||
+ updated_len += encoded_len;
|
||
+ RETURN_STRINGL(updated, updated_len, 0);
|
||
+ } else if (encoded) {
|
||
+ RETVAL_STRINGL(encoded, encoded_len, 0);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+ } else {
|
||
+ RETVAL_FALSE;
|
||
+ }
|
||
+ STR_FREE(updated);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpDeflateStream::finish([string data])
|
||
+ Finalizes the deflate stream. The deflate stream can be reused after finalizing. */
|
||
+PHP_METHOD(HttpDeflateStream, finish)
|
||
+{
|
||
+ int data_len = 0;
|
||
+ size_t updated_len = 0, encoded_len = 0;
|
||
+ char *updated = NULL, *encoded = NULL, *data = NULL;
|
||
+ getObject(http_deflatestream_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (data_len) {
|
||
+ if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (SUCCESS == http_encoding_deflate_stream_finish(obj->stream, &encoded, &encoded_len)) {
|
||
+ if (updated_len) {
|
||
+ updated = erealloc(updated, updated_len + encoded_len + 1);
|
||
+ updated[updated_len + encoded_len] = '\0';
|
||
+ memcpy(updated + updated_len, encoded, encoded_len);
|
||
+ STR_FREE(encoded);
|
||
+ updated_len += encoded_len;
|
||
+ RETVAL_STRINGL(updated, updated_len, 0);
|
||
+ } else {
|
||
+ STR_FREE(updated);
|
||
+ RETVAL_STRINGL(encoded, encoded_len, 0);
|
||
+ }
|
||
+ } else {
|
||
+ STR_FREE(updated);
|
||
+ RETVAL_FALSE;
|
||
+ }
|
||
+
|
||
+ http_encoding_deflate_stream_dtor(obj->stream);
|
||
+ http_encoding_deflate_stream_init(obj->stream, obj->stream->flags);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_encoding_api.c
|
||
@@ -0,0 +1,780 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_encoding_api.c 305668 2010-11-22 20:17:41Z iliaa $ */
|
||
+
|
||
+#define HTTP_WANT_ZLIB
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+#include "php_http_headers_api.h"
|
||
+
|
||
+/* {{{ */
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+PHP_MINIT_FUNCTION(http_encoding)
|
||
+{
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_DEF", HTTP_DEFLATE_LEVEL_DEF);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MIN", HTTP_DEFLATE_LEVEL_MIN);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MAX", HTTP_DEFLATE_LEVEL_MAX);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_ZLIB", HTTP_DEFLATE_TYPE_ZLIB);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_GZIP", HTTP_DEFLATE_TYPE_GZIP);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_RAW", HTTP_DEFLATE_TYPE_RAW);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_DEF", HTTP_DEFLATE_STRATEGY_DEF);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FILT", HTTP_DEFLATE_STRATEGY_FILT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_HUFF", HTTP_DEFLATE_STRATEGY_HUFF);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_RLE", HTTP_DEFLATE_STRATEGY_RLE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FIXED", HTTP_DEFLATE_STRATEGY_FIXED);
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_NONE", HTTP_ENCODING_STREAM_FLUSH_NONE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_SYNC", HTTP_ENCODING_STREAM_FLUSH_SYNC);
|
||
+ HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_FULL", HTTP_ENCODING_STREAM_FLUSH_FULL);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_RINIT_FUNCTION(http_encoding)
|
||
+{
|
||
+ if (HTTP_G->send.inflate.start_auto) {
|
||
+ php_ob_set_internal_handler(_http_ob_inflatehandler, HTTP_INFLATE_BUFFER_SIZE, "http inflate", 0 TSRMLS_CC);
|
||
+ }
|
||
+ if (HTTP_G->send.deflate.start_auto) {
|
||
+ php_ob_set_internal_handler(_http_ob_deflatehandler, HTTP_DEFLATE_BUFFER_SIZE, "http deflate", 0 TSRMLS_CC);
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_RSHUTDOWN_FUNCTION(http_encoding)
|
||
+{
|
||
+ if (HTTP_G->send.deflate.stream) {
|
||
+ http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream);
|
||
+ }
|
||
+ if (HTTP_G->send.inflate.stream) {
|
||
+ http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream);
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+#endif
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ eol_match(char **, int *) */
|
||
+static inline int eol_match(char **line, int *eol_len)
|
||
+{
|
||
+ char *ptr = *line;
|
||
+
|
||
+ while (' ' == *ptr) ++ptr;
|
||
+
|
||
+ if (ptr == http_locate_eol(*line, eol_len)) {
|
||
+ *line = ptr;
|
||
+ return 1;
|
||
+ } else {
|
||
+ return 0;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ char *http_encoding_dechunk(char *, size_t, char **, size_t *) */
|
||
+PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
|
||
+{
|
||
+ int eol_len = 0;
|
||
+ char *n_ptr = NULL;
|
||
+ const char *e_ptr = encoded;
|
||
+
|
||
+ *decoded_len = 0;
|
||
+ *decoded = ecalloc(1, encoded_len);
|
||
+
|
||
+ while ((encoded + encoded_len - e_ptr) > 0) {
|
||
+ ulong chunk_len = 0, rest;
|
||
+
|
||
+ chunk_len = strtoul(e_ptr, &n_ptr, 16);
|
||
+
|
||
+ /* we could not read in chunk size */
|
||
+ if (n_ptr == e_ptr) {
|
||
+ /*
|
||
+ * if this is the first turn and there doesn't seem to be a chunk
|
||
+ * size at the begining of the body, do not fail on apparently
|
||
+ * not encoded data and return a copy
|
||
+ */
|
||
+ if (e_ptr == encoded) {
|
||
+ http_error(HE_NOTICE, HTTP_E_ENCODING, "Data does not seem to be chunked encoded");
|
||
+ memcpy(*decoded, encoded, encoded_len);
|
||
+ *decoded_len = encoded_len;
|
||
+ return encoded + encoded_len;
|
||
+ } else {
|
||
+ efree(*decoded);
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected chunk size at pos %tu of %zu but got trash", n_ptr - encoded, encoded_len);
|
||
+ return NULL;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* reached the end */
|
||
+ if (!chunk_len) {
|
||
+ /* move over '0' chunked encoding terminator */
|
||
+ while (*e_ptr == '0') ++e_ptr;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* there should be CRLF after the chunk size, but we'll ignore SP+ too */
|
||
+ if (*n_ptr && !eol_match(&n_ptr, &eol_len)) {
|
||
+ if (eol_len == 2) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected CRLF at pos %tu of %zu but got 0x%02X 0x%02X", n_ptr - encoded, encoded_len, *n_ptr, *(n_ptr + 1));
|
||
+ } else {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected LF at pos %tu of %zu but got 0x%02X", n_ptr - encoded, encoded_len, *n_ptr);
|
||
+ }
|
||
+ }
|
||
+ n_ptr += eol_len;
|
||
+
|
||
+ /* chunk size pretends more data than we actually got, so it's probably a truncated message */
|
||
+ if (chunk_len > (rest = encoded + encoded_len - n_ptr)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Truncated message: chunk size %lu exceeds remaining data size %lu at pos %tu of %zu", chunk_len, rest, n_ptr - encoded, encoded_len);
|
||
+ chunk_len = rest;
|
||
+ }
|
||
+
|
||
+ /* copy the chunk */
|
||
+ memcpy(*decoded + *decoded_len, n_ptr, chunk_len);
|
||
+ *decoded_len += chunk_len;
|
||
+
|
||
+ if (chunk_len == rest) {
|
||
+ e_ptr = n_ptr + chunk_len;
|
||
+ break;
|
||
+ } else {
|
||
+ /* advance to next chunk */
|
||
+ e_ptr = n_ptr + chunk_len + eol_len;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return e_ptr;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ int http_encoding_response_start(size_t) */
|
||
+PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC)
|
||
+{
|
||
+ int response = HTTP_G->send.deflate.response;
|
||
+ int ohandler = php_ob_handler_used("ob_gzhandler" TSRMLS_CC) || php_ob_handler_used("zlib output compression" TSRMLS_CC);
|
||
+
|
||
+ if (!ohandler && !ignore_http_ohandler) {
|
||
+ ohandler = php_ob_handler_used("ob_deflatehandler" TSRMLS_CC) || php_ob_handler_used("http deflate" TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ if (response && !ohandler) {
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ HashTable *selected;
|
||
+ zval zsupported;
|
||
+
|
||
+ HTTP_G->send.deflate.encoding = 0;
|
||
+
|
||
+ INIT_PZVAL(&zsupported);
|
||
+ array_init(&zsupported);
|
||
+ add_next_index_stringl(&zsupported, "gzip", lenof("gzip"), 1);
|
||
+ add_next_index_stringl(&zsupported, "x-gzip", lenof("x-gzip"), 1);
|
||
+ add_next_index_stringl(&zsupported, "deflate", lenof("deflate"), 1);
|
||
+
|
||
+ if ((selected = http_negotiate_encoding(&zsupported))) {
|
||
+ STATUS hs = FAILURE;
|
||
+ char *encoding = NULL;
|
||
+ ulong idx;
|
||
+
|
||
+ if (HASH_KEY_IS_STRING == zend_hash_get_current_key(selected, &encoding, &idx, 0) && encoding) {
|
||
+ if (!strcmp(encoding, "gzip") || !strcmp(encoding, "x-gzip")) {
|
||
+ if (SUCCESS == (hs = http_send_header_string("Content-Encoding: gzip"))) {
|
||
+ HTTP_G->send.deflate.encoding = HTTP_ENCODING_GZIP;
|
||
+ }
|
||
+ } else if (!strcmp(encoding, "deflate")) {
|
||
+ if (SUCCESS == (hs = http_send_header_string("Content-Encoding: deflate"))) {
|
||
+ HTTP_G->send.deflate.encoding = HTTP_ENCODING_DEFLATE;
|
||
+ }
|
||
+ }
|
||
+ if (SUCCESS == hs) {
|
||
+ http_send_header_string("Vary: Accept-Encoding");
|
||
+ }
|
||
+ }
|
||
+
|
||
+ zend_hash_destroy(selected);
|
||
+ FREE_HASHTABLE(selected);
|
||
+ }
|
||
+
|
||
+ zval_dtor(&zsupported);
|
||
+#else
|
||
+ HTTP_G->send.deflate.encoding = 0;
|
||
+ php_start_ob_buffer_named("ob_gzhandler", 0, 0 TSRMLS_CC);
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+ } else if (content_length && !ohandler) {
|
||
+ /* emit a content-length header */
|
||
+ phpstr header;
|
||
+
|
||
+ phpstr_init(&header);
|
||
+ phpstr_appendf(&header, "Content-Length: %zu", content_length);
|
||
+ phpstr_fix(&header);
|
||
+ http_send_header_string_ex(PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
|
||
+ phpstr_dtor(&header);
|
||
+ } else {
|
||
+ HTTP_G->send.deflate.encoding = 0;
|
||
+ }
|
||
+
|
||
+ return HTTP_G->send.deflate.encoding;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+
|
||
+/* {{{ inline int http_inflate_rounds */
|
||
+static inline int http_inflate_rounds(z_stream *Z, int flush, char **buf, size_t *len)
|
||
+{
|
||
+ int status = 0, round = 0;
|
||
+ phpstr buffer;
|
||
+
|
||
+ *buf = NULL;
|
||
+ *len = 0;
|
||
+
|
||
+ phpstr_init_ex(&buffer, Z->avail_in, PHPSTR_INIT_PREALLOC);
|
||
+
|
||
+ do {
|
||
+ if (PHPSTR_NOMEM == phpstr_resize_ex(&buffer, buffer.size, 0, 1)) {
|
||
+ status = Z_MEM_ERROR;
|
||
+ } else {
|
||
+ Z->avail_out = buffer.free;
|
||
+ Z->next_out = (Bytef *) buffer.data + buffer.used;
|
||
+#if 0
|
||
+ fprintf(stderr, "\n%3d: %3d PRIOR: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
|
||
+#endif
|
||
+ status = inflate(Z, flush);
|
||
+
|
||
+ buffer.used += buffer.free - Z->avail_out;
|
||
+ buffer.free = Z->avail_out;
|
||
+#if 0
|
||
+ fprintf(stderr, "%3d: %3d AFTER: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out);
|
||
+#endif
|
||
+ HTTP_INFLATE_BUFFER_SIZE_ALIGN(buffer.size);
|
||
+ }
|
||
+ } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < HTTP_INFLATE_ROUNDS);
|
||
+
|
||
+ if (status == Z_OK || status == Z_STREAM_END) {
|
||
+ phpstr_shrink(&buffer);
|
||
+ phpstr_fix(&buffer);
|
||
+ *buf = buffer.data;
|
||
+ *len = buffer.used;
|
||
+ } else {
|
||
+ phpstr_dtor(&buffer);
|
||
+ }
|
||
+
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_deflate(int, char *, size_t, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status, level, wbits, strategy;
|
||
+ z_stream Z;
|
||
+
|
||
+ HTTP_DEFLATE_LEVEL_SET(flags, level);
|
||
+ HTTP_DEFLATE_WBITS_SET(flags, wbits);
|
||
+ HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
|
||
+
|
||
+ memset(&Z, 0, sizeof(z_stream));
|
||
+ *encoded = NULL;
|
||
+ *encoded_len = 0;
|
||
+
|
||
+ status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy);
|
||
+ if (Z_OK == status) {
|
||
+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
|
||
+ *encoded = emalloc_rel(*encoded_len);
|
||
+
|
||
+ Z.next_in = (Bytef *) data;
|
||
+ Z.next_out = (Bytef *) *encoded;
|
||
+ Z.avail_in = data_len;
|
||
+ Z.avail_out = *encoded_len;
|
||
+
|
||
+ status = deflate(&Z, Z_FINISH);
|
||
+ deflateEnd(&Z);
|
||
+
|
||
+ if (Z_STREAM_END == status) {
|
||
+ /* size buffer down to actual length */
|
||
+ *encoded = erealloc_rel(*encoded, Z.total_out + 1);
|
||
+ (*encoded)[*encoded_len = Z.total_out] = '\0';
|
||
+ return SUCCESS;
|
||
+ } else {
|
||
+ STR_SET(*encoded, NULL);
|
||
+ *encoded_len = 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not deflate data: %s", zError(status));
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_inflate(char *, size_t, char **, size_t) */
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ z_stream Z;
|
||
+ int status, wbits = HTTP_WINDOW_BITS_ANY;
|
||
+
|
||
+ memset(&Z, 0, sizeof(z_stream));
|
||
+
|
||
+retry_raw_inflate:
|
||
+ status = inflateInit2(&Z, wbits);
|
||
+ if (Z_OK == status) {
|
||
+ Z.next_in = (Bytef *) data;
|
||
+ Z.avail_in = data_len;
|
||
+
|
||
+ switch (status = http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) {
|
||
+ case Z_STREAM_END:
|
||
+ inflateEnd(&Z);
|
||
+ return SUCCESS;
|
||
+
|
||
+ case Z_OK:
|
||
+ status = Z_DATA_ERROR;
|
||
+ break;
|
||
+
|
||
+ case Z_DATA_ERROR:
|
||
+ /* raw deflated data? */
|
||
+ if (HTTP_WINDOW_BITS_ANY == wbits) {
|
||
+ inflateEnd(&Z);
|
||
+ wbits = HTTP_WINDOW_BITS_RAW;
|
||
+ goto retry_raw_inflate;
|
||
+ }
|
||
+ }
|
||
+ inflateEnd(&Z);
|
||
+ }
|
||
+
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s", zError(status));
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *, int) */
|
||
+PHP_HTTP_API http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status, level, wbits, strategy, free_stream;
|
||
+
|
||
+ if ((free_stream = !s)) {
|
||
+ s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));
|
||
+ }
|
||
+ memset(s, 0, sizeof(http_encoding_stream));
|
||
+ s->flags = flags;
|
||
+
|
||
+ HTTP_DEFLATE_LEVEL_SET(flags, level);
|
||
+ HTTP_DEFLATE_WBITS_SET(flags, wbits);
|
||
+ HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
|
||
+
|
||
+ if (Z_OK == (status = deflateInit2(&s->stream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy))) {
|
||
+ int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
|
||
+
|
||
+ if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) {
|
||
+ return s;
|
||
+ }
|
||
+ deflateEnd(&s->stream);
|
||
+ status = Z_MEM_ERROR;
|
||
+ }
|
||
+
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize deflate encoding stream: %s", zError(status));
|
||
+ if (free_stream) {
|
||
+ efree(s);
|
||
+ }
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_encoding_stream *http_encoding_inflate_stream_init(http_encoding_stream *, int) */
|
||
+PHP_HTTP_API http_encoding_stream *_http_encoding_inflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status, wbits, free_stream;
|
||
+
|
||
+ if ((free_stream = !s)) {
|
||
+ s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));
|
||
+ }
|
||
+ memset(s, 0, sizeof(http_encoding_stream));
|
||
+ s->flags = flags;
|
||
+
|
||
+ HTTP_INFLATE_WBITS_SET(flags, wbits);
|
||
+
|
||
+ if (Z_OK == (status = inflateInit2(&s->stream, wbits))) {
|
||
+ int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
|
||
+
|
||
+ if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) {
|
||
+ return s;
|
||
+ }
|
||
+ inflateEnd(&s->stream);
|
||
+ status = Z_MEM_ERROR;
|
||
+ }
|
||
+
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize inflate stream: %s", zError(status));
|
||
+ if (free_stream) {
|
||
+ efree(s);
|
||
+ }
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_deflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status;
|
||
+
|
||
+ /* append input to our buffer */
|
||
+ phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
|
||
+
|
||
+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
|
||
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
|
||
+
|
||
+ /* deflate */
|
||
+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
|
||
+ *encoded = emalloc_rel(*encoded_len);
|
||
+ s->stream.avail_out = *encoded_len;
|
||
+ s->stream.next_out = (Bytef *) *encoded;
|
||
+
|
||
+ switch (status = deflate(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags))) {
|
||
+ case Z_OK:
|
||
+ case Z_STREAM_END:
|
||
+ /* cut processed chunk off the buffer */
|
||
+ if (s->stream.avail_in) {
|
||
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
|
||
+ } else {
|
||
+ phpstr_reset(PHPSTR(s->stream.opaque));
|
||
+ }
|
||
+
|
||
+ /* size buffer down to actual size */
|
||
+ *encoded_len -= s->stream.avail_out;
|
||
+ *encoded = erealloc_rel(*encoded, *encoded_len + 1);
|
||
+ (*encoded)[*encoded_len] = '\0';
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ STR_SET(*encoded, NULL);
|
||
+ *encoded_len = 0;
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update deflate stream: %s", zError(status));
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_inflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status;
|
||
+
|
||
+ /* append input to buffer */
|
||
+ phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
|
||
+
|
||
+retry_raw_inflate:
|
||
+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
|
||
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
|
||
+
|
||
+ switch (status = http_inflate_rounds(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags), decoded, decoded_len)) {
|
||
+ case Z_OK:
|
||
+ case Z_STREAM_END:
|
||
+ /* cut off */
|
||
+ if (s->stream.avail_in) {
|
||
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
|
||
+ } else {
|
||
+ phpstr_reset(PHPSTR(s->stream.opaque));
|
||
+ }
|
||
+ return SUCCESS;
|
||
+
|
||
+ case Z_DATA_ERROR:
|
||
+ /* raw deflated data ? */
|
||
+ if (!(s->flags & HTTP_INFLATE_TYPE_RAW) && !s->stream.total_out) {
|
||
+ inflateEnd(&s->stream);
|
||
+ s->flags |= HTTP_INFLATE_TYPE_RAW;
|
||
+ inflateInit2(&s->stream, HTTP_WINDOW_BITS_RAW);
|
||
+ goto retry_raw_inflate;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update inflate stream: %s", zError(status));
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_deflate_stream_flush(http_encoding_stream *, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_flush(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status;
|
||
+
|
||
+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE;
|
||
+ *encoded = emalloc_rel(*encoded_len);
|
||
+
|
||
+ s->stream.avail_in = 0;
|
||
+ s->stream.next_in = NULL;
|
||
+ s->stream.avail_out = *encoded_len;
|
||
+ s->stream.next_out = (Bytef *) *encoded;
|
||
+
|
||
+ switch (status = deflate(&s->stream, Z_FULL_FLUSH)) {
|
||
+ case Z_OK:
|
||
+ case Z_STREAM_END:
|
||
+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE - s->stream.avail_out;
|
||
+ *encoded = erealloc_rel(*encoded, *encoded_len + 1);
|
||
+ (*encoded)[*encoded_len] = '\0';
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ STR_SET(*encoded, NULL);
|
||
+ *encoded_len = 0;
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to flush deflate stream: %s", zError(status));
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_inflate_straem_flush(http_encoding_stream *, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_flush(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ /* noop */
|
||
+ *decoded = estrndup("", *decoded_len = 0);
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_deflate_stream_finish(http_encoding_stream *, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status;
|
||
+
|
||
+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE;
|
||
+ *encoded = emalloc_rel(*encoded_len);
|
||
+
|
||
+ /* deflate remaining input */
|
||
+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
|
||
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
|
||
+
|
||
+ s->stream.avail_out = *encoded_len;
|
||
+ s->stream.next_out = (Bytef *) *encoded;
|
||
+
|
||
+ do {
|
||
+ status = deflate(&s->stream, Z_FINISH);
|
||
+ } while (Z_OK == status);
|
||
+
|
||
+ if (Z_STREAM_END == status) {
|
||
+ /* cut processed intp off */
|
||
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
|
||
+
|
||
+ /* size down */
|
||
+ *encoded_len -= s->stream.avail_out;
|
||
+ *encoded = erealloc_rel(*encoded, *encoded_len + 1);
|
||
+ (*encoded)[*encoded_len] = '\0';
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ STR_SET(*encoded, NULL);
|
||
+ *encoded_len = 0;
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish deflate stream: %s", zError(status));
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_encoding_inflate_stream_finish(http_encoding_stream *, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_finish(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ int status;
|
||
+
|
||
+ if (!PHPSTR_LEN(s->stream.opaque)) {
|
||
+ *decoded = NULL;
|
||
+ *decoded_len = 0;
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ *decoded_len = (PHPSTR_LEN(s->stream.opaque) + 1) * HTTP_INFLATE_ROUNDS;
|
||
+ *decoded = emalloc_rel(*decoded_len);
|
||
+
|
||
+ /* inflate remaining input */
|
||
+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
|
||
+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
|
||
+
|
||
+ s->stream.avail_out = *decoded_len;
|
||
+ s->stream.next_out = (Bytef *) *decoded;
|
||
+
|
||
+ if (Z_STREAM_END == (status = inflate(&s->stream, Z_FINISH))) {
|
||
+ /* cut processed input off */
|
||
+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
|
||
+
|
||
+ /* size down */
|
||
+ *decoded_len -= s->stream.avail_out;
|
||
+ *decoded = erealloc_rel(*decoded, *decoded_len + 1);
|
||
+ (*decoded)[*decoded_len] = '\0';
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ STR_SET(*decoded, NULL);
|
||
+ *decoded_len = 0;
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish inflate stream: %s", zError(status));
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_encoding_deflate_stream_dtor(http_encoding_stream *) */
|
||
+PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
|
||
+{
|
||
+ if (s) {
|
||
+ if (s->stream.opaque) {
|
||
+ phpstr_free((phpstr **) &s->stream.opaque);
|
||
+ }
|
||
+ deflateEnd(&s->stream);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_encoding_inflate_stream_dtor(http_encoding_stream *) */
|
||
+PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
|
||
+{
|
||
+ if (s) {
|
||
+ if (s->stream.opaque) {
|
||
+ phpstr_free((phpstr **) &s->stream.opaque);
|
||
+ }
|
||
+ inflateEnd(&s->stream);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_encoding_deflate_stream_free(http_encoding_stream **) */
|
||
+PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC)
|
||
+{
|
||
+ if (s) {
|
||
+ http_encoding_deflate_stream_dtor(*s);
|
||
+ if (*s) {
|
||
+ pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
|
||
+ }
|
||
+ *s = NULL;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_encoding_inflate_stream_free(http_encoding_stream **) */
|
||
+PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC)
|
||
+{
|
||
+ if (s) {
|
||
+ http_encoding_inflate_stream_dtor(*s);
|
||
+ if (*s) {
|
||
+ pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
|
||
+ }
|
||
+ *s = NULL;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_ob_deflatehandler(char *, uint, char **, uint *, int) */
|
||
+void _http_ob_deflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
|
||
+{
|
||
+ int encoding;
|
||
+
|
||
+ *handled_output = NULL;
|
||
+ *handled_output_len = 0;
|
||
+
|
||
+ if (mode & PHP_OUTPUT_HANDLER_START) {
|
||
+ int flags;
|
||
+
|
||
+ if (HTTP_G->send.deflate.stream) {
|
||
+ zend_error(E_ERROR, "ob_deflatehandler() can only be used once");
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ HTTP_G->send.deflate.response = 1;
|
||
+ encoding = http_encoding_response_start(0, 1);
|
||
+ HTTP_G->send.deflate.response = 0;
|
||
+
|
||
+ switch (encoding) {
|
||
+ case HTTP_ENCODING_GZIP:
|
||
+ flags = HTTP_DEFLATE_TYPE_GZIP;
|
||
+ break;
|
||
+
|
||
+ case HTTP_ENCODING_DEFLATE:
|
||
+ flags = HTTP_DEFLATE_TYPE_ZLIB;
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ goto deflate_passthru_plain;
|
||
+ }
|
||
+
|
||
+ flags |= (HTTP_G->send.deflate.start_flags &~ 0xf0);
|
||
+ HTTP_G->send.deflate.stream = http_encoding_deflate_stream_init(NULL, flags);
|
||
+ }
|
||
+
|
||
+ if (HTTP_G->send.deflate.stream) {
|
||
+ if (output_len) {
|
||
+ size_t tmp_len;
|
||
+
|
||
+ http_encoding_deflate_stream_update((http_encoding_stream *) HTTP_G->send.deflate.stream, output, output_len, handled_output, &tmp_len);
|
||
+ *handled_output_len = tmp_len;
|
||
+ }
|
||
+
|
||
+ if (mode & PHP_OUTPUT_HANDLER_END) {
|
||
+ char *remaining = NULL;
|
||
+ size_t remaining_len = 0;
|
||
+
|
||
+ http_encoding_deflate_stream_finish((http_encoding_stream *) HTTP_G->send.deflate.stream, &remaining, &remaining_len);
|
||
+ http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream);
|
||
+ if (remaining) {
|
||
+ *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1);
|
||
+ memcpy(*handled_output + *handled_output_len, remaining, remaining_len);
|
||
+ (*handled_output)[*handled_output_len += remaining_len] = '\0';
|
||
+ efree(remaining);
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+deflate_passthru_plain:
|
||
+ *handled_output = estrndup(output, *handled_output_len = output_len);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_ob_inflatehandler(char *, uint, char **, uint *, int) */
|
||
+void _http_ob_inflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
|
||
+{
|
||
+ *handled_output = NULL;
|
||
+ *handled_output_len = 0;
|
||
+
|
||
+ if (mode & PHP_OUTPUT_HANDLER_START) {
|
||
+ if (HTTP_G->send.inflate.stream) {
|
||
+ zend_error(E_ERROR, "ob_inflatehandler() can only be used once");
|
||
+ return;
|
||
+ }
|
||
+ HTTP_G->send.inflate.stream = http_encoding_inflate_stream_init(NULL, (HTTP_G->send.inflate.start_flags &~ 0xf0));
|
||
+ }
|
||
+
|
||
+ if (HTTP_G->send.inflate.stream) {
|
||
+ if (output_len) {
|
||
+ size_t tmp_len;
|
||
+
|
||
+ http_encoding_inflate_stream_update((http_encoding_stream *) HTTP_G->send.inflate.stream, output, output_len, handled_output, &tmp_len);
|
||
+ *handled_output_len = tmp_len;
|
||
+ }
|
||
+
|
||
+ if (mode & PHP_OUTPUT_HANDLER_END) {
|
||
+ char *remaining = NULL;
|
||
+ size_t remaining_len = 0;
|
||
+
|
||
+ http_encoding_inflate_stream_finish((http_encoding_stream *) HTTP_G->send.inflate.stream, &remaining, &remaining_len);
|
||
+ http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream);
|
||
+ if (remaining) {
|
||
+ *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1);
|
||
+ memcpy(*handled_output + *handled_output_len, remaining, remaining_len);
|
||
+ (*handled_output)[*handled_output_len += remaining_len] = '\0';
|
||
+ efree(remaining);
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ *handled_output = estrndup(output, *handled_output_len = output_len);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_exception_object.c
|
||
@@ -0,0 +1,186 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_exception_object.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#ifndef HTTP_DBG_EXCEPTIONS
|
||
+# define HTTP_DBG_EXCEPTIONS 0
|
||
+#endif
|
||
+
|
||
+#include "zend_interfaces.h"
|
||
+#include "zend_exceptions.h"
|
||
+#include "php_http_exception_object.h"
|
||
+
|
||
+zend_class_entry *http_exception_object_ce;
|
||
+zend_class_entry *HTTP_EX_CE(runtime);
|
||
+zend_class_entry *HTTP_EX_CE(header);
|
||
+zend_class_entry *HTTP_EX_CE(malformed_headers);
|
||
+zend_class_entry *HTTP_EX_CE(request_method);
|
||
+zend_class_entry *HTTP_EX_CE(message_type);
|
||
+zend_class_entry *HTTP_EX_CE(invalid_param);
|
||
+zend_class_entry *HTTP_EX_CE(encoding);
|
||
+zend_class_entry *HTTP_EX_CE(request);
|
||
+zend_class_entry *HTTP_EX_CE(request_pool);
|
||
+zend_class_entry *HTTP_EX_CE(socket);
|
||
+zend_class_entry *HTTP_EX_CE(response);
|
||
+zend_class_entry *HTTP_EX_CE(url);
|
||
+zend_class_entry *HTTP_EX_CE(querystring);
|
||
+
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpException, method, 0)
|
||
+#define HTTP_EXCEPTION_ME(method, visibility) PHP_ME(HttpException, method, HTTP_ARGS(HttpException, method), visibility)
|
||
+
|
||
+HTTP_EMPTY_ARGS(__toString);
|
||
+
|
||
+zend_function_entry http_exception_object_fe[] = {
|
||
+ HTTP_EXCEPTION_ME(__toString, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+
|
||
+#if HTTP_DBG_EXCEPTIONS
|
||
+static void http_exception_hook(zval *ex TSRMLS_DC)
|
||
+{
|
||
+ if (ex) {
|
||
+ zval *m = zend_read_property(Z_OBJCE_P(ex), ex, "message", lenof("message"), 0 TSRMLS_CC);
|
||
+ fprintf(stderr, "*** Threw exception '%s'\n", Z_STRVAL_P(m));
|
||
+ } else {
|
||
+ fprintf(stderr, "*** Threw NULL exception\n");
|
||
+ }
|
||
+}
|
||
+#endif
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_exception_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS(HttpException, http_exception_object, ZEND_EXCEPTION_GET_DEFAULT(), 0);
|
||
+
|
||
+ zend_declare_property_null(HTTP_EX_DEF_CE, "innerException", lenof("innerException"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
||
+
|
||
+ HTTP_REGISTER_EXCEPTION(HttpRuntimeException, HTTP_EX_CE(runtime), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpInvalidParamException, HTTP_EX_CE(invalid_param), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpHeaderException, HTTP_EX_CE(header), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpMalformedHeadersException, HTTP_EX_CE(malformed_headers), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpRequestMethodException, HTTP_EX_CE(request_method), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpMessageTypeException, HTTP_EX_CE(message_type), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpEncodingException, HTTP_EX_CE(encoding), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpRequestException, HTTP_EX_CE(request), HTTP_EX_DEF_CE);
|
||
+
|
||
+ zend_declare_property_long(HTTP_EX_CE(request), "curlCode", lenof("curlCode"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
||
+
|
||
+ HTTP_REGISTER_EXCEPTION(HttpRequestPoolException, HTTP_EX_CE(request_pool), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpSocketException, HTTP_EX_CE(socket), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpResponseException, HTTP_EX_CE(response), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpUrlException, HTTP_EX_CE(url), HTTP_EX_DEF_CE);
|
||
+ HTTP_REGISTER_EXCEPTION(HttpQueryStringException, HTTP_EX_CE(querystring), HTTP_EX_DEF_CE);
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_RUNTIME", HTTP_E_RUNTIME);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_INVALID_PARAM", HTTP_E_INVALID_PARAM);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_HEADER", HTTP_E_HEADER);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_MALFORMED_HEADERS", HTTP_E_MALFORMED_HEADERS);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST_METHOD", HTTP_E_REQUEST_METHOD);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_MESSAGE_TYPE", HTTP_E_MESSAGE_TYPE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_ENCODING", HTTP_E_ENCODING);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST", HTTP_E_REQUEST);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST_POOL", HTTP_E_REQUEST_POOL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_SOCKET", HTTP_E_SOCKET);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_RESPONSE", HTTP_E_RESPONSE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_URL", HTTP_E_URL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_E_QUERYSTRING", HTTP_E_QUERYSTRING);
|
||
+
|
||
+#if HTTP_DBG_EXCEPTIONS
|
||
+ zend_throw_exception_hook=http_exception_hook;
|
||
+#endif
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+zend_class_entry *_http_exception_get_default()
|
||
+{
|
||
+ return http_exception_object_ce;
|
||
+}
|
||
+
|
||
+zend_class_entry *_http_exception_get_for_code(long code)
|
||
+{
|
||
+ zend_class_entry *ex = http_exception_object_ce;
|
||
+
|
||
+ switch (code) {
|
||
+ case HTTP_E_RUNTIME: ex = HTTP_EX_CE(runtime); break;
|
||
+ case HTTP_E_INVALID_PARAM: ex = HTTP_EX_CE(invalid_param); break;
|
||
+ case HTTP_E_HEADER: ex = HTTP_EX_CE(header); break;
|
||
+ case HTTP_E_MALFORMED_HEADERS: ex = HTTP_EX_CE(malformed_headers); break;
|
||
+ case HTTP_E_REQUEST_METHOD: ex = HTTP_EX_CE(request_method); break;
|
||
+ case HTTP_E_MESSAGE_TYPE: ex = HTTP_EX_CE(message_type); break;
|
||
+ case HTTP_E_ENCODING: ex = HTTP_EX_CE(encoding); break;
|
||
+ case HTTP_E_REQUEST: ex = HTTP_EX_CE(request); break;
|
||
+ case HTTP_E_REQUEST_POOL: ex = HTTP_EX_CE(request_pool); break;
|
||
+ case HTTP_E_SOCKET: ex = HTTP_EX_CE(socket); break;
|
||
+ case HTTP_E_RESPONSE: ex = HTTP_EX_CE(response); break;
|
||
+ case HTTP_E_URL: ex = HTTP_EX_CE(url); break;
|
||
+ case HTTP_E_QUERYSTRING: ex = HTTP_EX_CE(querystring); break;
|
||
+ }
|
||
+
|
||
+ return ex;
|
||
+}
|
||
+
|
||
+PHP_METHOD(HttpException, __toString)
|
||
+{
|
||
+ phpstr full_str;
|
||
+ zend_class_entry *ce;
|
||
+ zval *zobj = getThis(), *retval = NULL, *m, *f, *l;
|
||
+
|
||
+ phpstr_init(&full_str);
|
||
+
|
||
+ do {
|
||
+ ce = Z_OBJCE_P(zobj);
|
||
+
|
||
+ m = zend_read_property(ce, zobj, "message", lenof("message"), 0 TSRMLS_CC);
|
||
+ f = zend_read_property(ce, zobj, "file", lenof("file"), 0 TSRMLS_CC);
|
||
+ l = zend_read_property(ce, zobj, "line", lenof("line"), 0 TSRMLS_CC);
|
||
+
|
||
+ if (m && f && l && Z_TYPE_P(m) == IS_STRING && Z_TYPE_P(f) == IS_STRING && Z_TYPE_P(l) == IS_LONG) {
|
||
+ if (zobj != getThis()) {
|
||
+ phpstr_appends(&full_str, " inner ");
|
||
+ }
|
||
+
|
||
+ phpstr_appendf(&full_str, "exception '%.*s' with message '%.*s' in %.*s:%ld" PHP_EOL,
|
||
+ ce->name_length, ce->name, Z_STRLEN_P(m), Z_STRVAL_P(m), Z_STRLEN_P(f), Z_STRVAL_P(f), Z_LVAL_P(l)
|
||
+ );
|
||
+ } else {
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ zobj = zend_read_property(ce, zobj, "innerException", lenof("innerException"), 0 TSRMLS_CC);
|
||
+ } while (Z_TYPE_P(zobj) == IS_OBJECT);
|
||
+
|
||
+ if (zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "gettraceasstring", &retval) && Z_TYPE_P(retval) == IS_STRING) {
|
||
+ phpstr_appends(&full_str, "Stack trace:" PHP_EOL);
|
||
+ phpstr_append(&full_str, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
||
+ zval_ptr_dtor(&retval);
|
||
+ }
|
||
+
|
||
+ RETURN_PHPSTR_VAL(&full_str);
|
||
+}
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_filter_api.c
|
||
@@ -0,0 +1,534 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_filter_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_ZLIB
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#include "php_streams.h"
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_filter_api.h"
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_filter)
|
||
+{
|
||
+ php_stream_filter_register_factory("http.*", &http_filter_factory TSRMLS_CC);
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+/*
|
||
+ -
|
||
+*/
|
||
+
|
||
+#define HTTP_FILTER_PARAMS \
|
||
+ php_stream *stream, \
|
||
+ php_stream_filter *this, \
|
||
+ php_stream_bucket_brigade *buckets_in, \
|
||
+ php_stream_bucket_brigade *buckets_out, \
|
||
+ size_t *bytes_consumed, int flags \
|
||
+ TSRMLS_DC
|
||
+#define HTTP_FILTER_OP(filter) \
|
||
+ http_filter_op_ ##filter
|
||
+#define HTTP_FILTER_OPS(filter) \
|
||
+ php_stream_filter_ops HTTP_FILTER_OP(filter)
|
||
+#define HTTP_FILTER_DTOR(filter) \
|
||
+ http_filter_ ##filter## _dtor
|
||
+#define HTTP_FILTER_DESTRUCTOR(filter) \
|
||
+ void HTTP_FILTER_DTOR(filter)(php_stream_filter *this TSRMLS_DC)
|
||
+#define HTTP_FILTER_FUNC(filter) \
|
||
+ http_filter_ ##filter
|
||
+#define HTTP_FILTER_FUNCTION(filter) \
|
||
+ php_stream_filter_status_t HTTP_FILTER_FUNC(filter)(HTTP_FILTER_PARAMS)
|
||
+#define HTTP_FILTER_BUFFER(filter) \
|
||
+ http_filter_ ##filter## _buffer
|
||
+
|
||
+#define NEW_BUCKET(data, length) \
|
||
+ { \
|
||
+ char *__data; \
|
||
+ php_stream_bucket *__buck; \
|
||
+ \
|
||
+ __data = pemalloc(length, this->is_persistent); \
|
||
+ if (!__data) { \
|
||
+ return PSFS_ERR_FATAL; \
|
||
+ } \
|
||
+ memcpy(__data, data, length); \
|
||
+ \
|
||
+ __buck = php_stream_bucket_new(stream, __data, length, 1, this->is_persistent TSRMLS_CC); \
|
||
+ if (!__buck) { \
|
||
+ pefree(__data, this->is_persistent); \
|
||
+ return PSFS_ERR_FATAL; \
|
||
+ } \
|
||
+ \
|
||
+ php_stream_bucket_append(buckets_out, __buck TSRMLS_CC); \
|
||
+ }
|
||
+
|
||
+typedef struct _http_chunked_decode_filter_buffer_t {
|
||
+ phpstr buffer;
|
||
+ ulong hexlen;
|
||
+} HTTP_FILTER_BUFFER(chunked_decode);
|
||
+
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+typedef http_encoding_stream HTTP_FILTER_BUFFER(deflate);
|
||
+typedef http_encoding_stream HTTP_FILTER_BUFFER(inflate);
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+
|
||
+
|
||
+static HTTP_FILTER_FUNCTION(chunked_decode)
|
||
+{
|
||
+ int out_avail = 0;
|
||
+ php_stream_bucket *ptr, *nxt;
|
||
+ HTTP_FILTER_BUFFER(chunked_decode) *buffer = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract);
|
||
+
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed = 0;
|
||
+ }
|
||
+
|
||
+ /* new data available? */
|
||
+ if (buckets_in->head) {
|
||
+
|
||
+ /* fetch available bucket data */
|
||
+ for (ptr = buckets_in->head; ptr; ptr = nxt) {
|
||
+ nxt = ptr->next;
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed += ptr->buflen;
|
||
+ }
|
||
+
|
||
+ if (PHPSTR_NOMEM == phpstr_append(PHPSTR(buffer), ptr->buf, ptr->buflen)) {
|
||
+ return PSFS_ERR_FATAL;
|
||
+ }
|
||
+
|
||
+ php_stream_bucket_unlink(ptr TSRMLS_CC);
|
||
+ php_stream_bucket_delref(ptr TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+ if (!phpstr_fix(PHPSTR(buffer))) {
|
||
+ return PSFS_ERR_FATAL;
|
||
+ }
|
||
+
|
||
+ /* we have data in our buffer */
|
||
+ while (PHPSTR_LEN(buffer)) {
|
||
+
|
||
+ /* we already know the size of the chunk and are waiting for data */
|
||
+ if (buffer->hexlen) {
|
||
+
|
||
+ /* not enough data buffered */
|
||
+ if (PHPSTR_LEN(buffer) < buffer->hexlen) {
|
||
+
|
||
+ /* flush anyway? */
|
||
+ if (flags & PSFS_FLAG_FLUSH_INC) {
|
||
+
|
||
+ /* flush all data (should only be chunk data) */
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer));
|
||
+
|
||
+ /* waiting for less data now */
|
||
+ buffer->hexlen -= PHPSTR_LEN(buffer);
|
||
+ /* no more buffered data */
|
||
+ phpstr_reset(PHPSTR(buffer));
|
||
+ /* break */
|
||
+ }
|
||
+
|
||
+ /* we have too less data and don't need to flush */
|
||
+ else {
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* we seem to have all data of the chunk */
|
||
+ else {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(PHPSTR_VAL(buffer), buffer->hexlen);
|
||
+
|
||
+ /* remove outgoing data from the buffer */
|
||
+ phpstr_cut(PHPSTR(buffer), 0, buffer->hexlen);
|
||
+ /* reset hexlen */
|
||
+ buffer->hexlen = 0;
|
||
+ /* continue */
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* we don't know the length of the chunk yet */
|
||
+ else {
|
||
+ size_t off = 0;
|
||
+
|
||
+ /* ignore preceeding CRLFs (too loose?) */
|
||
+ while (off < PHPSTR_LEN(buffer) && (
|
||
+ PHPSTR_VAL(buffer)[off] == '\n' ||
|
||
+ PHPSTR_VAL(buffer)[off] == '\r')) {
|
||
+ ++off;
|
||
+ }
|
||
+ if (off) {
|
||
+ phpstr_cut(PHPSTR(buffer), 0, off);
|
||
+ }
|
||
+
|
||
+ /* still data there? */
|
||
+ if (PHPSTR_LEN(buffer)) {
|
||
+ int eollen;
|
||
+ const char *eolstr;
|
||
+
|
||
+ /* we need eol, so we can be sure we have all hex digits */
|
||
+ phpstr_fix(PHPSTR(buffer));
|
||
+ if ((eolstr = http_locate_eol(PHPSTR_VAL(buffer), &eollen))) {
|
||
+ char *stop = NULL;
|
||
+
|
||
+ /* read in chunk size */
|
||
+ buffer->hexlen = strtoul(PHPSTR_VAL(buffer), &stop, 16);
|
||
+
|
||
+ /* if strtoul() stops at the beginning of the buffered data
|
||
+ there's domething oddly wrong, i.e. bad input */
|
||
+ if (stop == PHPSTR_VAL(buffer)) {
|
||
+ return PSFS_ERR_FATAL;
|
||
+ }
|
||
+
|
||
+ /* cut out <chunk size hex><chunk extension><eol> */
|
||
+ phpstr_cut(PHPSTR(buffer), 0, eolstr + eollen - PHPSTR_VAL(buffer));
|
||
+ /* buffer->hexlen is 0 now or contains the size of the next chunk */
|
||
+ /* continue */
|
||
+ } else {
|
||
+ /* we have not enough data buffered to read in chunk size */
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ /* break */
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* flush before close, but only if we are already waiting for more data */
|
||
+ if ((flags & PSFS_FLAG_FLUSH_CLOSE) && buffer->hexlen && PHPSTR_LEN(buffer)) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer));
|
||
+ phpstr_reset(PHPSTR(buffer));
|
||
+ buffer->hexlen = 0;
|
||
+ }
|
||
+
|
||
+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
|
||
+}
|
||
+
|
||
+static HTTP_FILTER_DESTRUCTOR(chunked_decode)
|
||
+{
|
||
+ HTTP_FILTER_BUFFER(chunked_decode) *b = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract);
|
||
+
|
||
+ phpstr_dtor(PHPSTR(b));
|
||
+ pefree(b, this->is_persistent);
|
||
+}
|
||
+
|
||
+static HTTP_FILTER_FUNCTION(chunked_encode)
|
||
+{
|
||
+ int out_avail = 0;
|
||
+ php_stream_bucket *ptr, *nxt;
|
||
+
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed = 0;
|
||
+ }
|
||
+
|
||
+ /* new data available? */
|
||
+ if (buckets_in->head) {
|
||
+ phpstr buf;
|
||
+ out_avail = 1;
|
||
+
|
||
+ phpstr_init(&buf);
|
||
+
|
||
+ /* fetch available bucket data */
|
||
+ for (ptr = buckets_in->head; ptr; ptr = nxt) {
|
||
+ nxt = ptr->next;
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed += ptr->buflen;
|
||
+ }
|
||
+
|
||
+ phpstr_appendf(&buf, "%x" HTTP_CRLF, ptr->buflen);
|
||
+ phpstr_append(&buf, ptr->buf, ptr->buflen);
|
||
+ phpstr_appends(&buf, HTTP_CRLF);
|
||
+
|
||
+ /* pass through */
|
||
+ NEW_BUCKET(PHPSTR_VAL(&buf), PHPSTR_LEN(&buf));
|
||
+ /* reset */
|
||
+ phpstr_reset(&buf);
|
||
+
|
||
+ php_stream_bucket_unlink(ptr TSRMLS_CC);
|
||
+ php_stream_bucket_delref(ptr TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ /* free buffer */
|
||
+ phpstr_dtor(&buf);
|
||
+ }
|
||
+
|
||
+ /* terminate with "0" */
|
||
+ if (flags & PSFS_FLAG_FLUSH_CLOSE) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET("0" HTTP_CRLF, lenof("0" HTTP_CRLF));
|
||
+ }
|
||
+
|
||
+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
|
||
+}
|
||
+
|
||
+static HTTP_FILTER_OPS(chunked_decode) = {
|
||
+ HTTP_FILTER_FUNC(chunked_decode),
|
||
+ HTTP_FILTER_DTOR(chunked_decode),
|
||
+ "http.chunked_decode"
|
||
+};
|
||
+
|
||
+static HTTP_FILTER_OPS(chunked_encode) = {
|
||
+ HTTP_FILTER_FUNC(chunked_encode),
|
||
+ NULL,
|
||
+ "http.chunked_encode"
|
||
+};
|
||
+
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+
|
||
+static HTTP_FILTER_FUNCTION(deflate)
|
||
+{
|
||
+ int out_avail = 0;
|
||
+ php_stream_bucket *ptr, *nxt;
|
||
+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
|
||
+
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed = 0;
|
||
+ }
|
||
+
|
||
+ /* new data available? */
|
||
+ if (buckets_in->head) {
|
||
+
|
||
+ /* fetch available bucket data */
|
||
+ for (ptr = buckets_in->head; ptr; ptr = nxt) {
|
||
+ char *encoded = NULL;
|
||
+ size_t encoded_len = 0;
|
||
+
|
||
+ nxt = ptr->next;
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed += ptr->buflen;
|
||
+ }
|
||
+
|
||
+ if (ptr->buflen) {
|
||
+ http_encoding_deflate_stream_update(buffer, ptr->buf, ptr->buflen, &encoded, &encoded_len);
|
||
+ if (encoded) {
|
||
+ if (encoded_len) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(encoded, encoded_len);
|
||
+ }
|
||
+ efree(encoded);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ php_stream_bucket_unlink(ptr TSRMLS_CC);
|
||
+ php_stream_bucket_delref(ptr TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* flush & close */
|
||
+ if (flags & PSFS_FLAG_FLUSH_INC) {
|
||
+ char *encoded = NULL;
|
||
+ size_t encoded_len = 0;
|
||
+
|
||
+ http_encoding_deflate_stream_flush(buffer, &encoded, &encoded_len);
|
||
+ if (encoded) {
|
||
+ if (encoded_len) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(encoded, encoded_len);
|
||
+ }
|
||
+ efree(encoded);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (flags & PSFS_FLAG_FLUSH_CLOSE) {
|
||
+ char *encoded = NULL;
|
||
+ size_t encoded_len = 0;
|
||
+
|
||
+ http_encoding_deflate_stream_finish(buffer, &encoded, &encoded_len);
|
||
+ if (encoded) {
|
||
+ if (encoded_len) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(encoded, encoded_len);
|
||
+ }
|
||
+ efree(encoded);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
|
||
+}
|
||
+
|
||
+static HTTP_FILTER_FUNCTION(inflate)
|
||
+{
|
||
+ int out_avail = 0;
|
||
+ php_stream_bucket *ptr, *nxt;
|
||
+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
|
||
+
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed = 0;
|
||
+ }
|
||
+
|
||
+ /* new data available? */
|
||
+ if (buckets_in->head) {
|
||
+
|
||
+ /* fetch available bucket data */
|
||
+ for (ptr = buckets_in->head; ptr; ptr = nxt) {
|
||
+ char *decoded = NULL;
|
||
+ size_t decoded_len = 0;
|
||
+
|
||
+ nxt = ptr->next;
|
||
+ if (bytes_consumed) {
|
||
+ *bytes_consumed += ptr->buflen;
|
||
+ }
|
||
+
|
||
+ if (ptr->buflen) {
|
||
+ http_encoding_inflate_stream_update(buffer, ptr->buf, ptr->buflen, &decoded, &decoded_len);
|
||
+ if (decoded) {
|
||
+ if (decoded_len) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(decoded, decoded_len);
|
||
+ }
|
||
+ efree(decoded);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ php_stream_bucket_unlink(ptr TSRMLS_CC);
|
||
+ php_stream_bucket_delref(ptr TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* flush & close */
|
||
+ if (flags & PSFS_FLAG_FLUSH_INC) {
|
||
+ char *decoded = NULL;
|
||
+ size_t decoded_len = 0;
|
||
+
|
||
+ http_encoding_inflate_stream_flush(buffer, &decoded, &decoded_len);
|
||
+ if (decoded) {
|
||
+ if (decoded_len) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(decoded, decoded_len);
|
||
+ }
|
||
+ efree(decoded);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (flags & PSFS_FLAG_FLUSH_CLOSE) {
|
||
+ char *decoded = NULL;
|
||
+ size_t decoded_len = 0;
|
||
+
|
||
+ http_encoding_inflate_stream_finish(buffer, &decoded, &decoded_len);
|
||
+ if (decoded) {
|
||
+ if (decoded_len) {
|
||
+ out_avail = 1;
|
||
+ NEW_BUCKET(decoded, decoded_len);
|
||
+ }
|
||
+ efree(decoded);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
|
||
+}
|
||
+
|
||
+static HTTP_FILTER_DESTRUCTOR(deflate)
|
||
+{
|
||
+ HTTP_FILTER_BUFFER(deflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
|
||
+ http_encoding_deflate_stream_free(&buffer);
|
||
+}
|
||
+
|
||
+static HTTP_FILTER_DESTRUCTOR(inflate)
|
||
+{
|
||
+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
|
||
+ http_encoding_inflate_stream_free(&buffer);
|
||
+}
|
||
+
|
||
+static HTTP_FILTER_OPS(deflate) = {
|
||
+ HTTP_FILTER_FUNC(deflate),
|
||
+ HTTP_FILTER_DTOR(deflate),
|
||
+ "http.deflate"
|
||
+};
|
||
+
|
||
+static HTTP_FILTER_OPS(inflate) = {
|
||
+ HTTP_FILTER_FUNC(inflate),
|
||
+ HTTP_FILTER_DTOR(inflate),
|
||
+ "http.inflate"
|
||
+};
|
||
+
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+
|
||
+static php_stream_filter *http_filter_create(const char *name, zval *params, int p TSRMLS_DC)
|
||
+{
|
||
+ zval **tmp = ¶ms;
|
||
+ php_stream_filter *f = NULL;
|
||
+
|
||
+ if (!strcasecmp(name, "http.chunked_decode")) {
|
||
+ HTTP_FILTER_BUFFER(chunked_decode) *b = NULL;
|
||
+
|
||
+ if ((b = pecalloc(1, sizeof(HTTP_FILTER_BUFFER(chunked_decode)), p))) {
|
||
+ phpstr_init_ex(PHPSTR(b), 4096, p ? PHPSTR_INIT_PERSISTENT : 0);
|
||
+ if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_decode), b, p))) {
|
||
+ pefree(b, p);
|
||
+ }
|
||
+ }
|
||
+ } else
|
||
+
|
||
+ if (!strcasecmp(name, "http.chunked_encode")) {
|
||
+ f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_encode), NULL, p);
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ } else
|
||
+
|
||
+ if (!strcasecmp(name, "http.inflate")) {
|
||
+ int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
|
||
+ HTTP_FILTER_BUFFER(inflate) *b = NULL;
|
||
+
|
||
+ if ((b = http_encoding_inflate_stream_init(NULL, flags))) {
|
||
+ if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(inflate), b, p))) {
|
||
+ http_encoding_inflate_stream_free(&b);
|
||
+ }
|
||
+ }
|
||
+ } else
|
||
+
|
||
+ if (!strcasecmp(name, "http.deflate")) {
|
||
+ int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
|
||
+ HTTP_FILTER_BUFFER(deflate) *b = NULL;
|
||
+
|
||
+ if (params) {
|
||
+ switch (Z_TYPE_P(params)) {
|
||
+ case IS_ARRAY:
|
||
+ case IS_OBJECT:
|
||
+ if (SUCCESS != zend_hash_find(HASH_OF(params), "flags", sizeof("flags"), (void *) &tmp)) {
|
||
+ break;
|
||
+ }
|
||
+ default:
|
||
+ {
|
||
+ zval *num = http_zsep(IS_LONG, *tmp);
|
||
+
|
||
+ flags |= (Z_LVAL_P(num) & 0x0fffffff);
|
||
+ zval_ptr_dtor(&num);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ if ((b = http_encoding_deflate_stream_init(NULL, flags))) {
|
||
+ if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(deflate), b, p))) {
|
||
+ http_encoding_deflate_stream_free(&b);
|
||
+ }
|
||
+ }
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+ }
|
||
+
|
||
+ return f;
|
||
+}
|
||
+
|
||
+php_stream_filter_factory http_filter_factory = {
|
||
+ http_filter_create
|
||
+};
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/http_functions.c
|
||
@@ -0,0 +1,1424 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_functions.c 300301 2010-06-09 08:30:34Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_CURL
|
||
+#define HTTP_WANT_ZLIB
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_ini.h"
|
||
+#include "ext/standard/php_string.h"
|
||
+#include "zend_operators.h"
|
||
+
|
||
+#ifdef HTTP_HAVE_SESSION
|
||
+# include "ext/session/php_session.h"
|
||
+#endif
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_cache_api.h"
|
||
+#include "php_http_cookie_api.h"
|
||
+#include "php_http_date_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_headers_api.h"
|
||
+#include "php_http_message_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_method_api.h"
|
||
+#include "php_http_persistent_handle_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+
|
||
+/* {{{ proto string http_date([int timestamp])
|
||
+ Compose a valid HTTP date regarding RFC 1123 looking like: "Wed, 22 Dec 2004 11:34:47 GMT" */
|
||
+PHP_FUNCTION(http_date)
|
||
+{
|
||
+ long t = -1;
|
||
+ char *date;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (t == -1) {
|
||
+ t = HTTP_G->request.time;
|
||
+ }
|
||
+
|
||
+ if (!(date = http_date(t))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Could not compose date of timestamp %ld", t);
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_STRING(date, 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_build_url([mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV[, array &new_url]]]])
|
||
+ Build an URL. */
|
||
+PHP_FUNCTION(http_build_url)
|
||
+{
|
||
+ char *url_str = NULL;
|
||
+ size_t url_len = 0;
|
||
+ long flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV;
|
||
+ zval *z_old_url = NULL, *z_new_url = NULL, *z_composed_url = NULL;
|
||
+ php_url *old_url = NULL, *new_url = NULL, *composed_url = NULL;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z!/lz", &z_old_url, &z_new_url, &flags, &z_composed_url) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (z_new_url) {
|
||
+ if (Z_TYPE_P(z_new_url) == IS_ARRAY || Z_TYPE_P(z_new_url) == IS_OBJECT) {
|
||
+ new_url = http_url_from_struct(NULL, HASH_OF(z_new_url));
|
||
+ } else {
|
||
+ convert_to_string(z_new_url);
|
||
+ if (!(new_url = php_url_parse_ex(Z_STRVAL_P(z_new_url), Z_STRLEN_P(z_new_url)))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_new_url));
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (z_old_url) {
|
||
+ if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) {
|
||
+ old_url = http_url_from_struct(NULL, HASH_OF(z_old_url));
|
||
+ } else {
|
||
+ convert_to_string(z_old_url);
|
||
+ if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) {
|
||
+ if (new_url) {
|
||
+ php_url_free(new_url);
|
||
+ }
|
||
+ http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_old_url));
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (z_composed_url) {
|
||
+ http_build_url(flags, old_url, new_url, &composed_url, &url_str, &url_len);
|
||
+ http_url_tostruct(composed_url, z_composed_url);
|
||
+ php_url_free(composed_url);
|
||
+ } else {
|
||
+ http_build_url(flags, old_url, new_url, NULL, &url_str, &url_len);
|
||
+ }
|
||
+
|
||
+ if (new_url) {
|
||
+ php_url_free(new_url);
|
||
+ }
|
||
+ if (old_url) {
|
||
+ php_url_free(old_url);
|
||
+ }
|
||
+
|
||
+ RETURN_STRINGL(url_str, url_len, 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_build_str(array query [, string prefix[, string arg_separator]])
|
||
+ Opponent to parse_str(). */
|
||
+PHP_FUNCTION(http_build_str)
|
||
+{
|
||
+ zval *formdata;
|
||
+ char *prefix = NULL, *arg_sep = INI_STR("arg_separator.output");
|
||
+ int prefix_len = 0, arg_sep_len = strlen(arg_sep);
|
||
+ phpstr formstr;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!arg_sep_len) {
|
||
+ arg_sep = HTTP_URL_ARGSEP;
|
||
+ arg_sep_len = lenof(HTTP_URL_ARGSEP);
|
||
+ }
|
||
+
|
||
+ phpstr_init(&formstr);
|
||
+ if (SUCCESS != http_urlencode_hash_recursive(HASH_OF(formdata), &formstr, arg_sep, arg_sep_len, prefix, prefix_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!formstr.used) {
|
||
+ phpstr_dtor(&formstr);
|
||
+ RETURN_NULL();
|
||
+ }
|
||
+
|
||
+ RETURN_PHPSTR_VAL(&formstr);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#define HTTP_DO_NEGOTIATE_DEFAULT(supported) \
|
||
+ { \
|
||
+ zval **value; \
|
||
+ \
|
||
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \
|
||
+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void *) &value)) { \
|
||
+ RETVAL_ZVAL(*value, 1, 0); \
|
||
+ } else { \
|
||
+ RETVAL_NULL(); \
|
||
+ } \
|
||
+ }
|
||
+
|
||
+#define HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array) \
|
||
+ HTTP_DO_NEGOTIATE_DEFAULT(supported); \
|
||
+ if (rs_array) { \
|
||
+ HashPosition pos; \
|
||
+ zval **value_ptr; \
|
||
+ \
|
||
+ FOREACH_VAL(pos, supported, value_ptr) { \
|
||
+ zval *value = http_zsep(IS_STRING, *value_ptr); \
|
||
+ add_assoc_double(rs_array, Z_STRVAL_P(value), 1.0); \
|
||
+ zval_ptr_dtor(&value); \
|
||
+ } \
|
||
+ }
|
||
+
|
||
+#define HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array) \
|
||
+ { \
|
||
+ char *key; \
|
||
+ uint key_len; \
|
||
+ ulong idx; \
|
||
+ \
|
||
+ if (zend_hash_num_elements(result) && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \
|
||
+ RETVAL_STRINGL(key, key_len-1, 0); \
|
||
+ } else { \
|
||
+ HTTP_DO_NEGOTIATE_DEFAULT(supported); \
|
||
+ } \
|
||
+ \
|
||
+ if (rs_array) { \
|
||
+ zend_hash_copy(Z_ARRVAL_P(rs_array), result, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); \
|
||
+ } \
|
||
+ \
|
||
+ zend_hash_destroy(result); \
|
||
+ FREE_HASHTABLE(result); \
|
||
+ }
|
||
+
|
||
+#define HTTP_DO_NEGOTIATE(type, supported, rs_array) \
|
||
+ { \
|
||
+ HashTable *result; \
|
||
+ if ((result = http_negotiate_ ##type(supported))) { \
|
||
+ HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array); \
|
||
+ } else { \
|
||
+ HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array); \
|
||
+ } \
|
||
+ }
|
||
+
|
||
+/* {{{ proto string http_negotiate_language(array supported[, array &result])
|
||
+ Negotiate the clients preferred language. */
|
||
+PHP_FUNCTION(http_negotiate_language)
|
||
+{
|
||
+ zval *supported, *rs_array = NULL;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (rs_array) {
|
||
+ zval_dtor(rs_array);
|
||
+ array_init(rs_array);
|
||
+ }
|
||
+
|
||
+ HTTP_DO_NEGOTIATE(language, supported, rs_array);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_negotiate_charset(array supported[, array &result])
|
||
+ Negotiate the clients preferred charset. */
|
||
+PHP_FUNCTION(http_negotiate_charset)
|
||
+{
|
||
+ zval *supported, *rs_array = NULL;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (rs_array) {
|
||
+ zval_dtor(rs_array);
|
||
+ array_init(rs_array);
|
||
+ }
|
||
+
|
||
+ HTTP_DO_NEGOTIATE(charset, supported, rs_array);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_negotiate_content_type(array supported[, array &result])
|
||
+ Negotiate the clients preferred content type. */
|
||
+PHP_FUNCTION(http_negotiate_content_type)
|
||
+{
|
||
+ zval *supported, *rs_array = NULL;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (rs_array) {
|
||
+ zval_dtor(rs_array);
|
||
+ array_init(rs_array);
|
||
+ }
|
||
+
|
||
+ HTTP_DO_NEGOTIATE(content_type, supported, rs_array);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_negotiate(mixed value, array supported[, array &result])
|
||
+ Negotiate the user supplied value. */
|
||
+PHP_FUNCTION(http_negotiate)
|
||
+{
|
||
+ zval *value, *supported, *rs_array = NULL;
|
||
+ HashTable *rs;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|z", &value, &supported, &rs_array)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (rs_array) {
|
||
+ zval_dtor(rs_array);
|
||
+ array_init(rs_array);
|
||
+ }
|
||
+
|
||
+ if ((rs = http_negotiate_z(value, Z_ARRVAL_P(supported), http_negotiate_default_func))) {
|
||
+ HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs, supported, rs_array);
|
||
+ } else {
|
||
+ HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_send_status(int status)
|
||
+ Send HTTP status code. */
|
||
+PHP_FUNCTION(http_send_status)
|
||
+{
|
||
+ long status = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (status < 100 || status > 510) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_send_status(status));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_send_last_modified([int timestamp])
|
||
+ Send a "Last-Modified" header with a valid HTTP date. */
|
||
+PHP_FUNCTION(http_send_last_modified)
|
||
+{
|
||
+ long t = -1;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (t == -1) {
|
||
+ t = HTTP_G->request.time;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_send_last_modified(t));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream'])
|
||
+ Send the Content-Type of the sent entity. This is particularly important if you use the http_send() API. */
|
||
+PHP_FUNCTION(http_send_content_type)
|
||
+{
|
||
+ char *ct = "application/x-octetstream";
|
||
+ int ct_len = lenof("application/x-octetstream");
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_send_content_type(ct, ct_len));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false])
|
||
+ Send the Content-Disposition. */
|
||
+PHP_FUNCTION(http_send_content_disposition)
|
||
+{
|
||
+ char *filename;
|
||
+ int f_len;
|
||
+ zend_bool send_inline = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_match_modified([int timestamp[, bool for_range = false]])
|
||
+ Matches the given unix timestamp against the clients "If-Modified-Since" resp. "If-Unmodified-Since" HTTP headers. */
|
||
+PHP_FUNCTION(http_match_modified)
|
||
+{
|
||
+ long t = -1;
|
||
+ zend_bool for_range = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &t, &for_range) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ // current time if not supplied (senseless though)
|
||
+ if (t == -1) {
|
||
+ t = HTTP_G->request.time;
|
||
+ }
|
||
+
|
||
+ if (for_range) {
|
||
+ RETURN_BOOL(http_match_last_modified("HTTP_IF_UNMODIFIED_SINCE", t));
|
||
+ }
|
||
+ RETURN_BOOL(http_match_last_modified("HTTP_IF_MODIFIED_SINCE", t));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_match_etag(string etag[, bool for_range = false])
|
||
+ Matches the given ETag against the clients "If-Match" resp. "If-None-Match" HTTP headers. */
|
||
+PHP_FUNCTION(http_match_etag)
|
||
+{
|
||
+ int etag_len;
|
||
+ char *etag;
|
||
+ zend_bool for_range = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &etag, &etag_len, &for_range) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (for_range) {
|
||
+ RETURN_BOOL(http_match_etag("HTTP_IF_MATCH", etag));
|
||
+ }
|
||
+ RETURN_BOOL(http_match_etag("HTTP_IF_NONE_MATCH", etag));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]])
|
||
+ Attempts to cache the sent entity by its last modification date. */
|
||
+PHP_FUNCTION(http_cache_last_modified)
|
||
+{
|
||
+ long last_modified = 0, send_modified = 0, t;
|
||
+ zval *zlm;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
|
||
+
|
||
+ t = HTTP_G->request.time;
|
||
+
|
||
+ /* 0 or omitted */
|
||
+ if (!last_modified) {
|
||
+ /* does the client have? (att: caching "forever") */
|
||
+ if ((zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE", 1))) {
|
||
+ last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm));
|
||
+ /* send current time */
|
||
+ } else {
|
||
+ send_modified = t;
|
||
+ }
|
||
+ /* negative value is supposed to be expiration time */
|
||
+ } else if (last_modified < 0) {
|
||
+ last_modified += t;
|
||
+ send_modified = t;
|
||
+ /* send supplied time explicitly */
|
||
+ } else {
|
||
+ send_modified = last_modified;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_cache_etag([string etag])
|
||
+ Attempts to cache the sent entity by its ETag, either supplied or generated by the hash algorithm specified by the INI setting "http.etag.mode". */
|
||
+PHP_FUNCTION(http_cache_etag)
|
||
+{
|
||
+ char *etag = NULL;
|
||
+ int etag_len = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
|
||
+
|
||
+ RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string ob_etaghandler(string data, int mode)
|
||
+ For use with ob_start(). Output buffer handler generating an ETag with the hash algorithm specified with the INI setting "http.etag.mode". */
|
||
+PHP_FUNCTION(ob_etaghandler)
|
||
+{
|
||
+ char *data;
|
||
+ int data_len;
|
||
+ long mode;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ Z_TYPE_P(return_value) = IS_STRING;
|
||
+ http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void http_throttle(double sec[, int bytes = 40960])
|
||
+ Sets the throttle delay and send buffer size for use with http_send() API. */
|
||
+PHP_FUNCTION(http_throttle)
|
||
+{
|
||
+ long chunk_size = HTTP_SENDBUF_SIZE;
|
||
+ double interval;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &interval, &chunk_size)) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ HTTP_G->send.throttle_delay = interval;
|
||
+ HTTP_G->send.buffer_size = chunk_size;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void http_redirect([string url[, array params[, bool session = false[, int status = 302]]]])
|
||
+ Redirect to the given url. */
|
||
+PHP_FUNCTION(http_redirect)
|
||
+{
|
||
+ int url_len = 0;
|
||
+ size_t query_len = 0;
|
||
+ zend_bool session = 0, free_params = 0;
|
||
+ zval *params = NULL;
|
||
+ long status = HTTP_REDIRECT;
|
||
+ char *query = NULL, *url = NULL, *URI, *LOC, *RED = NULL;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bl", &url, &url_len, ¶ms, &session, &status) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+#ifdef HTTP_HAVE_SESSION
|
||
+ /* append session info */
|
||
+ if (session) {
|
||
+ if (!params) {
|
||
+ free_params = 1;
|
||
+ MAKE_STD_ZVAL(params);
|
||
+ array_init(params);
|
||
+ }
|
||
+ if (PS(session_status) == php_session_active) {
|
||
+ if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not append session information");
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ /* treat params array with http_build_query() */
|
||
+ if (params) {
|
||
+ if (SUCCESS != http_urlencode_hash_ex(Z_ARRVAL_P(params), 0, NULL, 0, &query, &query_len)) {
|
||
+ if (free_params) {
|
||
+ zval_dtor(params);
|
||
+ FREE_ZVAL(params);
|
||
+ }
|
||
+ if (query) {
|
||
+ efree(query);
|
||
+ }
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ URI = http_absolute_url_ex(url, HTTP_URL_FROM_ENV);
|
||
+
|
||
+ if (query_len) {
|
||
+ spprintf(&LOC, 0, "Location: %s?%s", URI, query);
|
||
+ if (status != 300) {
|
||
+ spprintf(&RED, 0, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, query, URI, query);
|
||
+ }
|
||
+ } else {
|
||
+ spprintf(&LOC, 0, "Location: %s", URI);
|
||
+ if (status != 300) {
|
||
+ spprintf(&RED, 0, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ efree(URI);
|
||
+ if (query) {
|
||
+ efree(query);
|
||
+ }
|
||
+ if (free_params) {
|
||
+ zval_dtor(params);
|
||
+ FREE_ZVAL(params);
|
||
+ }
|
||
+
|
||
+ switch (status) {
|
||
+ case 300:
|
||
+ RETVAL_SUCCESS(http_send_status_header(status, LOC));
|
||
+ efree(LOC);
|
||
+ return;
|
||
+
|
||
+ case HTTP_REDIRECT_PERM:
|
||
+ case HTTP_REDIRECT_FOUND:
|
||
+ case HTTP_REDIRECT_POST:
|
||
+ case HTTP_REDIRECT_PROXY:
|
||
+ case HTTP_REDIRECT_TEMP:
|
||
+ break;
|
||
+
|
||
+ case 306:
|
||
+ default:
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Unsupported redirection status code: %ld", status);
|
||
+ case HTTP_REDIRECT:
|
||
+ if ( SG(request_info).request_method &&
|
||
+ strcasecmp(SG(request_info).request_method, "HEAD") &&
|
||
+ strcasecmp(SG(request_info).request_method, "GET")) {
|
||
+ status = HTTP_REDIRECT_POST;
|
||
+ } else {
|
||
+ status = HTTP_REDIRECT_FOUND;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_exit_ex(status, LOC, RED, 1));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_send_data(string data)
|
||
+ Sends raw data with support for (multiple) range requests. */
|
||
+PHP_FUNCTION(http_send_data)
|
||
+{
|
||
+ int data_len;
|
||
+ char *data_buf;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data_buf, &data_len) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_send_data(data_buf, data_len));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_send_file(string file)
|
||
+ Sends a file with support for (multiple) range requests. */
|
||
+PHP_FUNCTION(http_send_file)
|
||
+{
|
||
+ char *file;
|
||
+ int flen = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &flen) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (!flen) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_send_file(file));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_send_stream(resource stream)
|
||
+ Sends an already opened stream with support for (multiple) range requests. */
|
||
+PHP_FUNCTION(http_send_stream)
|
||
+{
|
||
+ zval *zstream;
|
||
+ php_stream *file;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ php_stream_from_zval(file, &zstream);
|
||
+ RETURN_SUCCESS(http_send_stream(file));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_chunked_decode(string encoded)
|
||
+ Decodes a string that was HTTP-chunked encoded. */
|
||
+PHP_FUNCTION(http_chunked_decode)
|
||
+{
|
||
+ char *encoded = NULL, *decoded = NULL;
|
||
+ size_t decoded_len = 0;
|
||
+ int encoded_len = 0;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (NULL != http_encoding_dechunk(encoded, encoded_len, &decoded, &decoded_len)) {
|
||
+ RETURN_STRINGL(decoded, (int) decoded_len, 0);
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto object http_parse_message(string message)
|
||
+ Parses (a) http_message(s) into a simple recursive object structure. */
|
||
+PHP_FUNCTION(http_parse_message)
|
||
+{
|
||
+ char *message;
|
||
+ int message_len;
|
||
+ http_message *msg = NULL;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &message, &message_len)) {
|
||
+ RETURN_NULL();
|
||
+ }
|
||
+
|
||
+ if ((msg = http_message_parse(message, message_len))) {
|
||
+ object_init(return_value);
|
||
+ http_message_tostruct_recursive(msg, return_value);
|
||
+ http_message_free(&msg);
|
||
+ } else {
|
||
+ RETURN_NULL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array http_parse_headers(string header)
|
||
+ Parses HTTP headers into an associative array. */
|
||
+PHP_FUNCTION(http_parse_headers)
|
||
+{
|
||
+ char *header;
|
||
+ int header_len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ array_init(return_value);
|
||
+ if (SUCCESS != http_parse_headers(header, return_value)) {
|
||
+ zval_dtor(return_value);
|
||
+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse headers");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}}*/
|
||
+
|
||
+/* {{{ proto object http_parse_cookie(string cookie[, int flags[, array allowed_extras]])
|
||
+ Parses HTTP cookies like sent in a response into a struct. */
|
||
+PHP_FUNCTION(http_parse_cookie)
|
||
+{
|
||
+ char *cookie, **allowed_extras = NULL;
|
||
+ int i = 0, cookie_len;
|
||
+ long flags = 0;
|
||
+ zval *allowed_extras_array = NULL, **entry = NULL;
|
||
+ HashPosition pos;
|
||
+ http_cookie_list list;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!", &cookie, &cookie_len, &flags, &allowed_extras_array)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (allowed_extras_array) {
|
||
+ allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
|
||
+ FOREACH_VAL(pos, allowed_extras_array, entry) {
|
||
+ zval *data = http_zsep(IS_STRING, *entry);
|
||
+ allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
|
||
+ zval_ptr_dtor(&data);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (http_parse_cookie_ex(&list, cookie, flags, allowed_extras)) {
|
||
+ object_init(return_value);
|
||
+ http_cookie_list_tostruct(&list, return_value);
|
||
+ http_cookie_list_dtor(&list);
|
||
+ } else {
|
||
+ RETVAL_FALSE;
|
||
+ }
|
||
+
|
||
+ if (allowed_extras) {
|
||
+ for (i = 0; allowed_extras[i]; ++i) {
|
||
+ efree(allowed_extras[i]);
|
||
+ }
|
||
+ efree(allowed_extras);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_build_cookie(array cookie)
|
||
+ Build a cookie string from an array/object like returned by http_parse_cookie(). */
|
||
+PHP_FUNCTION(http_build_cookie)
|
||
+{
|
||
+ char *str = NULL;
|
||
+ size_t len = 0;
|
||
+ zval *strct;
|
||
+ http_cookie_list list;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &strct)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ http_cookie_list_fromstruct(&list, strct);
|
||
+ http_cookie_list_tostring(&list, &str, &len);
|
||
+ http_cookie_list_dtor(&list);
|
||
+
|
||
+ RETURN_STRINGL(str, len, 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto object http_parse_params(string param[, int flags = HTTP_PARAMS_DEFAULT])
|
||
+ Parse parameter list. */
|
||
+PHP_FUNCTION(http_parse_params)
|
||
+{
|
||
+ char *param;
|
||
+ int param_len;
|
||
+ zval *params;
|
||
+ long flags = HTTP_PARAMS_DEFAULT;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", ¶m, ¶m_len, &flags)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(params);
|
||
+ array_init(params);
|
||
+ if (SUCCESS != http_parse_params(param, flags, Z_ARRVAL_P(params))) {
|
||
+ zval_ptr_dtor(¶ms);
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ object_init(return_value);
|
||
+ add_property_zval(return_value, "params", params);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zval_ptr_dtor(¶ms);
|
||
+#endif
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array http_get_request_headers(void)
|
||
+ Get a list of incoming HTTP headers. */
|
||
+PHP_FUNCTION(http_get_request_headers)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ array_init(return_value);
|
||
+ http_get_request_headers(Z_ARRVAL_P(return_value));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_get_request_body(void)
|
||
+ Get the raw request body (e.g. POST or PUT data). */
|
||
+PHP_FUNCTION(http_get_request_body)
|
||
+{
|
||
+ char *body;
|
||
+ size_t length;
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (SUCCESS == http_get_request_body(&body, &length)) {
|
||
+ RETURN_STRINGL(body, (int) length, 0);
|
||
+ } else {
|
||
+ RETURN_NULL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto resource http_get_request_body_stream(void)
|
||
+ Create a stream to read the raw request body (e.g. POST or PUT data). This function can only be used once if the request method was another than POST. */
|
||
+PHP_FUNCTION(http_get_request_body_stream)
|
||
+{
|
||
+ php_stream *s;
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ if ((s = http_get_request_body_stream())) {
|
||
+ php_stream_to_zval(s, return_value);
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Failed to create request body stream");
|
||
+ RETURN_NULL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_match_request_header(string header, string value[, bool match_case = false])
|
||
+ Match an incoming HTTP header. */
|
||
+PHP_FUNCTION(http_match_request_header)
|
||
+{
|
||
+ char *header, *value;
|
||
+ int header_len, value_len;
|
||
+ zend_bool match_case = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &header, &header_len, &value, &value_len, &match_case)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_BOOL(http_match_request_header_ex(header, value, match_case));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto object http_persistent_handles_count() */
|
||
+PHP_FUNCTION(http_persistent_handles_count)
|
||
+{
|
||
+ NO_ARGS;
|
||
+ object_init(return_value);
|
||
+ if (!http_persistent_handle_statall_ex(HASH_OF(return_value))) {
|
||
+ zval_dtor(return_value);
|
||
+ RETURN_NULL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void http_persistent_handles_clean([string name]) */
|
||
+PHP_FUNCTION(http_persistent_handles_clean)
|
||
+{
|
||
+ char *name_str = NULL;
|
||
+ int name_len = 0;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) {
|
||
+ http_persistent_handle_cleanup_ex(name_str, name_len, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_persistent_handles_ident([string ident]) */
|
||
+PHP_FUNCTION(http_persistent_handles_ident)
|
||
+{
|
||
+ char *ident_str = NULL;
|
||
+ int ident_len = 0;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ident_str, &ident_len)) {
|
||
+ RETVAL_STRING(zend_ini_string(ZEND_STRS("http.persistent.handles.ident"), 0), 1);
|
||
+ if (ident_str && ident_len) {
|
||
+ zend_alter_ini_entry(ZEND_STRS("http.persistent.handles.ident"), ident_str, ident_len, ZEND_INI_USER, PHP_INI_STAGE_RUNTIME);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ HAVE_CURL */
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+
|
||
+#define RETVAL_RESPONSE_OR_BODY(request) \
|
||
+ { \
|
||
+ zval **bodyonly; \
|
||
+ \
|
||
+ /* check if only the body should be returned */ \
|
||
+ if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void *) &bodyonly)) && i_zend_is_true(*bodyonly)) { \
|
||
+ http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \
|
||
+ \
|
||
+ if (msg) { \
|
||
+ RETVAL_STRINGL(PHPSTR_VAL(&msg->body), PHPSTR_LEN(&msg->body), 1); \
|
||
+ http_message_free(&msg); \
|
||
+ } \
|
||
+ } else { \
|
||
+ RETVAL_STRINGL(request.conv.response.data, request.conv.response.used, 1); \
|
||
+ } \
|
||
+ }
|
||
+
|
||
+/* {{{ proto string http_get(string url[, array options[, array &info]])
|
||
+ Performs an HTTP GET request on the supplied url. */
|
||
+PHP_FUNCTION(http_get)
|
||
+{
|
||
+ zval *options = NULL, *info = NULL;
|
||
+ char *URL;
|
||
+ int URL_len;
|
||
+ http_request request;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, HTTP_GET, URL);
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_head(string url[, array options[, array &info]])
|
||
+ Performs an HTTP HEAD request on the supplied url. */
|
||
+PHP_FUNCTION(http_head)
|
||
+{
|
||
+ zval *options = NULL, *info = NULL;
|
||
+ char *URL;
|
||
+ int URL_len;
|
||
+ http_request request;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, HTTP_HEAD, URL);
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_post_data(string url, string data[, array options[, array &info]])
|
||
+ Performs an HTTP POST request on the supplied url. */
|
||
+PHP_FUNCTION(http_post_data)
|
||
+{
|
||
+ zval *options = NULL, *info = NULL;
|
||
+ char *URL, *postdata;
|
||
+ int postdata_len, URL_len;
|
||
+ http_request_body body;
|
||
+ http_request request;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, HTTP_POST, URL);
|
||
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, postdata, postdata_len, 0);
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_post_fields(string url, array data[, array files[, array options[, array &info]]])
|
||
+ Performs an HTTP POST request on the supplied url. */
|
||
+PHP_FUNCTION(http_post_fields)
|
||
+{
|
||
+ zval *options = NULL, *info = NULL, *fields = NULL, *files = NULL;
|
||
+ char *URL;
|
||
+ int URL_len;
|
||
+ http_request_body body;
|
||
+ http_request request;
|
||
+
|
||
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa!|a!a/!z", &URL, &URL_len, &fields, &files, &options, &info) != SUCCESS) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!http_request_body_fill(&body, fields ? Z_ARRVAL_P(fields) : NULL, files ? Z_ARRVAL_P(files) : NULL)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, HTTP_POST, URL);
|
||
+ request.body = &body;
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_put_file(string url, string file[, array options[, array &info]])
|
||
+ Performs an HTTP PUT request on the supplied url. */
|
||
+PHP_FUNCTION(http_put_file)
|
||
+{
|
||
+ char *URL, *file;
|
||
+ int URL_len, f_len;
|
||
+ zval *options = NULL, *info = NULL;
|
||
+ php_stream *stream;
|
||
+ php_stream_statbuf ssb;
|
||
+ http_request_body body;
|
||
+ http_request request;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &file, &f_len, &options, &info)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!(stream = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (php_stream_stat(stream, &ssb)) {
|
||
+ php_stream_close(stream);
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, HTTP_PUT, URL);
|
||
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_put_stream(string url, resource stream[, array options[, array &info]])
|
||
+ Performs an HTTP PUT request on the supplied url. */
|
||
+PHP_FUNCTION(http_put_stream)
|
||
+{
|
||
+ zval *resource, *options = NULL, *info = NULL;
|
||
+ char *URL;
|
||
+ int URL_len;
|
||
+ php_stream *stream;
|
||
+ php_stream_statbuf ssb;
|
||
+ http_request_body body;
|
||
+ http_request request;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ php_stream_from_zval(stream, &resource);
|
||
+ if (php_stream_stat(stream, &ssb)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, HTTP_PUT, URL);
|
||
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 0);
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_put_data(string url, string data[, array options[, array &info]])
|
||
+ Performs an HTTP PUT request on the supplied url. */
|
||
+PHP_FUNCTION(http_put_data)
|
||
+{
|
||
+ char *URL, *data;
|
||
+ int URL_len, data_len;
|
||
+ zval *options = NULL, *info = NULL;
|
||
+ http_request_body body;
|
||
+ http_request request;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &data, &data_len, &options, &info)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, HTTP_PUT, URL);
|
||
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_request(int method, string url[, string body[, array options[, array &info]]])
|
||
+ Performs a custom HTTP request on the supplied url. */
|
||
+PHP_FUNCTION(http_request)
|
||
+{
|
||
+ long meth;
|
||
+ char *URL, *data = NULL;
|
||
+ int URL_len, data_len = 0;
|
||
+ zval *options = NULL, *info = NULL;
|
||
+ http_request_body body;
|
||
+ http_request request;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|sa/!z", &meth, &URL, &URL_len, &data, &data_len, &options, &info)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info) {
|
||
+ zval_dtor(info);
|
||
+ array_init(info);
|
||
+ }
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, meth, URL);
|
||
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
|
||
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
|
||
+ http_request_exec(&request);
|
||
+ if (info) {
|
||
+ http_request_info(&request, Z_ARRVAL_P(info));
|
||
+ }
|
||
+ RETVAL_RESPONSE_OR_BODY(request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_request_body_encode(array fields, array files)
|
||
+ Generate x-www-form-urlencoded resp. form-data encoded request body. */
|
||
+PHP_FUNCTION(http_request_body_encode)
|
||
+{
|
||
+ zval *fields = NULL, *files = NULL;
|
||
+ HashTable *fields_ht, *files_ht;
|
||
+ http_request_body body;
|
||
+ char *buf;
|
||
+ size_t len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!", &fields, &files)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ fields_ht = (fields && Z_TYPE_P(fields) == IS_ARRAY) ? Z_ARRVAL_P(fields) : NULL;
|
||
+ files_ht = (files && Z_TYPE_P(files) == IS_ARRAY) ? Z_ARRVAL_P(files) : NULL;
|
||
+ if (http_request_body_fill(&body, fields_ht, files_ht) && (SUCCESS == http_request_body_encode(&body, &buf, &len))) {
|
||
+ RETVAL_STRINGL(buf, len, 0);
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not encode request body");
|
||
+ RETVAL_FALSE;
|
||
+ }
|
||
+ http_request_body_dtor(&body);
|
||
+}
|
||
+#endif /* HTTP_HAVE_CURL */
|
||
+/* }}} HAVE_CURL */
|
||
+
|
||
+/* {{{ proto int http_request_method_register(string method)
|
||
+ Register a custom request method. */
|
||
+PHP_FUNCTION(http_request_method_register)
|
||
+{
|
||
+ char *method;
|
||
+ int method_len;
|
||
+ ulong existing;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if ((existing = http_request_method_exists(1, 0, method))) {
|
||
+ RETURN_LONG((long) existing);
|
||
+ }
|
||
+
|
||
+ RETVAL_LONG((long) http_request_method_register(method, method_len));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool http_request_method_unregister(mixed method)
|
||
+ Unregister a previously registered custom request method. */
|
||
+PHP_FUNCTION(http_request_method_unregister)
|
||
+{
|
||
+ zval *method;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ switch (Z_TYPE_P(method)) {
|
||
+ case IS_OBJECT:
|
||
+ convert_to_string(method);
|
||
+ case IS_STRING:
|
||
+ if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
|
||
+ convert_to_long(method);
|
||
+ } else {
|
||
+ int mn;
|
||
+ if (!(mn = http_request_method_exists(1, 0, Z_STRVAL_P(method)))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ zval_dtor(method);
|
||
+ ZVAL_LONG(method, (long)mn);
|
||
+ }
|
||
+ case IS_LONG:
|
||
+ RETURN_SUCCESS(http_request_method_unregister(Z_LVAL_P(method)));
|
||
+ default:
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int http_request_method_exists(mixed method)
|
||
+ Check if a request method is registered (or available by default). */
|
||
+PHP_FUNCTION(http_request_method_exists)
|
||
+{
|
||
+ if (return_value_used) {
|
||
+ zval *method;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ switch (Z_TYPE_P(method)) {
|
||
+ case IS_OBJECT:
|
||
+ convert_to_string(method);
|
||
+ case IS_STRING:
|
||
+ if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
|
||
+ convert_to_long(method);
|
||
+ } else {
|
||
+ RETURN_LONG((long) http_request_method_exists(1, 0, Z_STRVAL_P(method)));
|
||
+ }
|
||
+ case IS_LONG:
|
||
+ RETURN_LONG((long) http_request_method_exists(0, (int) Z_LVAL_P(method), NULL));
|
||
+ default:
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_request_method_name(int method)
|
||
+ Get the literal string representation of a standard or registered request method. */
|
||
+PHP_FUNCTION(http_request_method_name)
|
||
+{
|
||
+ if (return_value_used) {
|
||
+ long method;
|
||
+
|
||
+ if ((SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method)) || (method < 0)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_STRING(estrdup(http_request_method_name((int) method)), 0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ */
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+
|
||
+/* {{{ proto string http_deflate(string data[, int flags = 0])
|
||
+ Compress data with gzip, zlib AKA deflate or raw deflate encoding. */
|
||
+PHP_FUNCTION(http_deflate)
|
||
+{
|
||
+ char *data;
|
||
+ int data_len;
|
||
+ long flags = 0;
|
||
+
|
||
+ RETVAL_NULL();
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags)) {
|
||
+ char *encoded;
|
||
+ size_t encoded_len;
|
||
+
|
||
+ if (SUCCESS == http_encoding_deflate(flags, data, data_len, &encoded, &encoded_len)) {
|
||
+ RETURN_STRINGL(encoded, (int) encoded_len, 0);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string http_inflate(string data)
|
||
+ Decompress data compressed with either gzip, deflate AKA zlib or raw deflate encoding. */
|
||
+PHP_FUNCTION(http_inflate)
|
||
+{
|
||
+ char *data;
|
||
+ int data_len;
|
||
+
|
||
+ RETVAL_NULL();
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
|
||
+ char *decoded;
|
||
+ size_t decoded_len;
|
||
+
|
||
+ if (SUCCESS == http_encoding_inflate(data, data_len, &decoded, &decoded_len)) {
|
||
+ RETURN_STRINGL(decoded, (int) decoded_len, 0);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string ob_deflatehandler(string data, int mode)
|
||
+ For use with ob_start(). The deflate output buffer handler can only be used once. */
|
||
+PHP_FUNCTION(ob_deflatehandler)
|
||
+{
|
||
+ char *data;
|
||
+ int data_len;
|
||
+ long mode;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ http_ob_deflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
|
||
+ Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string ob_inflatehandler(string data, int mode)
|
||
+ For use with ob_start(). Same restrictions as with ob_deflatehandler apply. */
|
||
+PHP_FUNCTION(ob_inflatehandler)
|
||
+{
|
||
+ char *data;
|
||
+ int data_len;
|
||
+ long mode;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ http_ob_inflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
|
||
+ Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int http_support([int feature = 0])
|
||
+ Check for feature that require external libraries. */
|
||
+PHP_FUNCTION(http_support)
|
||
+{
|
||
+ long feature = 0;
|
||
+
|
||
+ RETVAL_LONG(0L);
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &feature)) {
|
||
+ RETVAL_LONG(http_support(feature));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_headers_api.c
|
||
@@ -0,0 +1,534 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_headers_api.c 300300 2010-06-09 07:29:35Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "ext/standard/url.h"
|
||
+#include "ext/standard/php_string.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_headers_api.h"
|
||
+
|
||
+#ifndef HTTP_DBG_NEG
|
||
+# define HTTP_DBG_NEG 0
|
||
+#endif
|
||
+
|
||
+/* {{{ static void http_grab_response_headers(void *, void *) */
|
||
+static void http_grab_response_headers(void *data, void *arg TSRMLS_DC)
|
||
+{
|
||
+ phpstr_appendl(PHPSTR(arg), ((sapi_header_struct *)data)->header);
|
||
+ phpstr_appends(PHPSTR(arg), HTTP_CRLF);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static int http_sort_q(const void *, const void *) */
|
||
+static int http_sort_q(const void *a, const void *b TSRMLS_DC)
|
||
+{
|
||
+ Bucket *f, *s;
|
||
+ zval result, *first, *second;
|
||
+
|
||
+ f = *((Bucket **) a);
|
||
+ s = *((Bucket **) b);
|
||
+
|
||
+ first = *((zval **) f->pData);
|
||
+ second= *((zval **) s->pData);
|
||
+
|
||
+ if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) {
|
||
+ return 0;
|
||
+ }
|
||
+ return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ char *http_negotiate_language_func */
|
||
+char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
|
||
+{
|
||
+ zval **value;
|
||
+ HashPosition pos;
|
||
+ const char *dash_test;
|
||
+
|
||
+ FOREACH_HASH_VAL(pos, supported, value) {
|
||
+#if HTTP_DBG_NEG
|
||
+ fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
|
||
+#endif
|
||
+ if (!strcasecmp(Z_STRVAL_PP(value), test)) {
|
||
+ return Z_STRVAL_PP(value);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* no distinct match found, so try primaries */
|
||
+ if ((dash_test = strchr(test, '-'))) {
|
||
+ FOREACH_HASH_VAL(pos, supported, value) {
|
||
+ int len = dash_test - test;
|
||
+#if HTTP_DBG_NEG
|
||
+ fprintf(stderr, "strncasecmp('%s', '%s', %d)\n", Z_STRVAL_PP(value), test, len);
|
||
+#endif
|
||
+ if ( (!strncasecmp(Z_STRVAL_PP(value), test, len)) &&
|
||
+ ( (Z_STRVAL_PP(value)[len] == '\0') ||
|
||
+ (Z_STRVAL_PP(value)[len] == '-'))) {
|
||
+ *quality *= .9;
|
||
+ return Z_STRVAL_PP(value);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ char *http_negotiate_default_func */
|
||
+char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
|
||
+{
|
||
+ zval **value;
|
||
+ HashPosition pos;
|
||
+
|
||
+ FOREACH_HASH_VAL(pos, supported, value) {
|
||
+#if HTTP_DBG_NEG
|
||
+ fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
|
||
+#endif
|
||
+ if (!strcasecmp(Z_STRVAL_PP(value), test)) {
|
||
+ return Z_STRVAL_PP(value);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ HashTable *http_negotiate_z(zval *, HashTable *, negotiate_func_t) */
|
||
+PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC)
|
||
+{
|
||
+ zval *accept = http_zsep(IS_STRING, value);
|
||
+ HashTable *result = NULL;
|
||
+
|
||
+ if (Z_STRLEN_P(accept)) {
|
||
+ zval ex_arr, ex_del;
|
||
+
|
||
+ INIT_PZVAL(&ex_del);
|
||
+ INIT_PZVAL(&ex_arr);
|
||
+ ZVAL_STRINGL(&ex_del, ",", 1, 0);
|
||
+ array_init(&ex_arr);
|
||
+
|
||
+ php_explode(&ex_del, accept, &ex_arr, INT_MAX);
|
||
+
|
||
+ if (zend_hash_num_elements(Z_ARRVAL(ex_arr)) > 0) {
|
||
+ int i = 0;
|
||
+ HashPosition pos;
|
||
+ zval **entry, array;
|
||
+
|
||
+ INIT_PZVAL(&array);
|
||
+ array_init(&array);
|
||
+
|
||
+ FOREACH_HASH_VAL(pos, Z_ARRVAL(ex_arr), entry) {
|
||
+ int ident_len;
|
||
+ double quality;
|
||
+ char *selected, *identifier, *freeme;
|
||
+ const char *separator;
|
||
+
|
||
+#if HTTP_DBG_NEG
|
||
+ fprintf(stderr, "Checking %s\n", Z_STRVAL_PP(entry));
|
||
+#endif
|
||
+
|
||
+ if ((separator = strchr(Z_STRVAL_PP(entry), ';'))) {
|
||
+ const char *ptr = separator;
|
||
+
|
||
+ while (*++ptr && !HTTP_IS_CTYPE(digit, *ptr) && '.' != *ptr);
|
||
+
|
||
+ quality = zend_strtod(ptr, NULL);
|
||
+ identifier = estrndup(Z_STRVAL_PP(entry), ident_len = separator - Z_STRVAL_PP(entry));
|
||
+ } else {
|
||
+ quality = 1000.0 - i++;
|
||
+ identifier = estrndup(Z_STRVAL_PP(entry), ident_len = Z_STRLEN_PP(entry));
|
||
+ }
|
||
+ freeme = identifier;
|
||
+
|
||
+ while (HTTP_IS_CTYPE(space, *identifier)) {
|
||
+ ++identifier;
|
||
+ --ident_len;
|
||
+ }
|
||
+ while (ident_len && HTTP_IS_CTYPE(space, identifier[ident_len - 1])) {
|
||
+ identifier[--ident_len] = '\0';
|
||
+ }
|
||
+
|
||
+ if ((selected = neg(identifier, &quality, supported TSRMLS_CC))) {
|
||
+ /* don't overwrite previously set with higher quality */
|
||
+ if (!zend_hash_exists(Z_ARRVAL(array), selected, strlen(selected) + 1)) {
|
||
+ add_assoc_double(&array, selected, quality);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ efree(freeme);
|
||
+ }
|
||
+
|
||
+ result = Z_ARRVAL(array);
|
||
+ zend_hash_sort(result, zend_qsort, http_sort_q, 0 TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ zval_dtor(&ex_arr);
|
||
+ }
|
||
+
|
||
+ zval_ptr_dtor(&accept);
|
||
+
|
||
+ return result;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ HashTable *http_negotiate_q(const char *, HashTable *, negotiate_func_t) */
|
||
+PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC)
|
||
+{
|
||
+ zval *accept;
|
||
+
|
||
+#if HTTP_DBG_NEG
|
||
+ fprintf(stderr, "Reading header %s: ", header);
|
||
+#endif
|
||
+ if (!(accept = http_get_server_var(header, 1))) {
|
||
+ return NULL;
|
||
+ }
|
||
+#if HTTP_DBG_NEG
|
||
+ fprintf(stderr, "%s\n", Z_STRVAL_P(accept));
|
||
+#endif
|
||
+
|
||
+ return http_negotiate_z(accept, supported, neg);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_range_status http_get_request_ranges(HashTable *ranges, size_t) */
|
||
+PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC)
|
||
+{
|
||
+ zval *zrange;
|
||
+ char *range, c;
|
||
+ long begin = -1, end = -1, *ptr;
|
||
+
|
||
+ if ( !(zrange = http_get_server_var("HTTP_RANGE", 1)) ||
|
||
+ (size_t) Z_STRLEN_P(zrange) < lenof("bytes=") || strncmp(Z_STRVAL_P(zrange), "bytes=", lenof("bytes="))) {
|
||
+ return RANGE_NO;
|
||
+ }
|
||
+ range = Z_STRVAL_P(zrange) + lenof("bytes=");
|
||
+ ptr = &begin;
|
||
+
|
||
+ do {
|
||
+ switch (c = *(range++)) {
|
||
+ case '0':
|
||
+ /* allow 000... - shall we? */
|
||
+ if (*ptr != -10) {
|
||
+ *ptr *= 10;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case '1': case '2': case '3':
|
||
+ case '4': case '5': case '6':
|
||
+ case '7': case '8': case '9':
|
||
+ /*
|
||
+ * If the value of the pointer is already set (non-negative)
|
||
+ * then multiply its value by ten and add the current value,
|
||
+ * else initialise the pointers value with the current value
|
||
+ * --
|
||
+ * This let us recognize empty fields when validating the
|
||
+ * ranges, i.e. a "-10" for begin and "12345" for the end
|
||
+ * was the following range request: "Range: bytes=0-12345";
|
||
+ * While a "-1" for begin and "12345" for the end would
|
||
+ * have been: "Range: bytes=-12345".
|
||
+ */
|
||
+ if (*ptr > 0) {
|
||
+ *ptr *= 10;
|
||
+ *ptr += c - '0';
|
||
+ } else {
|
||
+ *ptr = c - '0';
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case '-':
|
||
+ ptr = &end;
|
||
+ break;
|
||
+
|
||
+ case ' ':
|
||
+ break;
|
||
+
|
||
+ case 0:
|
||
+ case ',':
|
||
+
|
||
+ if (length) {
|
||
+ /* validate ranges */
|
||
+ switch (begin) {
|
||
+ /* "0-12345" */
|
||
+ case -10:
|
||
+ switch (end) {
|
||
+ /* "0-" */
|
||
+ case -1:
|
||
+ return RANGE_NO;
|
||
+
|
||
+ /* "0-0" */
|
||
+ case -10:
|
||
+ end = 0;
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ if (length <= (size_t) end) {
|
||
+ return RANGE_ERR;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ begin = 0;
|
||
+ break;
|
||
+
|
||
+ /* "-12345" */
|
||
+ case -1:
|
||
+ /* "-", "-0" or overflow */
|
||
+ if (end == -1 || end == -10 || length <= (size_t) end) {
|
||
+ return RANGE_ERR;
|
||
+ }
|
||
+ begin = length - end;
|
||
+ end = length - 1;
|
||
+ break;
|
||
+
|
||
+ /* "12345-(xxx)" */
|
||
+ default:
|
||
+ switch (end) {
|
||
+ /* "12345-0" */
|
||
+ case -10:
|
||
+ return RANGE_ERR;
|
||
+
|
||
+ /* "12345-" */
|
||
+ case -1:
|
||
+ if (length <= (size_t) begin) {
|
||
+ return RANGE_ERR;
|
||
+ }
|
||
+ end = length - 1;
|
||
+ break;
|
||
+
|
||
+ /* "12345-67890" */
|
||
+ default:
|
||
+ if ( (length <= (size_t) begin) ||
|
||
+ (length <= (size_t) end) ||
|
||
+ (end < begin)) {
|
||
+ return RANGE_ERR;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ {
|
||
+ zval *zentry;
|
||
+ MAKE_STD_ZVAL(zentry);
|
||
+ array_init(zentry);
|
||
+ add_index_long(zentry, 0, begin);
|
||
+ add_index_long(zentry, 1, end);
|
||
+ zend_hash_next_index_insert(ranges, &zentry, sizeof(zval *), NULL);
|
||
+
|
||
+ begin = -1;
|
||
+ end = -1;
|
||
+ ptr = &begin;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ return RANGE_NO;
|
||
+ }
|
||
+ } while (c != 0);
|
||
+
|
||
+ return RANGE_OK;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_parse_headers(char *, HashTable *, zend_bool) */
|
||
+PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *headers, zend_bool prettify,
|
||
+ http_info_callback callback_func, void **callback_data TSRMLS_DC)
|
||
+{
|
||
+ const char *colon = NULL, *line = NULL;
|
||
+ zval array;
|
||
+
|
||
+ INIT_ZARR(array, headers);
|
||
+
|
||
+ /* skip leading ws */
|
||
+ while (HTTP_IS_CTYPE(space, *header)) ++header;
|
||
+ line = header;
|
||
+
|
||
+#define MORE_HEADERS (*(line-1) && !(*(line-1) == '\n' && (*line == '\n' || *line == '\r')))
|
||
+ do {
|
||
+ int value_len = 0;
|
||
+
|
||
+ switch (*line++) {
|
||
+ case ':':
|
||
+ if (!colon) {
|
||
+ colon = line - 1;
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case 0:
|
||
+ --value_len; /* we don't have CR so value length is one char less */
|
||
+ case '\n':
|
||
+ if ((!*(line - 1)) || ((*line != ' ') && (*line != '\t'))) {
|
||
+ http_info i;
|
||
+
|
||
+ if (SUCCESS == http_info_parse(header, &i)) {
|
||
+ /* response/request line */
|
||
+ callback_func(callback_data, &headers, &i TSRMLS_CC);
|
||
+ http_info_dtor(&i);
|
||
+ Z_ARRVAL(array) = headers;
|
||
+ } else if (colon) {
|
||
+ /* "header: value" pair */
|
||
+ if (header != colon) {
|
||
+ int keylen = colon - header;
|
||
+ const char *key = header;
|
||
+
|
||
+ /* skip leading ws */
|
||
+ while (keylen && HTTP_IS_CTYPE(space, *key)) --keylen, ++key;
|
||
+ /* skip trailing ws */
|
||
+ while (keylen && HTTP_IS_CTYPE(space, key[keylen - 1])) --keylen;
|
||
+
|
||
+ if (keylen > 0) {
|
||
+ zval **previous = NULL;
|
||
+ char *value;
|
||
+ char *keydup = estrndup(key, keylen);
|
||
+
|
||
+ if (prettify) {
|
||
+ keydup = pretty_key(keydup, keylen, 1, 1);
|
||
+ }
|
||
+
|
||
+ value_len += line - colon - 1;
|
||
+
|
||
+ /* skip leading ws */
|
||
+ while (HTTP_IS_CTYPE(space, *(++colon))) --value_len;
|
||
+ /* skip trailing ws */
|
||
+ while (HTTP_IS_CTYPE(space, colon[value_len - 1])) --value_len;
|
||
+
|
||
+ if (value_len > 0) {
|
||
+ value = estrndup(colon, value_len);
|
||
+ } else {
|
||
+ value = estrdup("");
|
||
+ value_len = 0;
|
||
+ }
|
||
+
|
||
+ /* if we already have got such a header make an array of those */
|
||
+ if (SUCCESS == zend_hash_find(headers, keydup, keylen + 1, (void *) &previous)) {
|
||
+ /* convert to array */
|
||
+ if (Z_TYPE_PP(previous) != IS_ARRAY) {
|
||
+ convert_to_array(*previous);
|
||
+ }
|
||
+ add_next_index_stringl(*previous, value, value_len, 0);
|
||
+ } else {
|
||
+ add_assoc_stringl(&array, keydup, value, value_len, 0);
|
||
+ }
|
||
+ efree(keydup);
|
||
+ } else {
|
||
+ /* empty key (" : ...") */
|
||
+ return FAILURE;
|
||
+ }
|
||
+ } else {
|
||
+ /* empty key (": ...") */
|
||
+ return FAILURE;
|
||
+ }
|
||
+ } else if (MORE_HEADERS) {
|
||
+ /* a line without a colon */
|
||
+ return FAILURE;
|
||
+ }
|
||
+ colon = NULL;
|
||
+ value_len = 0;
|
||
+ header += line - header;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ } while (MORE_HEADERS);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_get_request_headers(HashTable *) */
|
||
+PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC)
|
||
+{
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **hsv, **header;
|
||
+ HashPosition pos;
|
||
+
|
||
+ if (!HTTP_G->request.headers) {
|
||
+ ALLOC_HASHTABLE(HTTP_G->request.headers);
|
||
+ zend_hash_init(HTTP_G->request.headers, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
|
||
+#endif
|
||
+
|
||
+ if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) {
|
||
+ FOREACH_KEY(pos, *hsv, key) {
|
||
+ if (key.type == HASH_KEY_IS_STRING && key.len > 6 && !strncmp(key.str, "HTTP_", 5)) {
|
||
+ key.len -= 5;
|
||
+ key.str = pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1);
|
||
+
|
||
+ zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
|
||
+ ZVAL_ADDREF(*header);
|
||
+ zend_hash_add(HTTP_G->request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
|
||
+
|
||
+ efree(key.str);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (headers) {
|
||
+ zend_hash_copy(headers, HTTP_G->request.headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_get_response_headers(HashTable *) */
|
||
+PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC)
|
||
+{
|
||
+ STATUS status;
|
||
+ phpstr headers;
|
||
+
|
||
+ phpstr_init(&headers);
|
||
+ zend_llist_apply_with_argument(&SG(sapi_headers).headers, http_grab_response_headers, &headers TSRMLS_CC);
|
||
+ phpstr_fix(&headers);
|
||
+
|
||
+ status = http_parse_headers_ex(PHPSTR_VAL(&headers), headers_ht, 1);
|
||
+ phpstr_dtor(&headers);
|
||
+
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ zend_bool http_match_request_header(char *, char *) */
|
||
+PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC)
|
||
+{
|
||
+ char *name;
|
||
+ uint name_len = strlen(header);
|
||
+ zend_bool result = 0;
|
||
+ zval **data, *zvalue;
|
||
+
|
||
+ http_get_request_headers(NULL);
|
||
+ name = pretty_key(estrndup(header, name_len), name_len, 1, 1);
|
||
+ if (SUCCESS == zend_hash_find(HTTP_G->request.headers, name, name_len+1, (void *) &data)) {
|
||
+ zvalue = http_zsep(IS_STRING, *data);
|
||
+ result = (match_case ? strcmp(Z_STRVAL_P(zvalue), value) : strcasecmp(Z_STRVAL_P(zvalue), value)) ? 0 : 1;
|
||
+ zval_ptr_dtor(&zvalue);
|
||
+ }
|
||
+ efree(name);
|
||
+
|
||
+ return result;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_inflatestream_object.c
|
||
@@ -0,0 +1,292 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_inflatestream_object.c 300299 2010-06-09 06:23:16Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_ZLIB
|
||
+#include "php_http.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB)
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_inflatestream_object.h"
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpInflateStream, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpInflateStream, method, 0)
|
||
+#define HTTP_INFLATE_ME(method, visibility) PHP_ME(HttpInflateStream, method, HTTP_ARGS(HttpInflateStream, method), visibility)
|
||
+
|
||
+HTTP_BEGIN_ARGS(__construct, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(factory, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+ HTTP_ARG_VAL(class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(update, 1)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(flush, 0)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(finish, 0)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+#define THIS_CE http_inflatestream_object_ce
|
||
+zend_class_entry *http_inflatestream_object_ce;
|
||
+zend_function_entry http_inflatestream_object_fe[] = {
|
||
+ HTTP_INFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
|
||
+ HTTP_INFLATE_ME(update, ZEND_ACC_PUBLIC)
|
||
+ HTTP_INFLATE_ME(flush, ZEND_ACC_PUBLIC)
|
||
+ HTTP_INFLATE_ME(finish, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_INFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+static zend_object_handlers http_inflatestream_object_handlers;
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_inflatestream_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS_EX(HttpInflateStream, http_inflatestream_object, NULL, 0);
|
||
+ http_inflatestream_object_handlers.clone_obj = _http_inflatestream_object_clone_obj;
|
||
+
|
||
+#ifndef WONKY
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
|
||
+#endif
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ return http_inflatestream_object_new_ex(ce, NULL, NULL);
|
||
+}
|
||
+
|
||
+zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ http_inflatestream_object *o;
|
||
+
|
||
+ o = ecalloc(1, sizeof(http_inflatestream_object));
|
||
+ o->zo.ce = ce;
|
||
+
|
||
+ if (ptr) {
|
||
+ *ptr = o;
|
||
+ }
|
||
+
|
||
+ if (s) {
|
||
+ o->stream = s;
|
||
+ }
|
||
+
|
||
+ ALLOC_HASHTABLE(OBJ_PROP(o));
|
||
+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+
|
||
+ ov.handle = putObject(http_inflatestream_object, o);
|
||
+ ov.handlers = &http_inflatestream_object_handlers;
|
||
+
|
||
+ return ov;
|
||
+}
|
||
+
|
||
+zend_object_value _http_inflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
|
||
+{
|
||
+ http_encoding_stream *s;
|
||
+ zend_object_value new_ov;
|
||
+ http_inflatestream_object *new_obj = NULL;
|
||
+ getObject(http_inflatestream_object, old_obj);
|
||
+
|
||
+ s = ecalloc(1, sizeof(http_encoding_stream));
|
||
+ s->flags = old_obj->stream->flags;
|
||
+ inflateCopy(&s->stream, &old_obj->stream->stream);
|
||
+ s->stream.opaque = phpstr_dup(s->stream.opaque);
|
||
+
|
||
+ new_ov = http_inflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
|
||
+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||
+
|
||
+ return new_ov;
|
||
+}
|
||
+
|
||
+void _http_inflatestream_object_free(zend_object *object TSRMLS_DC)
|
||
+{
|
||
+ http_inflatestream_object *o = (http_inflatestream_object *) object;
|
||
+
|
||
+ if (o->stream) {
|
||
+ http_encoding_inflate_stream_free(&o->stream);
|
||
+ }
|
||
+ freeObject(o);
|
||
+}
|
||
+
|
||
+/* {{{ proto void HttpInflateStream::__construct([int flags = 0])
|
||
+ Creates a new HttpInflateStream object instance. */
|
||
+PHP_METHOD(HttpInflateStream, __construct)
|
||
+{
|
||
+ long flags = 0;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
|
||
+ getObject(http_inflatestream_object, obj);
|
||
+
|
||
+ if (!obj->stream) {
|
||
+ obj->stream = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
|
||
+ } else {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpInflateStream cannot be initialized twice");
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpInflateStream HttpInflateStream::factory([int flags[, string class = "HttpInflateStream"]])
|
||
+ Creates a new HttpInflateStream object instance. */
|
||
+PHP_METHOD(HttpInflateStream, factory)
|
||
+{
|
||
+ long flags = 0;
|
||
+ char *cn = NULL;
|
||
+ int cl = 0;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
|
||
+ zend_object_value ov;
|
||
+ http_encoding_stream *s = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
|
||
+
|
||
+ if (SUCCESS == http_object_new(&ov, cn, cl, _http_inflatestream_object_new_ex, http_inflatestream_object_ce, s, NULL)) {
|
||
+ RETVAL_OBJVAL(ov, 0);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpInflateStream::update(string data)
|
||
+ Passes more data through the inflate stream. */
|
||
+PHP_METHOD(HttpInflateStream, update)
|
||
+{
|
||
+ int data_len;
|
||
+ size_t decoded_len = 0;
|
||
+ char *data, *decoded = NULL;
|
||
+ getObject(http_inflatestream_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!data_len) {
|
||
+ RETURN_STRING("", 1);
|
||
+ }
|
||
+
|
||
+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
|
||
+ RETURN_STRINGL(decoded, decoded_len, 0);
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpInflateStream::flush([string data])
|
||
+ Flush the inflate stream. */
|
||
+PHP_METHOD(HttpInflateStream, flush)
|
||
+{
|
||
+ int data_len = 0;
|
||
+ size_t decoded_len = 0;
|
||
+ char *decoded = NULL, *data = NULL;
|
||
+ getObject(http_inflatestream_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ /* flushing the inflate stream is a no-op */
|
||
+ if (!data_len) {
|
||
+ RETURN_STRINGL("", 0, 1);
|
||
+ } else if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
|
||
+ RETURN_STRINGL(decoded, decoded_len, 0);
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpInflateStream::finish([string data])
|
||
+ Finalizes the inflate stream. The inflate stream can be reused after finalizing. */
|
||
+PHP_METHOD(HttpInflateStream, finish)
|
||
+{
|
||
+ int data_len = 0;
|
||
+ size_t updated_len = 0, decoded_len = 0;
|
||
+ char *updated = NULL, *decoded = NULL, *data = NULL;
|
||
+ getObject(http_inflatestream_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (data_len) {
|
||
+ if (SUCCESS != http_encoding_inflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (SUCCESS == http_encoding_inflate_stream_finish(obj->stream, &decoded, &decoded_len)) {
|
||
+ if (updated_len) {
|
||
+ updated = erealloc(updated, updated_len + decoded_len + 1);
|
||
+ updated[updated_len + decoded_len] = '\0';
|
||
+ memcpy(updated + updated_len, decoded, decoded_len);
|
||
+ STR_FREE(decoded);
|
||
+ updated_len += decoded_len;
|
||
+ RETVAL_STRINGL(updated, updated_len, 0);
|
||
+ } else if (decoded) {
|
||
+ STR_FREE(updated);
|
||
+ RETVAL_STRINGL(decoded, decoded_len, 0);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+ } else {
|
||
+ STR_FREE(updated);
|
||
+ RETVAL_FALSE;
|
||
+ }
|
||
+
|
||
+ http_encoding_inflate_stream_dtor(obj->stream);
|
||
+ http_encoding_inflate_stream_init(obj->stream, obj->stream->flags);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_info_api.c
|
||
@@ -0,0 +1,155 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_info_api.c 304921 2010-10-26 15:27:36Z iliaa $ */
|
||
+
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_info_api.h"
|
||
+
|
||
+PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC)
|
||
+{
|
||
+ zval array;
|
||
+
|
||
+ INIT_ZARR(array, *headers);
|
||
+
|
||
+ switch (info->type) {
|
||
+ case IS_HTTP_REQUEST:
|
||
+ add_assoc_string(&array, "Request Method", HTTP_INFO(info).request.method, 1);
|
||
+ add_assoc_string(&array, "Request Url", HTTP_INFO(info).request.url, 1);
|
||
+ break;
|
||
+
|
||
+ case IS_HTTP_RESPONSE:
|
||
+ add_assoc_long(&array, "Response Code", (long) HTTP_INFO(info).response.code);
|
||
+ if (HTTP_INFO(info).response.status) {
|
||
+ add_assoc_string(&array, "Response Status", HTTP_INFO(info).response.status, 1);
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_info_dtor(http_info *i)
|
||
+{
|
||
+ switch (i->type) {
|
||
+ case IS_HTTP_REQUEST:
|
||
+ STR_SET(HTTP_INFO(i).request.method, NULL);
|
||
+ STR_SET(HTTP_INFO(i).request.url, NULL);
|
||
+ break;
|
||
+
|
||
+ case IS_HTTP_RESPONSE:
|
||
+ STR_SET(HTTP_INFO(i).response.status, NULL);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info, zend_bool silent TSRMLS_DC)
|
||
+{
|
||
+ const char *end, *http;
|
||
+
|
||
+ /* sane parameter */
|
||
+ if ((!pre_header) || (!*pre_header)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ /* where's the end of the line */
|
||
+ if (!(end = http_locate_eol(pre_header, NULL))) {
|
||
+ end = pre_header + strlen(pre_header);
|
||
+ }
|
||
+
|
||
+ /* there must be HTTP/1.x in the line */
|
||
+ if (!(http = http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ /* and nothing than SPACE or NUL after HTTP/1.x */
|
||
+ if ( (!HTTP_IS_CTYPE(digit, http[lenof("HTTP/1.")])) ||
|
||
+ (http[lenof("HTTP/1.1")] && (!HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) {
|
||
+ if (!silent) {
|
||
+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid HTTP/1.x protocol identification");
|
||
+ }
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+#if 0
|
||
+ {
|
||
+ char *line = estrndup(pre_header, end - pre_header);
|
||
+ fprintf(stderr, "http_parse_info('%s')\n", line);
|
||
+ efree(line);
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ info->http.version = zend_strtod(http + lenof("HTTP/"), NULL);
|
||
+
|
||
+ /* is response */
|
||
+ if (pre_header == http) {
|
||
+ char *status = NULL;
|
||
+ const char *code = http + sizeof("HTTP/1.1");
|
||
+
|
||
+ info->type = IS_HTTP_RESPONSE;
|
||
+ while (' ' == *code) ++code;
|
||
+ if (code && end > code) {
|
||
+ HTTP_INFO(info).response.code = strtol(code, &status, 10);
|
||
+ } else {
|
||
+ HTTP_INFO(info).response.code = 0;
|
||
+ }
|
||
+ if (status && end > status) {
|
||
+ while (' ' == *status) ++status;
|
||
+ HTTP_INFO(info).response.status = estrndup(status, end - status);
|
||
+ } else {
|
||
+ HTTP_INFO(info).response.status = NULL;
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ /* is request */
|
||
+ else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') {
|
||
+ const char *url = strchr(pre_header, ' ');
|
||
+
|
||
+ info->type = IS_HTTP_REQUEST;
|
||
+ if (url && http > url) {
|
||
+ HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header);
|
||
+ while (' ' == *url) ++url;
|
||
+ while (' ' == *(http-1)) --http;
|
||
+ if (http > url) {
|
||
+ HTTP_INFO(info).request.url = estrndup(url, http - url);
|
||
+ } else {
|
||
+ efree(HTTP_INFO(info).request.method);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ } else {
|
||
+ HTTP_INFO(info).request.method = NULL;
|
||
+ HTTP_INFO(info).request.url = NULL;
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ /* some darn header containing HTTP/1.x */
|
||
+ else {
|
||
+ return FAILURE;
|
||
+ }
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_message_api.c
|
||
@@ -0,0 +1,735 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_message_api.c 298689 2010-04-28 06:50:06Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_CURL
|
||
+#define HTTP_WANT_ZLIB
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_headers_api.h"
|
||
+#include "php_http_message_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+
|
||
+#define http_message_info_callback _http_message_info_callback
|
||
+static void _http_message_info_callback(http_message **message, HashTable **headers, http_info *info TSRMLS_DC)
|
||
+{
|
||
+ http_message *old = *message;
|
||
+
|
||
+ /* advance message */
|
||
+ if (old->type || zend_hash_num_elements(&old->hdrs) || PHPSTR_LEN(old)) {
|
||
+ (*message) = http_message_new();
|
||
+ (*message)->parent = old;
|
||
+ (*headers) = &((*message)->hdrs);
|
||
+ }
|
||
+
|
||
+ http_message_set_info(*message, info);
|
||
+}
|
||
+
|
||
+#define http_message_init_type _http_message_init_type
|
||
+static inline void _http_message_init_type(http_message *message, http_message_type type)
|
||
+{
|
||
+ message->http.version = .0;
|
||
+
|
||
+ switch (message->type = type) {
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ message->http.info.response.code = 0;
|
||
+ message->http.info.response.status = NULL;
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ message->http.info.request.method = NULL;
|
||
+ message->http.info.request.url = NULL;
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_NONE:
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API http_message *_http_message_init_ex(http_message *message, http_message_type type ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||
+{
|
||
+ if (!message) {
|
||
+ message = ecalloc_rel(1, sizeof(http_message));
|
||
+ }
|
||
+
|
||
+ http_message_init_type(message, type);
|
||
+ message->parent = NULL;
|
||
+ phpstr_init(&message->body);
|
||
+ zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+
|
||
+ return message;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API http_message *_http_message_init_env(http_message *message, http_message_type type TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||
+{
|
||
+ int free_msg;
|
||
+ http_info inf;
|
||
+ zval *sval, tval;
|
||
+ char *body_str;
|
||
+ size_t body_len;
|
||
+
|
||
+ if ((free_msg = !message)) {
|
||
+ message = http_message_init_rel(NULL, HTTP_MSG_NONE);
|
||
+ }
|
||
+
|
||
+ memset(&inf, 0, sizeof(http_info));
|
||
+ switch (inf.type = type) {
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ if ((sval = http_get_server_var("SERVER_PROTOCOL", 1)) && !strncmp(Z_STRVAL_P(sval), "HTTP/", lenof("HTTP/"))) {
|
||
+ inf.http.version = zend_strtod(Z_STRVAL_P(sval) + lenof("HTTP/"), NULL);
|
||
+ } else {
|
||
+ inf.http.version = 1.1;
|
||
+ }
|
||
+ if ((sval = http_get_server_var("REQUEST_METHOD", 1))) {
|
||
+ inf.http.info.request.method = estrdup(Z_STRVAL_P(sval));
|
||
+ }
|
||
+ if ((sval = http_get_server_var("REQUEST_URI", 1))) {
|
||
+ inf.http.info.request.url = estrdup(Z_STRVAL_P(sval));
|
||
+ }
|
||
+
|
||
+ http_message_set_info(message, &inf);
|
||
+ http_get_request_headers(&message->hdrs);
|
||
+ if (SUCCESS == http_get_request_body_ex(&body_str, &body_len, 0)) {
|
||
+ phpstr_from_string_ex(&message->body, body_str, body_len);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ if (!SG(sapi_headers).http_status_line || SUCCESS != http_info_parse_ex(SG(sapi_headers).http_status_line, &inf, 0)) {
|
||
+ inf.http.version = 1.1;
|
||
+ inf.http.info.response.code = 200;
|
||
+ inf.http.info.response.status = estrdup("Ok");
|
||
+ }
|
||
+
|
||
+ http_message_set_info(message, &inf);
|
||
+ http_get_response_headers(&message->hdrs);
|
||
+ if (SUCCESS == php_ob_get_buffer(&tval TSRMLS_CC)) {
|
||
+ message->body.data = Z_STRVAL(tval);
|
||
+ message->body.used = Z_STRLEN(tval);
|
||
+ message->body.free = 1; /* "\0" */
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ if (free_msg) {
|
||
+ http_message_free(&message);
|
||
+ } else {
|
||
+ message = NULL;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ http_info_dtor(&inf);
|
||
+
|
||
+ return message;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_message_set_type(http_message *message, http_message_type type)
|
||
+{
|
||
+ /* just act if different */
|
||
+ if (type != message->type) {
|
||
+
|
||
+ /* free request info */
|
||
+ switch (message->type) {
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ STR_FREE(message->http.info.request.method);
|
||
+ STR_FREE(message->http.info.request.url);
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ STR_FREE(message->http.info.response.status);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* init */
|
||
+ http_message_init_type(message, type);
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info)
|
||
+{
|
||
+ http_message_set_type(message, info->type);
|
||
+ message->http.version = info->http.version;
|
||
+ switch (message->type) {
|
||
+ case IS_HTTP_REQUEST:
|
||
+ STR_SET(HTTP_INFO(message).request.url, HTTP_INFO(info).request.url ? estrdup(HTTP_INFO(info).request.url) : NULL);
|
||
+ STR_SET(HTTP_INFO(message).request.method, HTTP_INFO(info).request.method ? estrdup(HTTP_INFO(info).request.method) : NULL);
|
||
+ break;
|
||
+
|
||
+ case IS_HTTP_RESPONSE:
|
||
+ HTTP_INFO(message).response.code = HTTP_INFO(info).response.code;
|
||
+ STR_SET(HTTP_INFO(message).response.status, HTTP_INFO(info).response.status ? estrdup(HTTP_INFO(info).response.status) : NULL);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+#define http_message_body_parse(m, ms, ml, c) _http_message_body_parse((m), (ms), (ml), (c) TSRMLS_CC)
|
||
+static inline void _http_message_body_parse(http_message *msg, const char *message, size_t message_length, const char **continue_at TSRMLS_DC)
|
||
+{
|
||
+ zval *c;
|
||
+ size_t remaining;
|
||
+ const char *body;
|
||
+
|
||
+ *continue_at = NULL;
|
||
+ if ((body = http_locate_body(message))) {
|
||
+ remaining = message + message_length - body;
|
||
+
|
||
+ if ((c = http_message_header(msg, "Transfer-Encoding"))) {
|
||
+ if (strstr(Z_STRVAL_P(c), "chunked")) {
|
||
+ /* message has chunked transfer encoding */
|
||
+ char *decoded;
|
||
+ size_t decoded_len;
|
||
+
|
||
+ /* decode and replace Transfer-Encoding with Content-Length header */
|
||
+ if ((*continue_at = http_encoding_dechunk(body, message + message_length - body, &decoded, &decoded_len))) {
|
||
+ zval *len;
|
||
+ char *tmp;
|
||
+ int tmp_len;
|
||
+
|
||
+ tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
|
||
+ MAKE_STD_ZVAL(len);
|
||
+ ZVAL_STRINGL(len, tmp, tmp_len, 0);
|
||
+
|
||
+ ZVAL_ADDREF(c);
|
||
+ zend_hash_update(&msg->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &c, sizeof(zval *), NULL);
|
||
+ zend_hash_del(&msg->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
|
||
+ zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length"));
|
||
+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
|
||
+
|
||
+ phpstr_from_string_ex(PHPSTR(msg), decoded, decoded_len);
|
||
+ efree(decoded);
|
||
+ }
|
||
+ }
|
||
+ zval_ptr_dtor(&c);
|
||
+ }
|
||
+
|
||
+ if (!*continue_at && (c = http_message_header(msg, "Content-Length"))) {
|
||
+ /* message has content-length header */
|
||
+ ulong len = strtoul(Z_STRVAL_P(c), NULL, 10);
|
||
+ if (len > remaining) {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_MALFORMED_HEADERS, "The Content-Length header pretends a larger body than actually received (expected %lu bytes; got %lu bytes)", len, remaining);
|
||
+ len = remaining;
|
||
+ }
|
||
+ phpstr_from_string_ex(PHPSTR(msg), body, len);
|
||
+ *continue_at = body + len;
|
||
+ zval_ptr_dtor(&c);
|
||
+ }
|
||
+
|
||
+ if (!*continue_at && (c = http_message_header(msg, "Content-Range"))) {
|
||
+ /* message has content-range header */
|
||
+ ulong total = 0, start = 0, end = 0, len = 0;
|
||
+
|
||
+ if (!strncasecmp(Z_STRVAL_P(c), "bytes", lenof("bytes")) &&
|
||
+ ( Z_STRVAL_P(c)[lenof("bytes")] == ':' ||
|
||
+ Z_STRVAL_P(c)[lenof("bytes")] == ' ' ||
|
||
+ Z_STRVAL_P(c)[lenof("bytes")] == '=')) {
|
||
+ char *total_at = NULL, *end_at = NULL;
|
||
+ char *start_at = Z_STRVAL_P(c) + sizeof("bytes");
|
||
+
|
||
+ start = strtoul(start_at, &end_at, 10);
|
||
+ if (end_at) {
|
||
+ end = strtoul(end_at + 1, &total_at, 10);
|
||
+ if (total_at && strncmp(total_at + 1, "*", 1)) {
|
||
+ total = strtoul(total_at + 1, NULL, 10);
|
||
+ }
|
||
+ if ((len = (end + 1 - start)) > remaining) {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_MALFORMED_HEADERS, "The Content-Range header pretends a larger body than actually received (expected %lu bytes; got %lu bytes)", len, remaining);
|
||
+ len = remaining;
|
||
+ }
|
||
+ if (end >= start && (!total || end < total)) {
|
||
+ phpstr_from_string_ex(PHPSTR(msg), body, len);
|
||
+ *continue_at = body + len;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!*continue_at) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid Content-Range header: %s", Z_STRVAL_P(c));
|
||
+ }
|
||
+ zval_ptr_dtor(&c);
|
||
+ }
|
||
+
|
||
+ if (!*continue_at) {
|
||
+ /* no headers that indicate content length */
|
||
+ if (HTTP_MSG_TYPE(RESPONSE, msg)) {
|
||
+ phpstr_from_string_ex(PHPSTR(msg), body, remaining);
|
||
+ } else {
|
||
+ *continue_at = body;
|
||
+ }
|
||
+ }
|
||
+
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ /* check for compressed data */
|
||
+ if ((c = http_message_header(msg, "Content-Encoding"))) {
|
||
+ char *decoded = NULL;
|
||
+ size_t decoded_len = 0;
|
||
+
|
||
+ if ( !strcasecmp(Z_STRVAL_P(c), "gzip") ||
|
||
+ !strcasecmp(Z_STRVAL_P(c), "x-gzip") ||
|
||
+ !strcasecmp(Z_STRVAL_P(c), "deflate")) {
|
||
+ http_encoding_inflate(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len);
|
||
+ }
|
||
+
|
||
+ if (decoded) {
|
||
+ zval *len, **original_len;
|
||
+ char *tmp;
|
||
+ int tmp_len;
|
||
+
|
||
+ tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
|
||
+ MAKE_STD_ZVAL(len);
|
||
+ ZVAL_STRINGL(len, tmp, tmp_len, 0);
|
||
+
|
||
+ ZVAL_ADDREF(c);
|
||
+ zend_hash_update(&msg->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), (void *) &c, sizeof(zval *), NULL);
|
||
+ zend_hash_del(&msg->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
|
||
+ if (SUCCESS == zend_hash_find(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &original_len)) {
|
||
+ ZVAL_ADDREF(*original_len);
|
||
+ zend_hash_update(&msg->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) original_len, sizeof(zval *), NULL);
|
||
+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
|
||
+ } else {
|
||
+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
|
||
+ }
|
||
+
|
||
+ phpstr_dtor(PHPSTR(msg));
|
||
+ PHPSTR(msg)->data = decoded;
|
||
+ PHPSTR(msg)->used = decoded_len;
|
||
+ PHPSTR(msg)->free = 1;
|
||
+ }
|
||
+
|
||
+ zval_ptr_dtor(&c);
|
||
+ }
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t message_length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ const char *continue_at;
|
||
+ zend_bool free_msg = msg ? 0 : 1;
|
||
+
|
||
+ if ((!message) || (message_length < HTTP_MSG_MIN_SIZE)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Empty or too short HTTP message: '%s'", message);
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ msg = http_message_init_rel(msg, 0);
|
||
+
|
||
+ if (SUCCESS != http_parse_headers_cb(message, &msg->hdrs, 1, (http_info_callback) http_message_info_callback, (void *) &msg)) {
|
||
+ if (free_msg) {
|
||
+ http_message_free(&msg);
|
||
+ }
|
||
+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse message headers");
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ http_message_body_parse(msg, message, message_length, &continue_at);
|
||
+
|
||
+ /* check for following messages */
|
||
+ if (continue_at && (continue_at < (message + message_length))) {
|
||
+ while (HTTP_IS_CTYPE(space, *continue_at)) ++continue_at;
|
||
+ if (continue_at < (message + message_length)) {
|
||
+ http_message *next = NULL, *most = NULL;
|
||
+
|
||
+ /* set current message to parent of most parent following messages and return deepest */
|
||
+ if ((most = next = http_message_parse_rel(NULL, continue_at, message + message_length - continue_at))) {
|
||
+ while (most->parent) most = most->parent;
|
||
+ most->parent = msg;
|
||
+ msg = next;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return msg;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length)
|
||
+{
|
||
+ phpstr str;
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **header;
|
||
+ char *data;
|
||
+ HashPosition pos1;
|
||
+
|
||
+ phpstr_init_ex(&str, 4096, 0);
|
||
+
|
||
+ switch (msg->type) {
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ phpstr_appendf(&str, HTTP_INFO_REQUEST_FMT_ARGS(&msg->http, HTTP_CRLF));
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ phpstr_appendf(&str, HTTP_INFO_RESPONSE_FMT_ARGS(&msg->http, HTTP_CRLF));
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_NONE:
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos1, &msg->hdrs, key, header) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ HashPosition pos2;
|
||
+ zval **single_header;
|
||
+
|
||
+ switch (Z_TYPE_PP(header)) {
|
||
+ case IS_BOOL:
|
||
+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(header)?"true":"false");
|
||
+ break;
|
||
+
|
||
+ case IS_LONG:
|
||
+ phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(header));
|
||
+ break;
|
||
+
|
||
+ case IS_DOUBLE:
|
||
+ phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(header));
|
||
+ break;
|
||
+
|
||
+ case IS_STRING:
|
||
+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(header));
|
||
+ break;
|
||
+
|
||
+ case IS_ARRAY:
|
||
+ FOREACH_VAL(pos2, *header, single_header) {
|
||
+ switch (Z_TYPE_PP(single_header)) {
|
||
+ case IS_BOOL:
|
||
+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(single_header)?"true":"false");
|
||
+ break;
|
||
+
|
||
+ case IS_LONG:
|
||
+ phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(single_header));
|
||
+ break;
|
||
+
|
||
+ case IS_DOUBLE:
|
||
+ phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(single_header));
|
||
+ break;
|
||
+
|
||
+ case IS_STRING:
|
||
+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(single_header));
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (PHPSTR_LEN(msg)) {
|
||
+ phpstr_appends(&str, HTTP_CRLF);
|
||
+ phpstr_append(&str, PHPSTR_VAL(msg), PHPSTR_LEN(msg));
|
||
+ phpstr_appends(&str, HTTP_CRLF);
|
||
+ }
|
||
+
|
||
+ data = phpstr_data(&str, string, length);
|
||
+ if (!string) {
|
||
+ efree(data);
|
||
+ }
|
||
+
|
||
+ phpstr_dtor(&str);
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length)
|
||
+{
|
||
+ char *buf;
|
||
+ size_t len;
|
||
+ phpstr str;
|
||
+
|
||
+ phpstr_init(&str);
|
||
+
|
||
+ do {
|
||
+ http_message_tostring(message, &buf, &len);
|
||
+ phpstr_prepend(&str, buf, len);
|
||
+ efree(buf);
|
||
+ } while ((message = message->parent));
|
||
+
|
||
+ buf = phpstr_data(&str, string, length);
|
||
+ if (!string) {
|
||
+ efree(buf);
|
||
+ }
|
||
+
|
||
+ phpstr_dtor(&str);
|
||
+}
|
||
+
|
||
+PHP_HTTP_API http_message *_http_message_reverse(http_message *msg)
|
||
+{
|
||
+ int i, c;
|
||
+
|
||
+ http_message_count(c, msg);
|
||
+
|
||
+ if (c > 1) {
|
||
+ http_message *tmp = msg, **arr = ecalloc(c, sizeof(http_message *));
|
||
+
|
||
+ for (i = 0; i < c; ++i) {
|
||
+ arr[i] = tmp;
|
||
+ tmp = tmp->parent;
|
||
+ }
|
||
+ arr[0]->parent = NULL;
|
||
+ for (i = 0; i < c-1; ++i) {
|
||
+ arr[i+1]->parent = arr[i];
|
||
+ }
|
||
+
|
||
+ msg = arr[c-1];
|
||
+ efree(arr);
|
||
+ }
|
||
+
|
||
+ return msg;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2)
|
||
+{
|
||
+ if (m1 && m2) {
|
||
+ int i = 0, c1, c2;
|
||
+ http_message *t1 = m1, *t2 = m2, *p1, *p2;
|
||
+
|
||
+ http_message_count(c1, m1);
|
||
+ http_message_count(c2, m2);
|
||
+
|
||
+ while (i++ < (c1 - c2)) {
|
||
+ t1 = t1->parent;
|
||
+ }
|
||
+ while (i++ <= c1) {
|
||
+ p1 = t1->parent;
|
||
+ p2 = t2->parent;
|
||
+ t1->parent = t2;
|
||
+ t2->parent = p1;
|
||
+ t1 = p1;
|
||
+ t2 = p2;
|
||
+ }
|
||
+ } else if (!m1 && m2) {
|
||
+ m1 = m2;
|
||
+ }
|
||
+ return m1;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *obj TSRMLS_DC)
|
||
+{
|
||
+ zval strct;
|
||
+ zval *headers;
|
||
+
|
||
+ INIT_ZARR(strct, HASH_OF(obj));
|
||
+
|
||
+ add_assoc_long(&strct, "type", msg->type);
|
||
+ add_assoc_double(&strct, "httpVersion", msg->http.version);
|
||
+ switch (msg->type)
|
||
+ {
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ add_assoc_long(&strct, "responseCode", msg->http.info.response.code);
|
||
+ add_assoc_string(&strct, "responseStatus", STR_PTR(msg->http.info.response.status), 1);
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ add_assoc_string(&strct, "requestMethod", STR_PTR(msg->http.info.request.method), 1);
|
||
+ add_assoc_string(&strct, "requestUrl", STR_PTR(msg->http.info.request.url), 1);
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_NONE:
|
||
+ /* avoid compiler warning */
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(headers);
|
||
+ array_init(headers);
|
||
+ zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ add_assoc_zval(&strct, "headers", headers);
|
||
+
|
||
+ add_assoc_stringl(&strct, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg), 1);
|
||
+
|
||
+ if (msg->parent) {
|
||
+ zval *parent;
|
||
+
|
||
+ MAKE_STD_ZVAL(parent);
|
||
+ if (Z_TYPE_P(obj) == IS_ARRAY) {
|
||
+ array_init(parent);
|
||
+ } else {
|
||
+ object_init(parent);
|
||
+ }
|
||
+ add_assoc_zval(&strct, "parentMessage", parent);
|
||
+ http_message_tostruct_recursive(msg->parent, parent);
|
||
+ } else {
|
||
+ add_assoc_null(&strct, "parentMessage");
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC)
|
||
+{
|
||
+ STATUS rs = FAILURE;
|
||
+
|
||
+ switch (message->type) {
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ {
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **val;
|
||
+ HashPosition pos;
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos, &message->hdrs, key, val) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ http_send_header_zval_ex(key.str, key.len-1, val, 1);
|
||
+ }
|
||
+ }
|
||
+ rs = SUCCESS == http_send_status(message->http.info.response.code) &&
|
||
+ SUCCESS == http_send_data(PHPSTR_VAL(message), PHPSTR_LEN(message)) ?
|
||
+ SUCCESS : FAILURE;
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ {
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+ char *uri = NULL;
|
||
+ http_request request;
|
||
+ zval **zhost, *options, *headers;
|
||
+
|
||
+ MAKE_STD_ZVAL(options);
|
||
+ MAKE_STD_ZVAL(headers);
|
||
+ array_init(options);
|
||
+ array_init(headers);
|
||
+ zend_hash_copy(Z_ARRVAL_P(headers), &message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ add_assoc_zval(options, "headers", headers);
|
||
+
|
||
+ /* check host header */
|
||
+ if (SUCCESS == zend_hash_find(&message->hdrs, "Host", sizeof("Host"), (void *) &zhost) && Z_TYPE_PP(zhost) == IS_STRING) {
|
||
+ char *colon = NULL;
|
||
+ php_url parts, *url = php_url_parse(message->http.info.request.url);
|
||
+
|
||
+ memset(&parts, 0, sizeof(php_url));
|
||
+
|
||
+ /* check for port */
|
||
+ if ((colon = strchr(Z_STRVAL_PP(zhost), ':'))) {
|
||
+ parts.port = atoi(colon + 1);
|
||
+ parts.host = estrndup(Z_STRVAL_PP(zhost), (Z_STRVAL_PP(zhost) - colon - 1));
|
||
+ } else {
|
||
+ parts.host = estrndup(Z_STRVAL_PP(zhost), Z_STRLEN_PP(zhost));
|
||
+ }
|
||
+
|
||
+ http_build_url(HTTP_URL_REPLACE, url, &parts, NULL, &uri, NULL);
|
||
+ php_url_free(url);
|
||
+ efree(parts.host);
|
||
+ } else {
|
||
+ uri = http_absolute_url(message->http.info.request.url);
|
||
+ }
|
||
+
|
||
+ if ((request.meth = http_request_method_exists(1, 0, message->http.info.request.method))) {
|
||
+ http_request_body body;
|
||
+
|
||
+ http_request_init_ex(&request, NULL, request.meth, uri);
|
||
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, PHPSTR_VAL(message), PHPSTR_LEN(message), 0);
|
||
+ if (SUCCESS == (rs = http_request_prepare(&request, Z_ARRVAL_P(options)))) {
|
||
+ http_request_exec(&request);
|
||
+ }
|
||
+ http_request_dtor(&request);
|
||
+ } else {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD,
|
||
+ "Cannot send HttpMessage. Request method %s not supported",
|
||
+ message->http.info.request.method);
|
||
+ }
|
||
+ efree(uri);
|
||
+ zval_ptr_dtor(&options);
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "HTTP requests not supported - ext/http was not linked against libcurl.");
|
||
+#endif
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case HTTP_MSG_NONE:
|
||
+ default:
|
||
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HTTP_MSG_REQUEST nor HTTP_MSG_RESPONSE");
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ return rs;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API http_message *_http_message_dup(http_message *orig TSRMLS_DC)
|
||
+{
|
||
+ http_message *temp, *copy = NULL;
|
||
+ http_info info;
|
||
+
|
||
+ if (orig) {
|
||
+ info.type = orig->type;
|
||
+ info.http = orig->http;
|
||
+
|
||
+ copy = temp = http_message_new();
|
||
+ http_message_set_info(temp, &info);
|
||
+ zend_hash_copy(&temp->hdrs, &orig->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ phpstr_append(&temp->body, orig->body.data, orig->body.used);
|
||
+
|
||
+ while (orig->parent) {
|
||
+ info.type = orig->parent->type;
|
||
+ info.http = orig->parent->http;
|
||
+
|
||
+ temp->parent = http_message_new();
|
||
+ http_message_set_info(temp->parent, &info);
|
||
+ zend_hash_copy(&temp->parent->hdrs, &orig->parent->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ phpstr_append(&temp->parent->body, orig->parent->body.data, orig->parent->body.used);
|
||
+
|
||
+ temp = temp->parent;
|
||
+ orig = orig->parent;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return copy;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_message_dtor(http_message *message)
|
||
+{
|
||
+ if (message) {
|
||
+ zend_hash_destroy(&message->hdrs);
|
||
+ phpstr_dtor(PHPSTR(message));
|
||
+
|
||
+ switch (message->type) {
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ STR_SET(message->http.info.request.method, NULL);
|
||
+ STR_SET(message->http.info.request.url, NULL);
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ STR_SET(message->http.info.response.status, NULL);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_message_free(http_message **message)
|
||
+{
|
||
+ if (*message) {
|
||
+ if ((*message)->parent) {
|
||
+ http_message_free(&(*message)->parent);
|
||
+ }
|
||
+ http_message_dtor(*message);
|
||
+ efree(*message);
|
||
+ *message = NULL;
|
||
+ }
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_message_object.c
|
||
@@ -0,0 +1,1546 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_message_object.c 309640 2011-03-24 09:26:11Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_CURL
|
||
+#define HTTP_WANT_MAGIC
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#include "zend_interfaces.h"
|
||
+#include "ext/standard/url.h"
|
||
+#include "php_variables.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+#include "php_http_message_api.h"
|
||
+#include "php_http_message_object.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_response_object.h"
|
||
+#include "php_http_request_method_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_object.h"
|
||
+#include "php_http_headers_api.h"
|
||
+
|
||
+#if defined(HTTP_HAVE_SPL) && !defined(WONKY)
|
||
+/* SPL doesn't install its headers */
|
||
+extern PHPAPI zend_class_entry *spl_ce_Countable;
|
||
+#endif
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpMessage, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpMessage, method, 0)
|
||
+#define HTTP_MESSAGE_ME(method, visibility) PHP_ME(HttpMessage, method, HTTP_ARGS(HttpMessage, method), visibility)
|
||
+
|
||
+HTTP_BEGIN_ARGS(__construct, 0)
|
||
+ HTTP_ARG_VAL(message, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(factory, 0)
|
||
+ HTTP_ARG_VAL(message, 0)
|
||
+ HTTP_ARG_VAL(class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(fromEnv, 1)
|
||
+ HTTP_ARG_VAL(type, 0)
|
||
+ HTTP_ARG_VAL(class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getBody);
|
||
+HTTP_BEGIN_ARGS(setBody, 1)
|
||
+ HTTP_ARG_VAL(body, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(getHeader, 1)
|
||
+ HTTP_ARG_VAL(header, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getHeaders);
|
||
+HTTP_BEGIN_ARGS(setHeaders, 1)
|
||
+ HTTP_ARG_VAL(headers, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addHeaders, 1)
|
||
+ HTTP_ARG_VAL(headers, 0)
|
||
+ HTTP_ARG_VAL(append, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getType);
|
||
+HTTP_BEGIN_ARGS(setType, 1)
|
||
+ HTTP_ARG_VAL(type, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getInfo);
|
||
+HTTP_BEGIN_ARGS(setInfo, 1)
|
||
+ HTTP_ARG_VAL(http_info, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getResponseCode);
|
||
+HTTP_BEGIN_ARGS(setResponseCode, 1)
|
||
+ HTTP_ARG_VAL(response_code, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getResponseStatus);
|
||
+HTTP_BEGIN_ARGS(setResponseStatus, 1)
|
||
+ HTTP_ARG_VAL(response_status, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getRequestMethod);
|
||
+HTTP_BEGIN_ARGS(setRequestMethod, 1)
|
||
+ HTTP_ARG_VAL(request_method, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getRequestUrl);
|
||
+HTTP_BEGIN_ARGS(setRequestUrl, 1)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getHttpVersion);
|
||
+HTTP_BEGIN_ARGS(setHttpVersion, 1)
|
||
+ HTTP_ARG_VAL(http_version, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(guessContentType, 1)
|
||
+ HTTP_ARG_VAL(magic_file, 0)
|
||
+ HTTP_ARG_VAL(magic_mode, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getParentMessage);
|
||
+HTTP_EMPTY_ARGS(send);
|
||
+HTTP_EMPTY_ARGS(__toString);
|
||
+HTTP_BEGIN_ARGS(toString, 0)
|
||
+ HTTP_ARG_VAL(include_parent, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(toMessageTypeObject);
|
||
+
|
||
+HTTP_EMPTY_ARGS(count);
|
||
+
|
||
+HTTP_EMPTY_ARGS(serialize);
|
||
+HTTP_BEGIN_ARGS(unserialize, 1)
|
||
+ HTTP_ARG_VAL(serialized, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(rewind);
|
||
+HTTP_EMPTY_ARGS(valid);
|
||
+HTTP_EMPTY_ARGS(key);
|
||
+HTTP_EMPTY_ARGS(current);
|
||
+HTTP_EMPTY_ARGS(next);
|
||
+
|
||
+HTTP_EMPTY_ARGS(detach);
|
||
+HTTP_BEGIN_ARGS(prepend, 1)
|
||
+ HTTP_ARG_OBJ(HttpMessage, message, 0)
|
||
+HTTP_END_ARGS;
|
||
+HTTP_EMPTY_ARGS(reverse);
|
||
+
|
||
+#define http_message_object_read_prop _http_message_object_read_prop
|
||
+static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC);
|
||
+#define http_message_object_write_prop _http_message_object_write_prop
|
||
+static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC);
|
||
+#define http_message_object_get_prop_ptr _http_message_object_get_prop_ptr
|
||
+static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC);
|
||
+#define http_message_object_get_props _http_message_object_get_props
|
||
+static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC);
|
||
+
|
||
+#define THIS_CE http_message_object_ce
|
||
+zend_class_entry *http_message_object_ce;
|
||
+zend_function_entry http_message_object_fe[] = {
|
||
+ HTTP_MESSAGE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
|
||
+ HTTP_MESSAGE_ME(getBody, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setBody, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getHeader, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getHeaders, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setHeaders, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(addHeaders, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getType, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setType, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getInfo, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setInfo, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getResponseCode, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setResponseCode, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getResponseStatus, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setResponseStatus, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getRequestMethod, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setRequestMethod, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getRequestUrl, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setRequestUrl, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getHttpVersion, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(setHttpVersion, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(guessContentType, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(getParentMessage, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(send, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(toString, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(toMessageTypeObject, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ /* implements Countable */
|
||
+ HTTP_MESSAGE_ME(count, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ /* implements Serializable */
|
||
+ HTTP_MESSAGE_ME(serialize, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(unserialize, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ /* implements Iterator */
|
||
+ HTTP_MESSAGE_ME(rewind, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(valid, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(current, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(key, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(next, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ ZEND_MALIAS(HttpMessage, __toString, toString, HTTP_ARGS(HttpMessage, __toString), ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_MESSAGE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+ ZEND_MALIAS(HttpMessage, fromString, factory, HTTP_ARGS(HttpMessage, factory), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+ HTTP_MESSAGE_ME(fromEnv, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+
|
||
+ HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC)
|
||
+ HTTP_MESSAGE_ME(reverse, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+static zend_object_handlers http_message_object_handlers;
|
||
+
|
||
+static HashTable http_message_object_prophandlers;
|
||
+
|
||
+typedef void (*http_message_object_prophandler_func)(http_message_object *o, zval *v TSRMLS_DC);
|
||
+
|
||
+typedef struct _http_message_object_prophandler {
|
||
+ http_message_object_prophandler_func read;
|
||
+ http_message_object_prophandler_func write;
|
||
+} http_message_object_prophandler;
|
||
+
|
||
+static STATUS http_message_object_add_prophandler(const char *prop_str, size_t prop_len, http_message_object_prophandler_func read, http_message_object_prophandler_func write) {
|
||
+ http_message_object_prophandler h = { read, write };
|
||
+ return zend_hash_add(&http_message_object_prophandlers, prop_str, prop_len, (void *) &h, sizeof(h), NULL);
|
||
+}
|
||
+static STATUS http_message_object_get_prophandler(const char *prop_str, size_t prop_len, http_message_object_prophandler **handler) {
|
||
+ return zend_hash_find(&http_message_object_prophandlers, prop_str, prop_len, (void *) handler);
|
||
+}
|
||
+static void http_message_object_prophandler_get_type(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ RETVAL_LONG(obj->message->type);
|
||
+}
|
||
+static void http_message_object_prophandler_set_type(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ zval *cpy = http_zsep(IS_LONG, value);
|
||
+ http_message_set_type(obj->message, Z_LVAL_P(cpy));
|
||
+ zval_ptr_dtor(&cpy);
|
||
+}
|
||
+static void http_message_object_prophandler_get_body(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ phpstr_fix(PHPSTR(obj->message));
|
||
+ RETVAL_PHPSTR(PHPSTR(obj->message), 0, 1);
|
||
+}
|
||
+static void http_message_object_prophandler_set_body(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ zval *cpy = http_zsep(IS_STRING, value);
|
||
+ phpstr_dtor(PHPSTR(obj->message));
|
||
+ phpstr_from_string_ex(PHPSTR(obj->message), Z_STRVAL_P(cpy), Z_STRLEN_P(cpy));
|
||
+ zval_ptr_dtor(&cpy);
|
||
+}
|
||
+static void http_message_object_prophandler_get_request_method(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.method) {
|
||
+ RETVAL_STRING(obj->message->http.info.request.method, 1);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_set_request_method(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(REQUEST, obj->message)) {
|
||
+ zval *cpy = http_zsep(IS_STRING, value);
|
||
+ STR_SET(obj->message->http.info.request.method, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
|
||
+ zval_ptr_dtor(&cpy);
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_get_request_url(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.url) {
|
||
+ RETVAL_STRING(obj->message->http.info.request.url, 1);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_set_request_url(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(REQUEST, obj->message)) {
|
||
+ zval *cpy = http_zsep(IS_STRING, value);
|
||
+ STR_SET(obj->message->http.info.request.url, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
|
||
+ zval_ptr_dtor(&cpy);
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_get_response_status(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(RESPONSE, obj->message) && obj->message->http.info.response.status) {
|
||
+ RETVAL_STRING(obj->message->http.info.response.status, 1);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_set_response_status(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
|
||
+ zval *cpy = http_zsep(IS_STRING, value);
|
||
+ STR_SET(obj->message->http.info.response.status, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
|
||
+ zval_ptr_dtor(&cpy);
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_get_response_code(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
|
||
+ RETVAL_LONG(obj->message->http.info.response.code);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_set_response_code(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
|
||
+ zval *cpy = http_zsep(IS_LONG, value);
|
||
+ obj->message->http.info.response.code = Z_LVAL_P(cpy);
|
||
+ zval_ptr_dtor(&cpy);
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_get_http_version(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ RETVAL_DOUBLE(obj->message->http.version);
|
||
+}
|
||
+static void http_message_object_prophandler_set_http_version(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ zval *cpy = http_zsep(IS_DOUBLE, value);
|
||
+ obj->message->http.version = Z_DVAL_P(cpy);
|
||
+ zval_ptr_dtor(&cpy);
|
||
+}
|
||
+static void http_message_object_prophandler_get_headers(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ array_init(return_value);
|
||
+ zend_hash_copy(Z_ARRVAL_P(return_value), &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+}
|
||
+static void http_message_object_prophandler_set_headers(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ zval *cpy = http_zsep(IS_ARRAY, value);
|
||
+ zend_hash_clean(&obj->message->hdrs);
|
||
+ zend_hash_copy(&obj->message->hdrs, Z_ARRVAL_P(cpy), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ zval_ptr_dtor(&cpy);
|
||
+}
|
||
+static void http_message_object_prophandler_get_parent_message(http_message_object *obj, zval *return_value TSRMLS_DC) {
|
||
+ if (obj->message->parent) {
|
||
+ RETVAL_OBJVAL(obj->parent, 1);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+}
|
||
+static void http_message_object_prophandler_set_parent_message(http_message_object *obj, zval *value TSRMLS_DC) {
|
||
+ if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), http_message_object_ce TSRMLS_CC)) {
|
||
+ if (obj->message->parent) {
|
||
+ zval tmp;
|
||
+ tmp.value.obj = obj->parent;
|
||
+ Z_OBJ_DELREF(tmp);
|
||
+ }
|
||
+ Z_OBJ_ADDREF_P(value);
|
||
+ obj->parent = value->value.obj;
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_message_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS_EX(HttpMessage, http_message_object, NULL, 0);
|
||
+
|
||
+#ifndef WONKY
|
||
+# ifdef HTTP_HAVE_SPL
|
||
+ zend_class_implements(http_message_object_ce TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator);
|
||
+# else
|
||
+ zend_class_implements(http_message_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_iterator);
|
||
+# endif
|
||
+#else
|
||
+ zend_class_implements(http_message_object_ce TSRMLS_CC, 1, zend_ce_iterator);
|
||
+#endif
|
||
+
|
||
+ http_message_object_handlers.clone_obj = _http_message_object_clone_obj;
|
||
+ http_message_object_handlers.read_property = http_message_object_read_prop;
|
||
+ http_message_object_handlers.write_property = http_message_object_write_prop;
|
||
+ http_message_object_handlers.get_properties = http_message_object_get_props;
|
||
+ http_message_object_handlers.get_property_ptr_ptr = http_message_object_get_prop_ptr;
|
||
+
|
||
+ zend_hash_init(&http_message_object_prophandlers, 9, NULL, NULL, 1);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("type")-1, HTTP_MSG_NONE, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("type")-1, http_message_object_prophandler_get_type, http_message_object_prophandler_set_type);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("body")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("body")-1, http_message_object_prophandler_get_body, http_message_object_prophandler_set_body);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("requestMethod")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("requestMethod")-1, http_message_object_prophandler_get_request_method, http_message_object_prophandler_set_request_method);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("requestUrl")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("requestUrl")-1, http_message_object_prophandler_get_request_url, http_message_object_prophandler_set_request_url);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("responseStatus")-1, http_message_object_prophandler_get_response_status, http_message_object_prophandler_set_response_status);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("responseCode")-1, http_message_object_prophandler_get_response_code, http_message_object_prophandler_set_response_code);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("httpVersion")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("httpVersion")-1, http_message_object_prophandler_get_http_version, http_message_object_prophandler_set_http_version);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("headers")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("headers")-1, http_message_object_prophandler_get_headers, http_message_object_prophandler_set_headers);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("parentMessage")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||
+ http_message_object_add_prophandler(ZEND_STRS("parentMessage")-1, http_message_object_prophandler_get_parent_message, http_message_object_prophandler_set_parent_message);
|
||
+
|
||
+#ifndef WONKY
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_NONE")-1, HTTP_MSG_NONE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_REQUEST")-1, HTTP_MSG_REQUEST TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RESPONSE")-1, HTTP_MSG_RESPONSE TSRMLS_CC);
|
||
+#endif
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_MSG_NONE", HTTP_MSG_NONE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST);
|
||
+ HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_MSHUTDOWN_FUNCTION(http_message_object)
|
||
+{
|
||
+ zend_hash_destroy(&http_message_object_prophandlers);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC)
|
||
+{
|
||
+ int i;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ /* count */
|
||
+ http_message_count(i, obj->message);
|
||
+
|
||
+ if (i > 1) {
|
||
+ zval o;
|
||
+ zend_object_value *ovalues = NULL;
|
||
+ http_message_object **objects = NULL;
|
||
+ int last = i - 1;
|
||
+
|
||
+ objects = ecalloc(i, sizeof(http_message_object *));
|
||
+ ovalues = ecalloc(i, sizeof(zend_object_value));
|
||
+
|
||
+ /* we are the first message */
|
||
+ objects[0] = obj;
|
||
+ ovalues[0] = getThis()->value.obj;
|
||
+
|
||
+ /* fetch parents */
|
||
+ INIT_PZVAL(&o);
|
||
+ o.type = IS_OBJECT;
|
||
+ for (i = 1; obj->parent.handle; ++i) {
|
||
+ o.value.obj = obj->parent;
|
||
+ ovalues[i] = o.value.obj;
|
||
+ objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ /* reorder parents */
|
||
+ for (last = --i; i; --i) {
|
||
+ objects[i]->message->parent = objects[i-1]->message;
|
||
+ objects[i]->parent = ovalues[i-1];
|
||
+ }
|
||
+ objects[0]->message->parent = NULL;
|
||
+ objects[0]->parent.handle = 0;
|
||
+ objects[0]->parent.handlers = NULL;
|
||
+
|
||
+ /* add ref (why?) */
|
||
+ Z_OBJ_ADDREF_P(getThis());
|
||
+ RETVAL_OBJVAL(ovalues[last], 1);
|
||
+
|
||
+ efree(objects);
|
||
+ efree(ovalues);
|
||
+ } else {
|
||
+ RETURN_ZVAL(getThis(), 1, 0);
|
||
+ }
|
||
+}
|
||
+
|
||
+void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC)
|
||
+{
|
||
+ zval m;
|
||
+ http_message *save_parent_msg = NULL;
|
||
+ zend_object_value save_parent_obj = {0, NULL};
|
||
+ getObject(http_message_object, obj);
|
||
+ getObjectEx(http_message_object, prepend_obj, prepend);
|
||
+
|
||
+ INIT_PZVAL(&m);
|
||
+ m.type = IS_OBJECT;
|
||
+
|
||
+ if (!top) {
|
||
+ save_parent_obj = obj->parent;
|
||
+ save_parent_msg = obj->message->parent;
|
||
+ } else {
|
||
+ /* iterate to the most parent object */
|
||
+ while (obj->parent.handle) {
|
||
+ m.value.obj = obj->parent;
|
||
+ obj = zend_object_store_get_object(&m TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* prepend */
|
||
+ obj->parent = prepend->value.obj;
|
||
+ obj->message->parent = prepend_obj->message;
|
||
+
|
||
+ /* add ref */
|
||
+ zend_objects_store_add_ref(prepend TSRMLS_CC);
|
||
+ while (prepend_obj->parent.handle) {
|
||
+ m.value.obj = prepend_obj->parent;
|
||
+ zend_objects_store_add_ref(&m TSRMLS_CC);
|
||
+ prepend_obj = zend_object_store_get_object(&m TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ if (!top) {
|
||
+ prepend_obj->parent = save_parent_obj;
|
||
+ prepend_obj->message->parent = save_parent_msg;
|
||
+ }
|
||
+}
|
||
+
|
||
+zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ return http_message_object_new_ex(ce, NULL, NULL);
|
||
+}
|
||
+
|
||
+zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ http_message_object *o;
|
||
+
|
||
+ o = ecalloc(1, sizeof(http_message_object));
|
||
+ o->zo.ce = ce;
|
||
+
|
||
+ if (ptr) {
|
||
+ *ptr = o;
|
||
+ }
|
||
+
|
||
+ if (msg) {
|
||
+ o->message = msg;
|
||
+ if (msg->parent) {
|
||
+ o->parent = http_message_object_new_ex(ce, msg->parent, NULL);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ ALLOC_HASHTABLE(OBJ_PROP(o));
|
||
+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+
|
||
+ ov.handle = putObject(http_message_object, o);
|
||
+ ov.handlers = &http_message_object_handlers;
|
||
+
|
||
+ return ov;
|
||
+}
|
||
+
|
||
+zend_object_value _http_message_object_clone_obj(zval *this_ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value new_ov;
|
||
+ http_message_object *new_obj = NULL;
|
||
+ getObject(http_message_object, old_obj);
|
||
+
|
||
+ new_ov = http_message_object_new_ex(old_obj->zo.ce, http_message_dup(old_obj->message), &new_obj);
|
||
+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||
+
|
||
+ return new_ov;
|
||
+}
|
||
+
|
||
+void _http_message_object_free(zend_object *object TSRMLS_DC)
|
||
+{
|
||
+ http_message_object *o = (http_message_object *) object;
|
||
+
|
||
+ if (o->iterator) {
|
||
+ zval_ptr_dtor(&o->iterator);
|
||
+ o->iterator = NULL;
|
||
+ }
|
||
+ if (o->message) {
|
||
+ http_message_dtor(o->message);
|
||
+ efree(o->message);
|
||
+ }
|
||
+ if (o->parent.handle) {
|
||
+ zval p;
|
||
+
|
||
+ INIT_PZVAL(&p);
|
||
+ p.type = IS_OBJECT;
|
||
+ p.value.obj = o->parent;
|
||
+ zend_objects_store_del_ref(&p TSRMLS_CC);
|
||
+ }
|
||
+ freeObject(o);
|
||
+}
|
||
+
|
||
+static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC) {
|
||
+ getObjectEx(http_message_object, obj, object);
|
||
+ http_message_object_prophandler *handler;
|
||
+
|
||
+ if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
|
||
+ zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index");
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member ZEND_LITERAL_KEY_CC TSRMLS_CC);
|
||
+}
|
||
+
|
||
+static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC)
|
||
+{
|
||
+ getObjectEx(http_message_object, obj, object);
|
||
+ http_message_object_prophandler *handler;
|
||
+ zval *return_value;
|
||
+
|
||
+ if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
|
||
+ if (type == BP_VAR_W) {
|
||
+ zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index");
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ ALLOC_ZVAL(return_value);
|
||
+#ifdef Z_SET_REFCOUNT
|
||
+ Z_SET_REFCOUNT_P(return_value, 0);
|
||
+ Z_UNSET_ISREF_P(return_value);
|
||
+#else
|
||
+ return_value->refcount = 0;
|
||
+ return_value->is_ref = 0;
|
||
+#endif
|
||
+
|
||
+ handler->read(obj, return_value TSRMLS_CC);
|
||
+
|
||
+ } else {
|
||
+ return_value = zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ return return_value;
|
||
+}
|
||
+
|
||
+static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC)
|
||
+{
|
||
+ getObjectEx(http_message_object, obj, object);
|
||
+ http_message_object_prophandler *handler;
|
||
+
|
||
+ if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
|
||
+ handler->write(obj, value TSRMLS_CC);
|
||
+ } else {
|
||
+ zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC);
|
||
+ }
|
||
+}
|
||
+
|
||
+static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC)
|
||
+{
|
||
+ zval *headers;
|
||
+ getObjectEx(http_message_object, obj, object);
|
||
+ http_message *msg = obj->message;
|
||
+ HashTable *props = OBJ_PROP(obj);
|
||
+ zval array, *parent;
|
||
+
|
||
+ INIT_ZARR(array, props);
|
||
+
|
||
+#define ASSOC_PROP(array, ptype, name, val) \
|
||
+ { \
|
||
+ char *m_prop_name; \
|
||
+ int m_prop_len; \
|
||
+ zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
|
||
+ add_assoc_ ##ptype## _ex(&array, m_prop_name, sizeof(name)+3, val); \
|
||
+ efree(m_prop_name); \
|
||
+ }
|
||
+#define ASSOC_STRING(array, name, val) ASSOC_STRINGL(array, name, val, strlen(val))
|
||
+#define ASSOC_STRINGL(array, name, val, len) \
|
||
+ { \
|
||
+ char *m_prop_name; \
|
||
+ int m_prop_len; \
|
||
+ zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
|
||
+ add_assoc_stringl_ex(&array, m_prop_name, sizeof(name)+3, val, len, 1); \
|
||
+ efree(m_prop_name); \
|
||
+ }
|
||
+
|
||
+ ASSOC_PROP(array, long, "type", msg->type);
|
||
+ ASSOC_PROP(array, double, "httpVersion", msg->http.version);
|
||
+
|
||
+ switch (msg->type) {
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ ASSOC_PROP(array, long, "responseCode", 0);
|
||
+ ASSOC_STRINGL(array, "responseStatus", "", 0);
|
||
+ ASSOC_STRING(array, "requestMethod", STR_PTR(msg->http.info.request.method));
|
||
+ ASSOC_STRING(array, "requestUrl", STR_PTR(msg->http.info.request.url));
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ ASSOC_PROP(array, long, "responseCode", msg->http.info.response.code);
|
||
+ ASSOC_STRING(array, "responseStatus", STR_PTR(msg->http.info.response.status));
|
||
+ ASSOC_STRINGL(array, "requestMethod", "", 0);
|
||
+ ASSOC_STRINGL(array, "requestUrl", "", 0);
|
||
+ break;
|
||
+
|
||
+ case HTTP_MSG_NONE:
|
||
+ default:
|
||
+ ASSOC_PROP(array, long, "responseCode", 0);
|
||
+ ASSOC_STRINGL(array, "responseStatus", "", 0);
|
||
+ ASSOC_STRINGL(array, "requestMethod", "", 0);
|
||
+ ASSOC_STRINGL(array, "requestUrl", "", 0);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(headers);
|
||
+ array_init(headers);
|
||
+ zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ ASSOC_PROP(array, zval, "headers", headers);
|
||
+ ASSOC_STRINGL(array, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg));
|
||
+
|
||
+ MAKE_STD_ZVAL(parent);
|
||
+ if (msg->parent) {
|
||
+ ZVAL_OBJVAL(parent, obj->parent, 1);
|
||
+ } else {
|
||
+ ZVAL_NULL(parent);
|
||
+ }
|
||
+ ASSOC_PROP(array, zval, "parentMessage", parent);
|
||
+
|
||
+ return OBJ_PROP(obj);
|
||
+}
|
||
+
|
||
+/* ### USERLAND ### */
|
||
+
|
||
+/* {{{ proto void HttpMessage::__construct([string message])
|
||
+ Create a new HttpMessage object instance. */
|
||
+PHP_METHOD(HttpMessage, __construct)
|
||
+{
|
||
+ int length = 0;
|
||
+ char *message = NULL;
|
||
+
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) {
|
||
+ http_message *msg = obj->message;
|
||
+
|
||
+ http_message_dtor(msg);
|
||
+ if ((obj->message = http_message_parse_ex(msg, message, length))) {
|
||
+ if (obj->message->parent) {
|
||
+ obj->parent = http_message_object_new_ex(Z_OBJCE_P(getThis()), obj->message->parent, NULL);
|
||
+ }
|
||
+ } else {
|
||
+ obj->message = http_message_init(msg);
|
||
+ }
|
||
+ }
|
||
+ if (!obj->message) {
|
||
+ obj->message = http_message_new();
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static HttpMessage HttpMessage::factory([string raw_message[, string class_name = "HttpMessage"]])
|
||
+ Create a new HttpMessage object instance. */
|
||
+PHP_METHOD(HttpMessage, factory)
|
||
+{
|
||
+ char *string = NULL, *cn = NULL;
|
||
+ int length = 0, cl = 0;
|
||
+ http_message *msg = NULL;
|
||
+ zend_object_value ov;
|
||
+ http_message_object *obj = NULL;
|
||
+
|
||
+ RETVAL_NULL();
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &string, &length, &cn, &cl)) {
|
||
+ if (length) {
|
||
+ msg = http_message_parse(string, length);
|
||
+ }
|
||
+ if ((msg || !length) && SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, msg, &obj)) {
|
||
+ RETVAL_OBJVAL(ov, 0);
|
||
+ }
|
||
+ if (obj && !obj->message) {
|
||
+ obj->message = http_message_new();
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static HttpMessage HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"])
|
||
+ Create a new HttpMessage object from environment representing either current request or response */
|
||
+PHP_METHOD(HttpMessage, fromEnv)
|
||
+{
|
||
+ char *cn = NULL;
|
||
+ int cl = 0;
|
||
+ long type;
|
||
+ http_message_object *obj = NULL;
|
||
+ zend_object_value ov;
|
||
+
|
||
+ RETVAL_NULL();
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &type, &cn, &cl)) {
|
||
+ if (SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, http_message_init_env(NULL, type), &obj)) {
|
||
+ RETVAL_OBJVAL(ov, 0);
|
||
+ }
|
||
+ if (obj && !obj->message) {
|
||
+ obj->message = http_message_new();
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::getBody()
|
||
+ Get the body of the parsed HttpMessage. */
|
||
+PHP_METHOD(HttpMessage, getBody)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+ RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::setBody(string body)
|
||
+ Set the body of the HttpMessage. NOTE: Don't forget to update any headers accordingly. */
|
||
+PHP_METHOD(HttpMessage, setBody)
|
||
+{
|
||
+ char *body;
|
||
+ int len;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &body, &len)) {
|
||
+ phpstr_dtor(PHPSTR(obj->message));
|
||
+ phpstr_from_string_ex(PHPSTR(obj->message), body, len);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::getHeader(string header)
|
||
+ Get message header. */
|
||
+PHP_METHOD(HttpMessage, getHeader)
|
||
+{
|
||
+ zval *header;
|
||
+ char *orig_header, *nice_header;
|
||
+ int header_len;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &orig_header, &header_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ nice_header = pretty_key(estrndup(orig_header, header_len), header_len, 1, 1);
|
||
+ if ((header = http_message_header_ex(obj->message, nice_header, header_len + 1, 0))) {
|
||
+ RETVAL_ZVAL(header, 1, 1);
|
||
+ }
|
||
+ efree(nice_header);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpMessage::getHeaders()
|
||
+ Get Message Headers. */
|
||
+PHP_METHOD(HttpMessage, getHeaders)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ array_init(return_value);
|
||
+ array_copy(&obj->message->hdrs, Z_ARRVAL_P(return_value));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::setHeaders(array headers)
|
||
+ Sets new headers. */
|
||
+PHP_METHOD(HttpMessage, setHeaders)
|
||
+{
|
||
+ zval *new_headers = NULL;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &new_headers)) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ zend_hash_clean(&obj->message->hdrs);
|
||
+ if (new_headers) {
|
||
+ array_copy(Z_ARRVAL_P(new_headers), &obj->message->hdrs);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
|
||
+ Add headers. If append is true, headers with the same name will be separated, else overwritten. */
|
||
+PHP_METHOD(HttpMessage, addHeaders)
|
||
+{
|
||
+ zval *new_headers;
|
||
+ zend_bool append = 0;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpMessage::getType()
|
||
+ Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
|
||
+PHP_METHOD(HttpMessage, getType)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+ RETURN_LONG(obj->message->type);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::setType(int type)
|
||
+ Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
|
||
+PHP_METHOD(HttpMessage, setType)
|
||
+{
|
||
+ long type;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
|
||
+ return;
|
||
+ }
|
||
+ http_message_set_type(obj->message, type);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::getInfo(void)
|
||
+ Get the HTTP request/response line */
|
||
+PHP_METHOD(HttpMessage, getInfo)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ switch (obj->message->type) {
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_REQUEST_FMT_ARGS(&obj->message->http, ""));
|
||
+ break;
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_RESPONSE_FMT_ARGS(&obj->message->http, ""));
|
||
+ break;
|
||
+ default:
|
||
+ RETURN_NULL();
|
||
+ break;
|
||
+ }
|
||
+ Z_TYPE_P(return_value) = IS_STRING;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::setInfo(string http_info)
|
||
+ Set type and request or response info with a standard HTTP request or response line */
|
||
+PHP_METHOD(HttpMessage, setInfo)
|
||
+{
|
||
+ char *str;
|
||
+ int len;
|
||
+ http_info inf;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) && SUCCESS == http_info_parse_ex(str, &inf, 0)) {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ http_message_set_info(obj->message, &inf);
|
||
+ http_info_dtor(&inf);
|
||
+ RETURN_TRUE;
|
||
+ }
|
||
+ RETURN_FALSE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpMessage::getResponseCode()
|
||
+ Get the Response Code of the Message. */
|
||
+PHP_METHOD(HttpMessage, getResponseCode)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
|
||
+ RETURN_LONG(obj->message->http.info.response.code);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::setResponseCode(int code)
|
||
+ Set the response code of an HTTP Response Message. */
|
||
+PHP_METHOD(HttpMessage, setResponseCode)
|
||
+{
|
||
+ long code;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (code < 100 || code > 599) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid response code (100-599): %ld", code);
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ obj->message->http.info.response.code = code;
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::getResponseStatus()
|
||
+ Get the Response Status of the message (i.e. the string following the response code). */
|
||
+PHP_METHOD(HttpMessage, getResponseStatus)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
|
||
+ if (obj->message->http.info.response.status) {
|
||
+ RETURN_STRING(obj->message->http.info.response.status, 1);
|
||
+ } else {
|
||
+ RETURN_EMPTY_STRING();
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::setResponseStatus(string status)
|
||
+ Set the Response Status of the HTTP message (i.e. the string following the response code). */
|
||
+PHP_METHOD(HttpMessage, setResponseStatus)
|
||
+{
|
||
+ char *status;
|
||
+ int status_len;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &status, &status_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ STR_SET(obj->message->http.info.response.status, estrndup(status, status_len));
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::getRequestMethod()
|
||
+ Get the Request Method of the Message. */
|
||
+PHP_METHOD(HttpMessage, getRequestMethod)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
|
||
+ if (obj->message->http.info.request.method) {
|
||
+ RETURN_STRING(obj->message->http.info.request.method, 1);
|
||
+ } else {
|
||
+ RETURN_EMPTY_STRING();
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::setRequestMethod(string method)
|
||
+ Set the Request Method of the HTTP Message. */
|
||
+PHP_METHOD(HttpMessage, setRequestMethod)
|
||
+{
|
||
+ char *method;
|
||
+ int method_len;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (method_len < 1) {
|
||
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (!http_request_method_exists(1, 0, method)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unknown request method: %s", method);
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ STR_SET(obj->message->http.info.request.method, estrndup(method, method_len));
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::getRequestUrl()
|
||
+ Get the Request URL of the Message. */
|
||
+PHP_METHOD(HttpMessage, getRequestUrl)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
|
||
+ if (obj->message->http.info.request.url) {
|
||
+ RETURN_STRING(obj->message->http.info.request.url, 1);
|
||
+ } else {
|
||
+ RETURN_EMPTY_STRING();
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::setRequestUrl(string url)
|
||
+ Set the Request URL of the HTTP Message. */
|
||
+PHP_METHOD(HttpMessage, setRequestUrl)
|
||
+{
|
||
+ char *URI;
|
||
+ int URIlen;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
|
||
+ if (URIlen < 1) {
|
||
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestUrl to an empty string");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ STR_SET(obj->message->http.info.request.url, estrndup(URI, URIlen));
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::getHttpVersion()
|
||
+ Get the HTTP Protocol Version of the Message. */
|
||
+PHP_METHOD(HttpMessage, getHttpVersion)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ char *version;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ spprintf(&version, 0, "%1.1F", obj->message->http.version);
|
||
+ RETURN_STRING(version, 0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::setHttpVersion(string version)
|
||
+ Set the HTTP Protocol version of the Message. */
|
||
+PHP_METHOD(HttpMessage, setHttpVersion)
|
||
+{
|
||
+ zval *zv;
|
||
+ char *version;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) {
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ convert_to_double(zv);
|
||
+ spprintf(&version, 0, "%1.1F", Z_DVAL_P(zv));
|
||
+ if (strcmp(version, "1.0") && strcmp(version, "1.1")) {
|
||
+ efree(version);
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %g", Z_DVAL_P(zv));
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ efree(version);
|
||
+ obj->message->http.version = Z_DVAL_P(zv);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
|
||
+ Attempts to guess the content type of supplied payload through libmagic. */
|
||
+PHP_METHOD(HttpMessage, guessContentType)
|
||
+{
|
||
+#ifdef HTTP_HAVE_MAGIC
|
||
+ char *magic_file, *ct = NULL;
|
||
+ int magic_file_len;
|
||
+ long magic_mode = MAGIC_MIME;
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
|
||
+ getObject(http_message_object, obj);
|
||
+ if ((ct = http_guess_content_type(magic_file, magic_mode, PHPSTR_VAL(&obj->message->body), PHPSTR_LEN(&obj->message->body), SEND_DATA))) {
|
||
+ RETVAL_STRING(ct, 0);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+#else
|
||
+ http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
|
||
+ RETURN_FALSE;
|
||
+#endif
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpMessage HttpMessage::getParentMessage()
|
||
+ Get parent Message. */
|
||
+PHP_METHOD(HttpMessage, getParentMessage)
|
||
+{
|
||
+ SET_EH_THROW_HTTP();
|
||
+ NO_ARGS {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (obj->message->parent) {
|
||
+ RETVAL_OBJVAL(obj->parent, 1);
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpMessage does not have a parent message");
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::send()
|
||
+ Send the Message according to its type as Response or Request. */
|
||
+PHP_METHOD(HttpMessage, send)
|
||
+{
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ RETURN_SUCCESS(http_message_send(obj->message));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::toString([bool include_parent = false])
|
||
+ Get the string representation of the Message. */
|
||
+PHP_METHOD(HttpMessage, toString)
|
||
+{
|
||
+ if (return_value_used) {
|
||
+ char *string;
|
||
+ size_t length;
|
||
+ zend_bool include_parent = 0;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (include_parent) {
|
||
+ http_message_serialize(obj->message, &string, &length);
|
||
+ } else {
|
||
+ http_message_tostring(obj->message, &string, &length);
|
||
+ }
|
||
+ RETURN_STRINGL(string, length, 0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpRequest|HttpResponse HttpMessage::toMessageTypeObject(void)
|
||
+ Creates an object regarding to the type of the message. Returns either an HttpRequest or HttpResponse object on success, or NULL on failure. */
|
||
+PHP_METHOD(HttpMessage, toMessageTypeObject)
|
||
+{
|
||
+ SET_EH_THROW_HTTP();
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ switch (obj->message->type) {
|
||
+ case HTTP_MSG_REQUEST:
|
||
+ {
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+ int method;
|
||
+ char *url;
|
||
+ zval post, body, *array, *headers, *host = http_message_header(obj->message, "Host");
|
||
+ php_url hurl, *purl = php_url_parse(STR_PTR(obj->message->http.info.request.url));
|
||
+
|
||
+ MAKE_STD_ZVAL(array);
|
||
+ array_init(array);
|
||
+
|
||
+ memset(&hurl, 0, sizeof(php_url));
|
||
+ if (host) {
|
||
+ hurl.host = Z_STRVAL_P(host);
|
||
+ zval_ptr_dtor(&host);
|
||
+ }
|
||
+ http_build_url(HTTP_URL_REPLACE, purl, &hurl, NULL, &url, NULL);
|
||
+ php_url_free(purl);
|
||
+ add_assoc_string(array, "url", url, 0);
|
||
+
|
||
+ if ( obj->message->http.info.request.method &&
|
||
+ ((method = http_request_method_exists(1, 0, obj->message->http.info.request.method)) ||
|
||
+ (method = http_request_method_register(obj->message->http.info.request.method, strlen(obj->message->http.info.request.method))))) {
|
||
+ add_assoc_long(array, "method", method);
|
||
+ }
|
||
+
|
||
+ if (10 == (int) (obj->message->http.version * 10)) {
|
||
+ add_assoc_long(array, "protocol", CURL_HTTP_VERSION_1_0);
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(headers);
|
||
+ array_init(headers);
|
||
+ array_copy(&obj->message->hdrs, Z_ARRVAL_P(headers));
|
||
+ add_assoc_zval(array, "headers", headers);
|
||
+
|
||
+ object_init_ex(return_value, http_request_object_ce);
|
||
+ zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setoptions", NULL, array);
|
||
+ zval_ptr_dtor(&array);
|
||
+
|
||
+ if (PHPSTR_VAL(obj->message) && PHPSTR_LEN(obj->message)) {
|
||
+ phpstr_fix(PHPSTR(obj->message));
|
||
+ INIT_PZVAL(&body);
|
||
+ ZVAL_STRINGL(&body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 0);
|
||
+ if (method != HTTP_POST) {
|
||
+ zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setbody", NULL, &body);
|
||
+ } else {
|
||
+ INIT_PZVAL(&post);
|
||
+ array_init(&post);
|
||
+
|
||
+ zval_copy_ctor(&body);
|
||
+ sapi_module.treat_data(PARSE_STRING, Z_STRVAL(body), &post TSRMLS_CC);
|
||
+ zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setpostfields", NULL, &post);
|
||
+ zval_dtor(&post);
|
||
+ }
|
||
+ }
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpRequest (missing curl support)");
|
||
+#endif
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case HTTP_MSG_RESPONSE:
|
||
+ {
|
||
+#ifndef WONKY
|
||
+ HashPosition pos1, pos2;
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **header, **h, *body;
|
||
+
|
||
+ if (obj->message->http.info.response.code) {
|
||
+ http_send_status(obj->message->http.info.response.code);
|
||
+ }
|
||
+
|
||
+ object_init_ex(return_value, http_response_object_ce);
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos1, &obj->message->hdrs, key, header) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ zval *zkey;
|
||
+
|
||
+ MAKE_STD_ZVAL(zkey);
|
||
+ ZVAL_STRINGL(zkey, key.str, key.len - 1, 1);
|
||
+
|
||
+ switch (Z_TYPE_PP(header)) {
|
||
+ case IS_ARRAY:
|
||
+ case IS_OBJECT:
|
||
+ FOREACH_HASH_VAL(pos2, HASH_OF(*header), h) {
|
||
+ ZVAL_ADDREF(*h);
|
||
+ zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *h);
|
||
+ zval_ptr_dtor(h);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ ZVAL_ADDREF(*header);
|
||
+ zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *header);
|
||
+ zval_ptr_dtor(header);
|
||
+ break;
|
||
+ }
|
||
+ zval_ptr_dtor(&zkey);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(body);
|
||
+ ZVAL_STRINGL(body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 1);
|
||
+ zend_call_method_with_1_params(&return_value, http_response_object_ce, NULL, "setdata", NULL, body);
|
||
+ zval_ptr_dtor(&body);
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpResponse (need PHP 5.1+)");
|
||
+#endif
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ default:
|
||
+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HttpMessage::TYPE_REQUEST nor HttpMessage::TYPE_RESPONSE");
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpMessage::count()
|
||
+ Implements Countable::count(). Returns the number of parent messages + 1. */
|
||
+PHP_METHOD(HttpMessage, count)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ long i;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ http_message_count(i, obj->message);
|
||
+ RETURN_LONG(i);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpMessage::serialize()
|
||
+ Implements Serializable::serialize(). Returns the serialized representation of the HttpMessage. */
|
||
+PHP_METHOD(HttpMessage, serialize)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ char *string;
|
||
+ size_t length;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ http_message_serialize(obj->message, &string, &length);
|
||
+ RETURN_STRINGL(string, length, 0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::unserialize(string serialized)
|
||
+ Implements Serializable::unserialize(). Re-constructs the HttpMessage based upon the serialized string. */
|
||
+PHP_METHOD(HttpMessage, unserialize)
|
||
+{
|
||
+ int length;
|
||
+ char *serialized;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &length)) {
|
||
+ http_message *msg;
|
||
+
|
||
+ http_message_dtor(obj->message);
|
||
+ if ((msg = http_message_parse_ex(obj->message, serialized, (size_t) length))) {
|
||
+ obj->message = msg;
|
||
+ } else {
|
||
+ http_message_init(obj->message);
|
||
+ http_error(HE_ERROR, HTTP_E_RUNTIME, "Could not unserialize HttpMessage");
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpMessage HttpMessage::detach(void)
|
||
+ Returns a clone of an HttpMessage object detached from any parent messages. */
|
||
+PHP_METHOD(HttpMessage, detach)
|
||
+{
|
||
+ http_info info;
|
||
+ http_message *msg;
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ info.type = obj->message->type;
|
||
+ memcpy(&HTTP_INFO(&info), &HTTP_INFO(obj->message), sizeof(struct http_info));
|
||
+
|
||
+ msg = http_message_new();
|
||
+ http_message_set_info(msg, &info);
|
||
+
|
||
+ zend_hash_copy(&msg->hdrs, &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ phpstr_append(&msg->body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message));
|
||
+
|
||
+ RETVAL_OBJVAL(http_message_object_new_ex(Z_OBJCE_P(getThis()), msg, NULL), 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::prepend(HttpMessage message[, bool top = true])
|
||
+ Prepends message(s) to the HTTP message. Throws HttpInvalidParamException if the message is located within the same message chain. */
|
||
+PHP_METHOD(HttpMessage, prepend)
|
||
+{
|
||
+ zval *prepend;
|
||
+ zend_bool top = 1;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, http_message_object_ce, &top)) {
|
||
+ http_message *msg[2];
|
||
+ getObject(http_message_object, obj);
|
||
+ getObjectEx(http_message_object, prepend_obj, prepend);
|
||
+
|
||
+ /* safety check */
|
||
+ for (msg[0] = obj->message; msg[0]; msg[0] = msg[0]->parent) {
|
||
+ for (msg[1] = prepend_obj->message; msg[1]; msg[1] = msg[1]->parent) {
|
||
+ if (msg[0] == msg[1]) {
|
||
+ http_error(HE_THROW, HTTP_E_INVALID_PARAM, "Cannot prepend a message located within the same message chain");
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ http_message_object_prepend_ex(getThis(), prepend, top);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpMessage HttpMessage::reverse()
|
||
+ Reorders the message chain in reverse order. Returns the most parent HttpMessage object. */
|
||
+PHP_METHOD(HttpMessage, reverse)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ http_message_object_reverse(getThis(), return_value);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::rewind(void)
|
||
+ Implements Iterator::rewind(). */
|
||
+PHP_METHOD(HttpMessage, rewind)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (obj->iterator) {
|
||
+ zval_ptr_dtor(&obj->iterator);
|
||
+ }
|
||
+ ZVAL_ADDREF(getThis());
|
||
+ obj->iterator = getThis();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpMessage::valid(void)
|
||
+ Implements Iterator::valid(). */
|
||
+PHP_METHOD(HttpMessage, valid)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ RETURN_BOOL(obj->iterator != NULL);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpMessage::next(void)
|
||
+ Implements Iterator::next(). */
|
||
+PHP_METHOD(HttpMessage, next)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_message_object, obj);
|
||
+ if (obj->iterator) {
|
||
+ getObjectEx(http_message_object, itr, obj->iterator);
|
||
+
|
||
+ if (itr && itr->parent.handle) {
|
||
+ zval *old = obj->iterator;
|
||
+ MAKE_STD_ZVAL(obj->iterator);
|
||
+ ZVAL_OBJVAL(obj->iterator, itr->parent, 1);
|
||
+ zval_ptr_dtor(&old);
|
||
+ } else {
|
||
+ zval_ptr_dtor(&obj->iterator);
|
||
+ obj->iterator = NULL;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpMessage::key(void)
|
||
+ Implements Iterator::key(). */
|
||
+PHP_METHOD(HttpMessage, key)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ RETURN_LONG(obj->iterator ? obj->iterator->value.obj.handle:0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpMessage HttpMessage::current(void)
|
||
+ Implements Iterator::current(). */
|
||
+PHP_METHOD(HttpMessage, current)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_message_object, obj);
|
||
+
|
||
+ if (obj->iterator) {
|
||
+ RETURN_ZVAL(obj->iterator, 1, 0);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_persistent_handle_api.c
|
||
@@ -0,0 +1,388 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_persistent_handle_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#include "php_http.h"
|
||
+#include "php_http_api.h"
|
||
+
|
||
+#include "php_http_persistent_handle_api.h"
|
||
+
|
||
+#ifndef HTTP_DEBUG_PHANDLES
|
||
+# define HTTP_DEBUG_PHANDLES 0
|
||
+#endif
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+# undef inline
|
||
+# define inline
|
||
+#endif
|
||
+
|
||
+static HashTable http_persistent_handles_hash;
|
||
+#ifdef ZTS
|
||
+# define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
|
||
+# define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
|
||
+static MUTEX_T http_persistent_handles_lock;
|
||
+#else
|
||
+# define LOCK()
|
||
+# define UNLOCK()
|
||
+#endif
|
||
+
|
||
+typedef struct _http_persistent_handle_list_t {
|
||
+ HashTable free;
|
||
+ ulong used;
|
||
+} http_persistent_handle_list;
|
||
+
|
||
+typedef struct _http_persistent_handle_provider_t {
|
||
+ http_persistent_handle_list list; /* "ident" => array(handles) entries */
|
||
+ http_persistent_handle_ctor ctor;
|
||
+ http_persistent_handle_dtor dtor;
|
||
+ http_persistent_handle_copy copy;
|
||
+} http_persistent_handle_provider;
|
||
+
|
||
+static inline http_persistent_handle_list *http_persistent_handle_list_init(http_persistent_handle_list *list)
|
||
+{
|
||
+ int free_list;
|
||
+
|
||
+ if ((free_list = !list)) {
|
||
+ list = pemalloc(sizeof(http_persistent_handle_list), 1);
|
||
+ }
|
||
+
|
||
+ list->used = 0;
|
||
+
|
||
+ if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) {
|
||
+ if (free_list) {
|
||
+ pefree(list, 1);
|
||
+ }
|
||
+ list = NULL;
|
||
+ }
|
||
+
|
||
+ return list;
|
||
+}
|
||
+
|
||
+static inline void http_persistent_handle_list_dtor(http_persistent_handle_list *list, http_persistent_handle_dtor dtor)
|
||
+{
|
||
+ HashPosition pos;
|
||
+ void **handle;
|
||
+
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "LSTDTOR: %p\n", list);
|
||
+#endif
|
||
+ FOREACH_HASH_VAL(pos, &list->free, handle) {
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "DESTROY: %p\n", *handle);
|
||
+#endif
|
||
+
|
||
+ dtor(*handle);
|
||
+ }
|
||
+ zend_hash_destroy(&list->free);
|
||
+}
|
||
+
|
||
+static inline void http_persistent_handle_list_free(http_persistent_handle_list **list, http_persistent_handle_dtor dtor)
|
||
+{
|
||
+ http_persistent_handle_list_dtor(*list, dtor);
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "LSTFREE: %p\n", *list);
|
||
+#endif
|
||
+ pefree(*list, 1);
|
||
+ *list = NULL;
|
||
+}
|
||
+
|
||
+static inline http_persistent_handle_list *http_persistent_handle_list_find(http_persistent_handle_provider *provider TSRMLS_DC)
|
||
+{
|
||
+ http_persistent_handle_list **list, *new_list;
|
||
+
|
||
+ if (SUCCESS == zend_hash_quick_find(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "LSTFIND: %p\n", *list);
|
||
+#endif
|
||
+ return *list;
|
||
+ }
|
||
+
|
||
+ if ((new_list = http_persistent_handle_list_init(NULL))) {
|
||
+ if (SUCCESS == zend_hash_quick_add(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &new_list, sizeof(http_persistent_handle_list *), (void *) &list)) {
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "LSTFIND: %p (new)\n", *list);
|
||
+#endif
|
||
+ return *list;
|
||
+ }
|
||
+ http_persistent_handle_list_free(&new_list, provider->dtor);
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+static inline STATUS http_persistent_handle_do_acquire(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)
|
||
+{
|
||
+ ulong index;
|
||
+ void **handle_ptr;
|
||
+ http_persistent_handle_list *list;
|
||
+
|
||
+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
|
||
+ zend_hash_internal_pointer_end(&list->free);
|
||
+ if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&list->free, NULL, &index, 0) && SUCCESS == zend_hash_get_current_data(&list->free, (void *) &handle_ptr)) {
|
||
+ *handle = *handle_ptr;
|
||
+ zend_hash_index_del(&list->free, index);
|
||
+ } else {
|
||
+ *handle = provider->ctor();
|
||
+ }
|
||
+
|
||
+ if (*handle) {
|
||
+ ++provider->list.used;
|
||
+ ++list->used;
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ } else {
|
||
+ *handle = NULL;
|
||
+ }
|
||
+
|
||
+ return FAILURE;
|
||
+}
|
||
+
|
||
+static inline STATUS http_persistent_handle_do_release(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)
|
||
+{
|
||
+ http_persistent_handle_list *list;
|
||
+
|
||
+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
|
||
+ if (provider->list.used >= HTTP_G->persistent.handles.limit) {
|
||
+ provider->dtor(*handle);
|
||
+ } else {
|
||
+ if (SUCCESS != zend_hash_next_index_insert(&list->free, (void *) handle, sizeof(void *), NULL)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ *handle = NULL;
|
||
+ --provider->list.used;
|
||
+ --list->used;
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ return FAILURE;
|
||
+}
|
||
+
|
||
+static inline STATUS http_persistent_handle_do_accrete(http_persistent_handle_provider *provider, void *old_handle, void **new_handle TSRMLS_DC)
|
||
+{
|
||
+ http_persistent_handle_list *list;
|
||
+
|
||
+ if (provider->copy && (*new_handle = provider->copy(old_handle))) {
|
||
+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
|
||
+ ++list->used;
|
||
+ }
|
||
+ ++provider->list.used;
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+
|
||
+static void http_persistent_handles_hash_dtor(void *p)
|
||
+{
|
||
+ http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p;
|
||
+ http_persistent_handle_list **list, *list_tmp;
|
||
+ HashPosition pos;
|
||
+
|
||
+ FOREACH_HASH_VAL(pos, &provider->list.free, list) {
|
||
+ /* fix shutdown crash in PHP4 */
|
||
+ list_tmp = *list;
|
||
+ http_persistent_handle_list_free(&list_tmp, provider->dtor);
|
||
+ }
|
||
+
|
||
+ zend_hash_destroy(&provider->list.free);
|
||
+}
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_persistent_handle)
|
||
+{
|
||
+ zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1);
|
||
+#ifdef ZTS
|
||
+ http_persistent_handles_lock = tsrm_mutex_alloc();
|
||
+#endif
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle)
|
||
+{
|
||
+ zend_hash_destroy(&http_persistent_handles_hash);
|
||
+#ifdef ZTS
|
||
+ tsrm_mutex_free(http_persistent_handles_lock);
|
||
+#endif
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor, http_persistent_handle_copy copy)
|
||
+{
|
||
+ STATUS status = FAILURE;
|
||
+ http_persistent_handle_provider provider;
|
||
+
|
||
+ LOCK();
|
||
+ if (http_persistent_handle_list_init(&provider.list)) {
|
||
+ provider.ctor = ctor;
|
||
+ provider.dtor = dtor;
|
||
+ provider.copy = copy;
|
||
+
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "PROVIDE: %s\n", name_str);
|
||
+#endif
|
||
+
|
||
+ if (SUCCESS == zend_hash_add(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider, sizeof(http_persistent_handle_provider), NULL)) {
|
||
+ status = SUCCESS;
|
||
+ }
|
||
+ }
|
||
+ UNLOCK();
|
||
+
|
||
+ return status;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC)
|
||
+{
|
||
+ STATUS status = FAILURE;
|
||
+ http_persistent_handle_provider *provider;
|
||
+
|
||
+ *handle = NULL;
|
||
+ LOCK();
|
||
+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
|
||
+ status = http_persistent_handle_do_acquire(provider, handle TSRMLS_CC);
|
||
+ }
|
||
+ UNLOCK();
|
||
+
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "ACQUIRE: %p (%s)\n", *handle, name_str);
|
||
+#endif
|
||
+
|
||
+ return status;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC)
|
||
+{
|
||
+ STATUS status = FAILURE;
|
||
+ http_persistent_handle_provider *provider;
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ void *handle_tmp = *handle;
|
||
+#endif
|
||
+
|
||
+ LOCK();
|
||
+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
|
||
+ status = http_persistent_handle_do_release(provider, handle TSRMLS_CC);
|
||
+ }
|
||
+ UNLOCK();
|
||
+
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "RELEASE: %p (%s)\n", handle_tmp, name_str);
|
||
+#endif
|
||
+
|
||
+ return status;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_accrete_ex(const char *name_str, size_t name_len, void *old_handle, void **new_handle TSRMLS_DC)
|
||
+{
|
||
+ STATUS status = FAILURE;
|
||
+ http_persistent_handle_provider *provider;
|
||
+
|
||
+ *new_handle = NULL;
|
||
+ LOCK();
|
||
+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
|
||
+ status = http_persistent_handle_do_accrete(provider, old_handle, new_handle TSRMLS_CC);
|
||
+ }
|
||
+ UNLOCK();
|
||
+
|
||
+#if HTTP_DEBUG_PHANDLES
|
||
+ fprintf(stderr, "ACCRETE: %p > %p (%s)\n", old_handle, *new_handle, name_str);
|
||
+#endif
|
||
+
|
||
+ return status;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC)
|
||
+{
|
||
+ http_persistent_handle_provider *provider;
|
||
+ http_persistent_handle_list *list, **listp;
|
||
+ HashPosition pos1, pos2;
|
||
+
|
||
+ LOCK();
|
||
+ if (name_str && name_len) {
|
||
+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
|
||
+ if (current_ident_only) {
|
||
+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
|
||
+ http_persistent_handle_list_dtor(list, provider->dtor);
|
||
+ http_persistent_handle_list_init(list);
|
||
+ }
|
||
+ } else {
|
||
+ FOREACH_HASH_VAL(pos1, &provider->list.free, listp) {
|
||
+ http_persistent_handle_list_dtor(*listp, provider->dtor);
|
||
+ http_persistent_handle_list_init(*listp);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ FOREACH_HASH_VAL(pos1, &http_persistent_handles_hash, provider) {
|
||
+ if (current_ident_only) {
|
||
+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
|
||
+ http_persistent_handle_list_dtor(list, provider->dtor);
|
||
+ http_persistent_handle_list_init(list);
|
||
+ }
|
||
+ } else {
|
||
+ FOREACH_HASH_VAL(pos2, &provider->list.free, listp) {
|
||
+ http_persistent_handle_list_dtor(*listp, provider->dtor);
|
||
+ http_persistent_handle_list_init(*listp);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ UNLOCK();
|
||
+}
|
||
+
|
||
+PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC)
|
||
+{
|
||
+ zval *zentry[2];
|
||
+ HashPosition pos1, pos2;
|
||
+ HashKey key1 = initHashKey(0), key2 = initHashKey(0);
|
||
+ http_persistent_handle_provider *provider;
|
||
+ http_persistent_handle_list **list;
|
||
+
|
||
+ LOCK();
|
||
+ if (zend_hash_num_elements(&http_persistent_handles_hash)) {
|
||
+ if (!ht) {
|
||
+ ALLOC_HASHTABLE(ht);
|
||
+ zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+ }
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos1, &http_persistent_handles_hash, key1, provider) {
|
||
+ MAKE_STD_ZVAL(zentry[0]);
|
||
+ array_init(zentry[0]);
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos2, &provider->list.free, key2, list) {
|
||
+ MAKE_STD_ZVAL(zentry[1]);
|
||
+ array_init(zentry[1]);
|
||
+ add_assoc_long_ex(zentry[1], ZEND_STRS("used"), (*list)->used);
|
||
+ add_assoc_long_ex(zentry[1], ZEND_STRS("free"), zend_hash_num_elements(&(*list)->free));
|
||
+
|
||
+ /* use zend_hash_* not add_assoc_* (which is zend_symtable_*) as we want a string even for numbers */
|
||
+ zend_hash_add(Z_ARRVAL_P(zentry[0]), key2.str, key2.len, &zentry[1], sizeof(zval *), NULL);
|
||
+ }
|
||
+
|
||
+ zend_hash_add(ht, key1.str, key1.len, &zentry[0], sizeof(zval *), NULL);
|
||
+ }
|
||
+ } else if (ht) {
|
||
+ ht = NULL;
|
||
+ }
|
||
+ UNLOCK();
|
||
+
|
||
+ return ht;
|
||
+}
|
||
+
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_querystring_api.c
|
||
@@ -0,0 +1,220 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_querystring_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_variables.h"
|
||
+#ifdef HTTP_HAVE_ICONV
|
||
+# undef PHP_ATOM_INC
|
||
+# include "ext/iconv/php_iconv.h"
|
||
+# include "ext/standard/url.h"
|
||
+#endif
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+#include "php_http_querystring_api.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+#define THIS_CE http_querystring_object_ce
|
||
+extern zend_class_entry *http_querystring_object_ce;
|
||
+#endif
|
||
+
|
||
+
|
||
+#define http_querystring_modify_array_ex(q, t, k, kl, i, pe) _http_querystring_modify_array_ex((q), (t), (k), (kl), (i), (pe) TSRMLS_CC)
|
||
+static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC);
|
||
+#define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC)
|
||
+static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC);
|
||
+
|
||
+
|
||
+#ifdef HTTP_HAVE_ICONV
|
||
+PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC)
|
||
+{
|
||
+ HashPosition pos;
|
||
+ zval **entry = NULL;
|
||
+ char *xlate_str = NULL, *xkey;
|
||
+ size_t xlate_len = 0, xlen;
|
||
+ HashKey key = initHashKey(0);
|
||
+
|
||
+ FOREACH_KEYVAL(pos, param, key, entry) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.str, key.len-1, &xkey, &xlen, oe, ie)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (Z_TYPE_PP(entry) == IS_STRING) {
|
||
+ if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ efree(xkey);
|
||
+ }
|
||
+ http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0);
|
||
+ } else {
|
||
+ add_index_stringl(array, key.num, xlate_str, xlate_len, 0);
|
||
+ }
|
||
+ } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
|
||
+ zval *subarray;
|
||
+
|
||
+ MAKE_STD_ZVAL(subarray);
|
||
+ array_init(subarray);
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ add_assoc_zval_ex(array, xkey, xlen+1, subarray);
|
||
+ } else {
|
||
+ add_index_zval(array, key.num, subarray);
|
||
+ }
|
||
+ if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ efree(xkey);
|
||
+ }
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ efree(xkey);
|
||
+ }
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+#endif /* HAVE_ICONV */
|
||
+
|
||
+PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC)
|
||
+{
|
||
+ char *s = NULL;
|
||
+ size_t l = 0;
|
||
+
|
||
+ if (Z_TYPE_P(qarray) != IS_ARRAY) {
|
||
+ convert_to_array(qarray);
|
||
+ }
|
||
+ if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) {
|
||
+ zval_dtor(qstring);
|
||
+ ZVAL_STRINGL(qstring, s, l, 0);
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string");
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC)
|
||
+{
|
||
+ if (Z_TYPE_P(params) == IS_ARRAY) {
|
||
+ return http_querystring_modify_array(qarray, params);
|
||
+ } else if (Z_TYPE_P(params) == IS_OBJECT) {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if (instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) {
|
||
+ return http_querystring_modify_array(qarray, zend_read_property(THIS_CE, params, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC));
|
||
+ } else {
|
||
+#endif
|
||
+ return http_querystring_modify_array(qarray, params);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ }
|
||
+#endif
|
||
+ } else {
|
||
+ int rv;
|
||
+ zval array;
|
||
+ zval *qstring = http_zsep(IS_STRING, params);
|
||
+
|
||
+ INIT_PZVAL(&array);
|
||
+ array_init(&array);
|
||
+
|
||
+ sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(qstring)), &array TSRMLS_CC);
|
||
+ zval_ptr_dtor(&qstring);
|
||
+
|
||
+ rv = http_querystring_modify_array(qarray, &array);
|
||
+ zval_dtor(&array);
|
||
+ return rv;
|
||
+ }
|
||
+}
|
||
+
|
||
+static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC)
|
||
+{
|
||
+ int rv = 0;
|
||
+ HashKey key = initHashKey(0);
|
||
+ HashPosition pos;
|
||
+ zval **params_entry = NULL;
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos, HASH_OF(params), key, params_entry) {
|
||
+ /* only public properties */
|
||
+ if ((key.type != HASH_KEY_IS_STRING || *key.str) && http_querystring_modify_array_ex(qarray, key.type, key.str, key.len, key.num, *params_entry)) {
|
||
+ rv = 1;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return rv;
|
||
+}
|
||
+
|
||
+static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC)
|
||
+{
|
||
+ zval **qarray_entry;
|
||
+
|
||
+ /* ensure array type */
|
||
+ if (Z_TYPE_P(qarray) != IS_ARRAY) {
|
||
+ convert_to_array(qarray);
|
||
+ }
|
||
+
|
||
+ /* delete */
|
||
+ if (Z_TYPE_P(params_entry) == IS_NULL) {
|
||
+ if (key_type == HASH_KEY_IS_STRING) {
|
||
+ return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen));
|
||
+ } else {
|
||
+ return (SUCCESS == zend_hash_index_del(Z_ARRVAL_P(qarray), idx));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* update */
|
||
+ if ( ((key_type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry))) ||
|
||
+ ((key_type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), idx, (void *) &qarray_entry)))) {
|
||
+ zval equal;
|
||
+
|
||
+ /* recursive */
|
||
+ if (Z_TYPE_P(params_entry) == IS_ARRAY || Z_TYPE_P(params_entry) == IS_OBJECT) {
|
||
+ return http_querystring_modify(*qarray_entry, params_entry);
|
||
+ }
|
||
+ /* equal */
|
||
+ if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) {
|
||
+ return 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* add */
|
||
+ if (Z_TYPE_P(params_entry) == IS_OBJECT) {
|
||
+ zval *new_array;
|
||
+
|
||
+ MAKE_STD_ZVAL(new_array);
|
||
+ array_init(new_array);
|
||
+ http_querystring_modify_array(new_array, params_entry);
|
||
+ params_entry = new_array;
|
||
+ } else {
|
||
+ ZVAL_ADDREF(params_entry);
|
||
+ }
|
||
+ if (key_type == HASH_KEY_IS_STRING) {
|
||
+ add_assoc_zval_ex(qarray, key, keylen, params_entry);
|
||
+ } else {
|
||
+ add_index_zval(qarray, idx, params_entry);
|
||
+ }
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/http_querystring_object.c
|
||
@@ -0,0 +1,628 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_querystring_object.c 300299 2010-06-09 06:23:16Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#include "php_variables.h"
|
||
+#include "zend_interfaces.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_querystring_api.h"
|
||
+#include "php_http_querystring_object.h"
|
||
+#include "php_http_exception_object.h"
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpQueryString, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpQueryString, method, 0)
|
||
+#define HTTP_QUERYSTRING_ME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, method), visibility)
|
||
+#define HTTP_QUERYSTRING_GME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, __getter), visibility)
|
||
+
|
||
+HTTP_BEGIN_ARGS(__construct, 0)
|
||
+ HTTP_ARG_VAL(global, 0)
|
||
+ HTTP_ARG_VAL(params, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+#ifndef WONKY
|
||
+HTTP_BEGIN_ARGS(singleton, 0)
|
||
+ HTTP_ARG_VAL(global, 0)
|
||
+HTTP_END_ARGS;
|
||
+#endif
|
||
+
|
||
+HTTP_BEGIN_ARGS(factory, 0)
|
||
+ HTTP_ARG_VAL(global, 0)
|
||
+ HTTP_ARG_VAL(params, 0)
|
||
+ HTTP_ARG_VAL(class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(toArray);
|
||
+HTTP_EMPTY_ARGS(toString);
|
||
+
|
||
+HTTP_BEGIN_ARGS(get, 0)
|
||
+ HTTP_ARG_VAL(name, 0)
|
||
+ HTTP_ARG_VAL(type, 0)
|
||
+ HTTP_ARG_VAL(defval, 0)
|
||
+ HTTP_ARG_VAL(delete, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(set, 1)
|
||
+ HTTP_ARG_VAL(params, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(mod, 0)
|
||
+ HTTP_ARG_VAL(params, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(__getter, 1)
|
||
+ HTTP_ARG_VAL(name, 0)
|
||
+ HTTP_ARG_VAL(defval, 0)
|
||
+ HTTP_ARG_VAL(delete, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+#ifdef HTTP_HAVE_ICONV
|
||
+HTTP_BEGIN_ARGS(xlate, 2)
|
||
+ HTTP_ARG_VAL(from_encoding, 0)
|
||
+ HTTP_ARG_VAL(to_encoding, 0)
|
||
+HTTP_END_ARGS;
|
||
+#endif
|
||
+
|
||
+HTTP_EMPTY_ARGS(serialize);
|
||
+HTTP_BEGIN_ARGS(unserialize, 1)
|
||
+ HTTP_ARG_VAL(serialized, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(offsetGet, 1)
|
||
+ HTTP_ARG_VAL(offset, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(offsetSet, 2)
|
||
+ HTTP_ARG_VAL(offset, 0)
|
||
+ HTTP_ARG_VAL(value, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(offsetExists, 1)
|
||
+ HTTP_ARG_VAL(offset, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(offsetUnset, 1)
|
||
+ HTTP_ARG_VAL(offset, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+
|
||
+#define THIS_CE http_querystring_object_ce
|
||
+zend_class_entry *http_querystring_object_ce;
|
||
+zend_function_entry http_querystring_object_fe[] = {
|
||
+ HTTP_QUERYSTRING_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
|
||
+
|
||
+ HTTP_QUERYSTRING_ME(toArray, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_ME(toString, ZEND_ACC_PUBLIC)
|
||
+ ZEND_MALIAS(HttpQueryString, __toString, toString, HTTP_ARGS(HttpQueryString, toString), ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_QUERYSTRING_ME(get, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_ME(set, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_ME(mod, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_QUERYSTRING_GME(getBool, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_GME(getInt, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_GME(getFloat, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_GME(getString, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_GME(getArray, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_GME(getObject, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_QUERYSTRING_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+#ifndef WONKY
|
||
+ HTTP_QUERYSTRING_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_ICONV
|
||
+ HTTP_QUERYSTRING_ME(xlate, ZEND_ACC_PUBLIC)
|
||
+#endif
|
||
+
|
||
+ /* Implements Serializable */
|
||
+ HTTP_QUERYSTRING_ME(serialize, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_ME(unserialize, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ /* Implements ArrayAccess */
|
||
+ HTTP_QUERYSTRING_ME(offsetGet, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_ME(offsetSet, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_ME(offsetExists, ZEND_ACC_PUBLIC)
|
||
+ HTTP_QUERYSTRING_ME(offsetUnset, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+static zend_object_handlers http_querystring_object_handlers;
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_querystring_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS_EX(HttpQueryString, http_querystring_object, NULL, 0);
|
||
+
|
||
+#ifndef WONKY
|
||
+ zend_class_implements(http_querystring_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_arrayaccess);
|
||
+#endif
|
||
+
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("queryArray")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("queryString")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+
|
||
+#ifndef WONKY
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_BOOL")-1, HTTP_QUERYSTRING_TYPE_BOOL TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_INT")-1, HTTP_QUERYSTRING_TYPE_INT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_FLOAT")-1, HTTP_QUERYSTRING_TYPE_FLOAT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_STRING")-1, HTTP_QUERYSTRING_TYPE_STRING TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ARRAY")-1, HTTP_QUERYSTRING_TYPE_ARRAY TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_OBJECT")-1, HTTP_QUERYSTRING_TYPE_OBJECT TSRMLS_CC);
|
||
+#endif
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_BOOL", HTTP_QUERYSTRING_TYPE_BOOL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_INT", HTTP_QUERYSTRING_TYPE_INT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_FLOAT", HTTP_QUERYSTRING_TYPE_FLOAT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_STRING", HTTP_QUERYSTRING_TYPE_STRING);
|
||
+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_ARRAY", HTTP_QUERYSTRING_TYPE_ARRAY);
|
||
+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_OBJECT", HTTP_QUERYSTRING_TYPE_OBJECT);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ return http_querystring_object_new_ex(ce, NULL, NULL);
|
||
+}
|
||
+
|
||
+zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ http_querystring_object *o;
|
||
+
|
||
+ o = ecalloc(1, sizeof(http_querystring_object));
|
||
+ o->zo.ce = ce;
|
||
+
|
||
+ if (ptr) {
|
||
+ *ptr = o;
|
||
+ }
|
||
+
|
||
+ ALLOC_HASHTABLE(OBJ_PROP(o));
|
||
+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+
|
||
+ ov.handle = putObject(http_querystring_object, o);
|
||
+ ov.handlers = &http_querystring_object_handlers;
|
||
+
|
||
+ return ov;
|
||
+}
|
||
+
|
||
+void _http_querystring_object_free(zend_object *object TSRMLS_DC)
|
||
+{
|
||
+ http_querystring_object *o = (http_querystring_object *) object;
|
||
+
|
||
+ freeObject(o);
|
||
+}
|
||
+
|
||
+/* {{{ querystring helpers */
|
||
+#define http_querystring_instantiate(t, g, p, u) _http_querystring_instantiate((t), (g), (p), (u) TSRMLS_CC)
|
||
+static inline zval *_http_querystring_instantiate(zval *this_ptr, zend_bool global, zval *params, zend_bool defer_update TSRMLS_DC)
|
||
+{
|
||
+ zval *qarray = NULL, *qstring = NULL, **_SERVER = NULL, **_GET = NULL, **QUERY_STRING = NULL;;
|
||
+
|
||
+ if (!this_ptr) {
|
||
+ MAKE_STD_ZVAL(this_ptr);
|
||
+ Z_TYPE_P(this_ptr) = IS_OBJECT;
|
||
+ this_ptr->value.obj = http_querystring_object_new(http_querystring_object_ce);
|
||
+ }
|
||
+ if (global) {
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
|
||
+#endif
|
||
+ if ( (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &_SERVER)) &&
|
||
+ (Z_TYPE_PP(_SERVER) == IS_ARRAY) &&
|
||
+ (SUCCESS == zend_hash_find(Z_ARRVAL_PP(_SERVER), "QUERY_STRING", sizeof("QUERY_STRING"), (void *) &QUERY_STRING))) {
|
||
+
|
||
+ qstring = *QUERY_STRING;
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_is_auto_global("_GET", lenof("_GET") TSRMLS_CC);
|
||
+#endif
|
||
+ if ((SUCCESS == zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void *) &_GET)) && (Z_TYPE_PP(_GET) == IS_ARRAY)) {
|
||
+ qarray = *_GET;
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to superglobal GET array");
|
||
+ }
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to QUERY_STRING");
|
||
+ }
|
||
+
|
||
+ if (qarray && qstring) {
|
||
+ if (Z_TYPE_P(qstring) != IS_STRING) {
|
||
+ convert_to_string(qstring);
|
||
+ }
|
||
+
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC);
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, qstring TSRMLS_CC);
|
||
+#ifdef Z_SET_ISREF
|
||
+ Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC));
|
||
+ Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
|
||
+#else
|
||
+ zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)->is_ref = 1;
|
||
+ zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)->is_ref = 1;
|
||
+#endif
|
||
+
|
||
+ if (params) {
|
||
+ http_querystring_modify(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), params);
|
||
+ }
|
||
+ if (!defer_update) {
|
||
+ http_querystring_update(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ MAKE_STD_ZVAL(qarray);
|
||
+ array_init(qarray);
|
||
+
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC);
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryString")-1, "", 0 TSRMLS_CC);
|
||
+
|
||
+ if (params && http_querystring_modify(qarray, params) && !defer_update) {
|
||
+ http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
|
||
+ }
|
||
+
|
||
+ zval_ptr_dtor(&qarray);
|
||
+ }
|
||
+
|
||
+ return this_ptr;
|
||
+}
|
||
+
|
||
+#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC)
|
||
+static inline void _http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC)
|
||
+{
|
||
+ zval **arrval, *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if ((Z_TYPE_P(qarray) == IS_ARRAY) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), name, name_len + 1, (void *) &arrval))) {
|
||
+ if (type) {
|
||
+ zval *value = http_zsep(type, *arrval);
|
||
+ RETVAL_ZVAL(value, 1, 1);
|
||
+ } else {
|
||
+ RETVAL_ZVAL(*arrval, 1, 0);
|
||
+ }
|
||
+
|
||
+ if (del && (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), name, name_len + 1))) {
|
||
+ http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
|
||
+ }
|
||
+ } else if(defval) {
|
||
+ RETURN_ZVAL(defval, 1, 0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto final void HttpQueryString::__construct([bool global = true[, mixed add])
|
||
+ Creates a new HttpQueryString object instance. Operates on and modifies $_GET and $_SERVER['QUERY_STRING'] if global is TRUE. */
|
||
+PHP_METHOD(HttpQueryString, __construct)
|
||
+{
|
||
+ zend_bool global = 1;
|
||
+ zval *params = NULL;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (!sapi_module.treat_data) {
|
||
+ http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered");
|
||
+ } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bz", &global, ¶ms)) {
|
||
+ http_querystring_instantiate(getThis(), global, params, 0);
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpQueryString HttpQueryString::factory([bool global = TRUE[, mixed params[, string class_name = "HttpQueryString"])
|
||
+ Creates a new HttpQueryString object instance. */
|
||
+PHP_METHOD(HttpQueryString, factory)
|
||
+{
|
||
+ zend_bool global = 1;
|
||
+ zval *params = NULL;
|
||
+ char *cn = NULL;
|
||
+ int cl = 0;
|
||
+ zend_object_value ov;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (!sapi_module.treat_data) {
|
||
+ http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered");
|
||
+ } else if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bzs", &global, ¶ms, &cn, &cl) &&
|
||
+ SUCCESS == http_object_new(&ov, cn, cl, _http_querystring_object_new_ex, http_querystring_object_ce, NULL, NULL)) {
|
||
+ RETVAL_OBJVAL(ov, 0);
|
||
+ http_querystring_instantiate(return_value, global, params, 0);
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpQueryString::toString()
|
||
+ Returns the string representation. */
|
||
+PHP_METHOD(HttpQueryString, toString)
|
||
+{
|
||
+ NO_ARGS;
|
||
+ RETURN_PROP(queryString);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpQueryString::toArray()
|
||
+ Returns the array representation. */
|
||
+PHP_METHOD(HttpQueryString, toArray)
|
||
+{
|
||
+ NO_ARGS;
|
||
+ RETURN_PROP(queryArray);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto mixed HttpQueryString::get([string key[, mixed type = 0[, mixed defval = NULL[, bool delete = false]]]])
|
||
+ Get (part of) the query string. The type parameter is either one of the HttpQueryString::TYPE_* constants or a type abbreviation like "b" for bool, "i" for int, "f" for float, "s" for string, "a" for array and "o" for a stdClass object. */
|
||
+PHP_METHOD(HttpQueryString, get)
|
||
+{
|
||
+ char *name = NULL;
|
||
+ int name_len = 0;
|
||
+ long type = 0;
|
||
+ zend_bool del = 0;
|
||
+ zval *ztype = NULL, *defval = NULL;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szzb", &name, &name_len, &ztype, &defval, &del)) {
|
||
+ if (name && name_len) {
|
||
+ if (ztype) {
|
||
+ if (Z_TYPE_P(ztype) == IS_LONG) {
|
||
+ type = Z_LVAL_P(ztype);
|
||
+ } else if(Z_TYPE_P(ztype) == IS_STRING) {
|
||
+ switch (Z_STRVAL_P(ztype)[0]) {
|
||
+ case 'B':
|
||
+ case 'b': type = HTTP_QUERYSTRING_TYPE_BOOL; break;
|
||
+ case 'I':
|
||
+ case 'i': type = HTTP_QUERYSTRING_TYPE_INT; break;
|
||
+ case 'F':
|
||
+ case 'f': type = HTTP_QUERYSTRING_TYPE_FLOAT; break;
|
||
+ case 'S':
|
||
+ case 's': type = HTTP_QUERYSTRING_TYPE_STRING; break;
|
||
+ case 'A':
|
||
+ case 'a': type = HTTP_QUERYSTRING_TYPE_ARRAY; break;
|
||
+ case 'O':
|
||
+ case 'o': type = HTTP_QUERYSTRING_TYPE_OBJECT; break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ http_querystring_get(getThis(), type, name, name_len, defval, del, return_value);
|
||
+ } else {
|
||
+ RETURN_PROP(queryString);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpQueryString::set(mixed params)
|
||
+ Set query string entry/entries. NULL values will unset the variable. */
|
||
+PHP_METHOD(HttpQueryString, set)
|
||
+{
|
||
+ zval *params;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) {
|
||
+ zval *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
|
||
+ if (http_querystring_modify(qarray, params)) {
|
||
+ http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(queryString);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpQueryString HttpQueryString::mod(mixed params)
|
||
+ Copies the query string object and sets provided params at the clone. */
|
||
+PHP_METHOD(HttpQueryString, mod)
|
||
+{
|
||
+ zval *zobj, *qarr, *qstr, *params;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) {
|
||
+ zobj = http_querystring_instantiate(NULL, 0, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), 1);
|
||
+ qarr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
|
||
+ qstr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryString")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ http_querystring_modify(qarr, params);
|
||
+ http_querystring_update(qarr, qstr);
|
||
+
|
||
+ RETURN_ZVAL(zobj, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifndef WONKY
|
||
+/* {{{ proto static HttpQueryString HttpQueryString::singleton([bool global = true])
|
||
+ Get a single instance (differentiates between the global setting). */
|
||
+PHP_METHOD(HttpQueryString, singleton)
|
||
+{
|
||
+ zend_bool global = 1;
|
||
+ zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) {
|
||
+ zval **zobj_ptr = NULL, *zobj = NULL;
|
||
+
|
||
+ if (Z_TYPE_P(instance) == IS_ARRAY) {
|
||
+ if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) {
|
||
+ RETVAL_ZVAL(*zobj_ptr, 1, 0);
|
||
+ } else {
|
||
+ zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global);
|
||
+ add_index_zval(instance, global, zobj);
|
||
+ RETVAL_OBJECT(zobj, 1);
|
||
+ }
|
||
+ } else {
|
||
+ MAKE_STD_ZVAL(instance);
|
||
+ array_init(instance);
|
||
+
|
||
+ zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global);
|
||
+ add_index_zval(instance, global, zobj);
|
||
+ RETVAL_OBJECT(zobj, 1);
|
||
+
|
||
+ zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC);
|
||
+ zval_ptr_dtor(&instance);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+#endif
|
||
+
|
||
+/* {{{ Getters by type */
|
||
+#define HTTP_QUERYSTRING_GETTER(method, TYPE) \
|
||
+PHP_METHOD(HttpQueryString, method) \
|
||
+{ \
|
||
+ char *name; \
|
||
+ int name_len; \
|
||
+ zval *defval = NULL; \
|
||
+ zend_bool del = 0; \
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &name, &name_len, &defval, &del)) { \
|
||
+ http_querystring_get(getThis(), TYPE, name, name_len, defval, del, return_value); \
|
||
+ } \
|
||
+}
|
||
+HTTP_QUERYSTRING_GETTER(getBool, IS_BOOL);
|
||
+HTTP_QUERYSTRING_GETTER(getInt, IS_LONG);
|
||
+HTTP_QUERYSTRING_GETTER(getFloat, IS_DOUBLE);
|
||
+HTTP_QUERYSTRING_GETTER(getString, IS_STRING);
|
||
+HTTP_QUERYSTRING_GETTER(getArray, IS_ARRAY);
|
||
+HTTP_QUERYSTRING_GETTER(getObject, IS_OBJECT);
|
||
+/* }}} */
|
||
+
|
||
+#ifdef HTTP_HAVE_ICONV
|
||
+/* {{{ proto bool HttpQueryString::xlate(string ie, string oe)
|
||
+ Converts the query string from the source encoding ie to the target encoding oe. WARNING: Don't use any character set that can contain NUL bytes like UTF-16. */
|
||
+PHP_METHOD(HttpQueryString, xlate)
|
||
+{
|
||
+ char *ie, *oe;
|
||
+ int ie_len, oe_len;
|
||
+ zval xa, *qa, *qs;
|
||
+ STATUS rs;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ie, &ie_len, &oe, &oe_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ qa = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
|
||
+ qs = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC);
|
||
+ INIT_PZVAL(&xa);
|
||
+ array_init(&xa);
|
||
+
|
||
+ if (SUCCESS == (rs = http_querystring_xlate(&xa, qa, ie, oe))) {
|
||
+ zend_hash_clean(Z_ARRVAL_P(qa));
|
||
+ zend_hash_copy(Z_ARRVAL_P(qa), Z_ARRVAL(xa), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ http_querystring_update(qa, qs);
|
||
+ }
|
||
+ zval_dtor(&xa);
|
||
+
|
||
+ RETURN_SUCCESS(rs);
|
||
+}
|
||
+/* }}} */
|
||
+#endif /* HAVE_ICONV */
|
||
+
|
||
+/* {{{ proto string HttpQueryString::serialize()
|
||
+ Implements Serializable::serialize(). */
|
||
+PHP_METHOD(HttpQueryString, serialize)
|
||
+{
|
||
+ NO_ARGS;
|
||
+ RETURN_PROP(queryString);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpQueryString::unserialize(string serialized)
|
||
+ Implements Serializable::unserialize(). */
|
||
+PHP_METHOD(HttpQueryString, unserialize)
|
||
+{
|
||
+ zval *serialized;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &serialized)) {
|
||
+ if (Z_TYPE_P(serialized) == IS_STRING) {
|
||
+ http_querystring_instantiate(getThis(), 0, serialized, 0);
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Expected a string as parameter");
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto mixed HttpQueryString::offsetGet(string offset)
|
||
+ Implements ArrayAccess::offsetGet(). */
|
||
+PHP_METHOD(HttpQueryString, offsetGet)
|
||
+{
|
||
+ char *offset_str;
|
||
+ int offset_len;
|
||
+ zval **value;
|
||
+
|
||
+ if ( (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) &&
|
||
+ (SUCCESS == zend_hash_find(Z_ARRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)), offset_str, offset_len + 1, (void *) &value))) {
|
||
+ RETVAL_ZVAL(*value, 1, 0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpQueryString::offsetSet(string offset, mixed value)
|
||
+ Implements ArrayAccess::offsetGet(). */
|
||
+PHP_METHOD(HttpQueryString, offsetSet)
|
||
+{
|
||
+ char *offset_str;
|
||
+ int offset_len;
|
||
+ zval *value;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset_str, &offset_len, &value)) {
|
||
+ zval *qarr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), *qstr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ ZVAL_ADDREF(value);
|
||
+ add_assoc_zval_ex(qarr, offset_str, offset_len + 1, value);
|
||
+ http_querystring_update(qarr, qstr);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpQueryString::offsetExists(string offset)
|
||
+ Implements ArrayAccess::offsetExists(). */
|
||
+PHP_METHOD(HttpQueryString, offsetExists)
|
||
+{
|
||
+ char *offset_str;
|
||
+ int offset_len;
|
||
+ zval **value;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
|
||
+ RETURN_BOOL((SUCCESS == zend_hash_find(Z_ARRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)), offset_str, offset_len + 1, (void *) &value)) && (Z_TYPE_PP(value) != IS_NULL));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpQueryString::offsetUnset(string offset)
|
||
+ Implements ArrayAccess::offsetUnset(). */
|
||
+PHP_METHOD(HttpQueryString, offsetUnset)
|
||
+{
|
||
+ char *offset_str;
|
||
+ int offset_len;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
|
||
+ zval *qarr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarr), offset_str, offset_len + 1)) {
|
||
+ http_querystring_update(qarr, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_request_api.c
|
||
@@ -0,0 +1,1326 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_request_api.c 310775 2011-05-05 06:02:50Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_persistent_handle_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+# include "php_http_request_object.h"
|
||
+#endif
|
||
+
|
||
+#include "php_http_request_int.h"
|
||
+
|
||
+/* {{{ cruft for thread safe SSL crypto locks */
|
||
+#ifdef HTTP_NEED_OPENSSL_TSL
|
||
+static MUTEX_T *http_openssl_tsl = NULL;
|
||
+
|
||
+static void http_openssl_thread_lock(int mode, int n, const char * file, int line)
|
||
+{
|
||
+ if (mode & CRYPTO_LOCK) {
|
||
+ tsrm_mutex_lock(http_openssl_tsl[n]);
|
||
+ } else {
|
||
+ tsrm_mutex_unlock(http_openssl_tsl[n]);
|
||
+ }
|
||
+}
|
||
+
|
||
+static ulong http_openssl_thread_id(void)
|
||
+{
|
||
+ return (ulong) tsrm_thread_id();
|
||
+}
|
||
+#endif
|
||
+#ifdef HTTP_NEED_GNUTLS_TSL
|
||
+static int http_gnutls_mutex_create(void **m)
|
||
+{
|
||
+ if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
|
||
+ return SUCCESS;
|
||
+ } else {
|
||
+ return FAILURE;
|
||
+ }
|
||
+}
|
||
+
|
||
+static int http_gnutls_mutex_destroy(void **m)
|
||
+{
|
||
+ tsrm_mutex_free(*((MUTEX_T *) m));
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+static int http_gnutls_mutex_lock(void **m)
|
||
+{
|
||
+ return tsrm_mutex_lock(*((MUTEX_T *) m));
|
||
+}
|
||
+
|
||
+static int http_gnutls_mutex_unlock(void **m)
|
||
+{
|
||
+ return tsrm_mutex_unlock(*((MUTEX_T *) m));
|
||
+}
|
||
+
|
||
+static struct gcry_thread_cbs http_gnutls_tsl = {
|
||
+ GCRY_THREAD_OPTION_USER,
|
||
+ NULL,
|
||
+ http_gnutls_mutex_create,
|
||
+ http_gnutls_mutex_destroy,
|
||
+ http_gnutls_mutex_lock,
|
||
+ http_gnutls_mutex_unlock
|
||
+};
|
||
+#endif
|
||
+/* }}} */
|
||
+
|
||
+/* safe curl wrappers */
|
||
+#define init_curl_storage(ch) \
|
||
+ {\
|
||
+ http_request_storage *st = pecalloc(1, sizeof(http_request_storage), 1); \
|
||
+ curl_easy_setopt(ch, CURLOPT_PRIVATE, st); \
|
||
+ curl_easy_setopt(ch, CURLOPT_ERRORBUFFER, st->errorbuffer); \
|
||
+ }
|
||
+
|
||
+static void *safe_curl_init(void)
|
||
+{
|
||
+ CURL *ch;
|
||
+
|
||
+ if ((ch = curl_easy_init())) {
|
||
+ init_curl_storage(ch);
|
||
+ return ch;
|
||
+ }
|
||
+ return NULL;
|
||
+}
|
||
+static void *safe_curl_copy(void *p)
|
||
+{
|
||
+ CURL *ch;
|
||
+
|
||
+ if ((ch = curl_easy_duphandle(p))) {
|
||
+ init_curl_storage(ch);
|
||
+ return ch;
|
||
+ }
|
||
+ return NULL;
|
||
+}
|
||
+static void safe_curl_dtor(void *p) {
|
||
+ http_request_storage *st = http_request_storage_get(p);
|
||
+
|
||
+ curl_easy_cleanup(p);
|
||
+
|
||
+ if (st) {
|
||
+ if (st->url) {
|
||
+ pefree(st->url, 1);
|
||
+ }
|
||
+ if (st->cookiestore) {
|
||
+ pefree(st->cookiestore, 1);
|
||
+ }
|
||
+ pefree(st, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ MINIT */
|
||
+PHP_MINIT_FUNCTION(http_request)
|
||
+{
|
||
+#ifdef HTTP_NEED_OPENSSL_TSL
|
||
+ /* mod_ssl, libpq or ext/curl might already have set thread lock callbacks */
|
||
+ if (!CRYPTO_get_id_callback()) {
|
||
+ int i, c = CRYPTO_num_locks();
|
||
+
|
||
+ http_openssl_tsl = malloc(c * sizeof(MUTEX_T));
|
||
+
|
||
+ for (i = 0; i < c; ++i) {
|
||
+ http_openssl_tsl[i] = tsrm_mutex_alloc();
|
||
+ }
|
||
+
|
||
+ CRYPTO_set_id_callback(http_openssl_thread_id);
|
||
+ CRYPTO_set_locking_callback(http_openssl_thread_lock);
|
||
+ }
|
||
+#endif
|
||
+#ifdef HTTP_NEED_GNUTLS_TSL
|
||
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &http_gnutls_tsl);
|
||
+#endif
|
||
+
|
||
+ if (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (SUCCESS != http_persistent_handle_provide("http_request", safe_curl_init, safe_curl_dtor, safe_curl_copy)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC);
|
||
+ HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST);
|
||
+#if HTTP_CURL_VERSION(7,19,3)
|
||
+ HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST_IE", CURLAUTH_DIGEST_IE);
|
||
+#endif
|
||
+ HTTP_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM);
|
||
+ HTTP_LONG_CONSTANT("HTTP_AUTH_GSSNEG", CURLAUTH_GSSNEGOTIATE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_AUTH_ANY", CURLAUTH_ANY);
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_VERSION_NONE", CURL_HTTP_VERSION_NONE); /* to be removed */
|
||
+ HTTP_LONG_CONSTANT("HTTP_VERSION_1_0", CURL_HTTP_VERSION_1_0);
|
||
+ HTTP_LONG_CONSTANT("HTTP_VERSION_1_1", CURL_HTTP_VERSION_1_1);
|
||
+ HTTP_LONG_CONSTANT("HTTP_VERSION_ANY", CURL_HTTP_VERSION_NONE);
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_TLSv1", CURL_SSLVERSION_TLSv1);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv2", CURL_SSLVERSION_SSLv2);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv3", CURL_SSLVERSION_SSLv3);
|
||
+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_ANY", CURL_SSLVERSION_DEFAULT);
|
||
+
|
||
+ HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V4", CURL_IPRESOLVE_V4);
|
||
+ HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V6", CURL_IPRESOLVE_V6);
|
||
+ HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_ANY", CURL_IPRESOLVE_WHATEVER);
|
||
+
|
||
+#if HTTP_CURL_VERSION(7,15,2)
|
||
+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4", CURLPROXY_SOCKS4);
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,18,0)
|
||
+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4A", CURLPROXY_SOCKS4A);
|
||
+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5_HOSTNAME);
|
||
+#endif
|
||
+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5", CURLPROXY_SOCKS5);
|
||
+ HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP", CURLPROXY_HTTP);
|
||
+#if HTTP_CURL_VERSION(7,19,4)
|
||
+ HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP_1_0", CURLPROXY_HTTP_1_0);
|
||
+#endif
|
||
+
|
||
+#if HTTP_CURL_VERSION(7,19,1)
|
||
+ HTTP_LONG_CONSTANT("HTTP_POSTREDIR_301", CURL_REDIR_POST_301);
|
||
+ HTTP_LONG_CONSTANT("HTTP_POSTREDIR_302", CURL_REDIR_POST_302);
|
||
+ HTTP_LONG_CONSTANT("HTTP_POSTREDIR_ALL", CURL_REDIR_POST_ALL);
|
||
+#endif
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ MSHUTDOWN */
|
||
+PHP_MSHUTDOWN_FUNCTION(http_request)
|
||
+{
|
||
+ curl_global_cleanup();
|
||
+#ifdef HTTP_NEED_OPENSSL_TSL
|
||
+ if (http_openssl_tsl) {
|
||
+ int i, c = CRYPTO_num_locks();
|
||
+
|
||
+ CRYPTO_set_id_callback(NULL);
|
||
+ CRYPTO_set_locking_callback(NULL);
|
||
+
|
||
+ for (i = 0; i < c; ++i) {
|
||
+ tsrm_mutex_free(http_openssl_tsl[i]);
|
||
+ }
|
||
+
|
||
+ free(http_openssl_tsl);
|
||
+ http_openssl_tsl = NULL;
|
||
+ }
|
||
+#endif
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ forward declarations */
|
||
+#define http_request_option(r, o, k, t) _http_request_option_ex((r), (o), (k), sizeof(k), (t) TSRMLS_CC)
|
||
+#define http_request_option_ex(r, o, k, l, t) _http_request_option_ex((r), (o), (k), (l), (t) TSRMLS_CC)
|
||
+static inline zval *_http_request_option_ex(http_request *request, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC);
|
||
+#define http_request_option_cache(r, k, z) _http_request_option_cache_ex((r), (k), sizeof(k), 0, (z) TSRMLS_CC)
|
||
+#define http_request_option_cache_ex(r, k, kl, h, z) _http_request_option_cache_ex((r), (k), (kl), (h), (z) TSRMLS_CC)
|
||
+static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC);
|
||
+
|
||
+#define http_request_cookies_enabled(r) _http_request_cookies_enabled((r))
|
||
+static inline int _http_request_cookies_enabled(http_request *r);
|
||
+
|
||
+static size_t http_curl_read_callback(void *, size_t, size_t, void *);
|
||
+static int http_curl_progress_callback(void *, double, double, double, double);
|
||
+static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *);
|
||
+static int http_curl_dummy_callback(char *data, size_t n, size_t l, void *s) { return n*l; }
|
||
+static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *);
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ CURL *http_curl_init(http_request *) */
|
||
+PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC)
|
||
+{
|
||
+ if (ch || (SUCCESS == http_persistent_handle_acquire("http_request", &ch))) {
|
||
+#if defined(ZTS)
|
||
+ curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
|
||
+#endif
|
||
+ curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
|
||
+ curl_easy_setopt(ch, CURLOPT_FILETIME, 1L);
|
||
+ curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1L);
|
||
+ curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
|
||
+ curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, NULL);
|
||
+ curl_easy_setopt(ch, CURLOPT_DEBUGFUNCTION, http_curl_raw_callback);
|
||
+ curl_easy_setopt(ch, CURLOPT_READFUNCTION, http_curl_read_callback);
|
||
+ curl_easy_setopt(ch, CURLOPT_IOCTLFUNCTION, http_curl_ioctl_callback);
|
||
+ curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, http_curl_dummy_callback);
|
||
+
|
||
+ /* set context */
|
||
+ if (request) {
|
||
+ curl_easy_setopt(ch, CURLOPT_DEBUGDATA, request);
|
||
+
|
||
+ /* attach curl handle */
|
||
+ request->ch = ch;
|
||
+ /* set defaults (also in http_request_reset()) */
|
||
+ http_request_defaults(request);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return ch;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ CURL *http_curl_copy(CURL *) */
|
||
+PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC)
|
||
+{
|
||
+ CURL *copy;
|
||
+
|
||
+ if (SUCCESS == http_persistent_handle_accrete("http_request", ch, ©)) {
|
||
+ return copy;
|
||
+ }
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_curl_free(CURL **) */
|
||
+PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC)
|
||
+{
|
||
+ if (*ch) {
|
||
+ curl_easy_setopt(*ch, CURLOPT_NOPROGRESS, 1L);
|
||
+ curl_easy_setopt(*ch, CURLOPT_PROGRESSFUNCTION, NULL);
|
||
+ curl_easy_setopt(*ch, CURLOPT_VERBOSE, 0L);
|
||
+ curl_easy_setopt(*ch, CURLOPT_DEBUGFUNCTION, NULL);
|
||
+
|
||
+ http_persistent_handle_release("http_request", ch);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_request *http_request_init(http_request *) */
|
||
+PHP_HTTP_API http_request *_http_request_init_ex(http_request *request, CURL *ch, http_request_method meth, const char *url ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ http_request *r;
|
||
+
|
||
+ if (request) {
|
||
+ r = request;
|
||
+ } else {
|
||
+ r = emalloc_rel(sizeof(http_request));
|
||
+ }
|
||
+ memset(r, 0, sizeof(http_request));
|
||
+
|
||
+ r->ch = ch;
|
||
+ r->url = (url) ? http_absolute_url(url) : NULL;
|
||
+ r->meth = (meth > 0) ? meth : HTTP_GET;
|
||
+
|
||
+ phpstr_init(&r->conv.request);
|
||
+ phpstr_init_ex(&r->conv.response, HTTP_CURLBUF_SIZE, 0);
|
||
+ phpstr_init(&r->_cache.cookies);
|
||
+ zend_hash_init(&r->_cache.options, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+
|
||
+ TSRMLS_SET_CTX(r->tsrm_ls);
|
||
+
|
||
+ return r;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_dtor(http_request *) */
|
||
+PHP_HTTP_API void _http_request_dtor(http_request *request)
|
||
+{
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ http_request_reset(request);
|
||
+ http_curl_free(&request->ch);
|
||
+
|
||
+ phpstr_dtor(&request->_cache.cookies);
|
||
+ zend_hash_destroy(&request->_cache.options);
|
||
+ if (request->_cache.headers) {
|
||
+ curl_slist_free_all(request->_cache.headers);
|
||
+ request->_cache.headers = NULL;
|
||
+ }
|
||
+ if (request->_progress_callback) {
|
||
+ zval_ptr_dtor(&request->_progress_callback);
|
||
+ request->_progress_callback = NULL;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_free(http_request **) */
|
||
+PHP_HTTP_API void _http_request_free(http_request **request)
|
||
+{
|
||
+ if (*request) {
|
||
+ TSRMLS_FETCH_FROM_CTX((*request)->tsrm_ls);
|
||
+ http_request_body_free(&(*request)->body);
|
||
+ http_request_dtor(*request);
|
||
+ efree(*request);
|
||
+ *request = NULL;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_reset(http_request *) */
|
||
+PHP_HTTP_API void _http_request_reset(http_request *request)
|
||
+{
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+ STR_SET(request->url, NULL);
|
||
+ request->conv.last_type = 0;
|
||
+ phpstr_dtor(&request->conv.request);
|
||
+ phpstr_dtor(&request->conv.response);
|
||
+ http_request_body_dtor(request->body);
|
||
+ http_request_defaults(request);
|
||
+
|
||
+ if (request->ch) {
|
||
+ http_request_storage *st = http_request_storage_get(request->ch);
|
||
+
|
||
+ if (st) {
|
||
+ if (st->url) {
|
||
+ pefree(st->url, 1);
|
||
+ st->url = NULL;
|
||
+ }
|
||
+ if (st->cookiestore) {
|
||
+ pefree(st->cookiestore, 1);
|
||
+ st->cookiestore = NULL;
|
||
+ }
|
||
+ st->errorbuffer[0] = '\0';
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_request_enable_cookies(http_request *) */
|
||
+PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request)
|
||
+{
|
||
+ int initialized = 1;
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
|
||
+ if (initialized && (http_request_cookies_enabled(request) || (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIEFILE, "")))) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not enable cookies for this session");
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_request_reset_cookies(http_request *, int) */
|
||
+PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only)
|
||
+{
|
||
+ int initialized = 1;
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
|
||
+ if (initialized) {
|
||
+ if (!http_request_cookies_enabled(request)) {
|
||
+ if (SUCCESS != http_request_enable_cookies(request)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+ if (session_only) {
|
||
+#if HTTP_CURL_VERSION(7,15,4)
|
||
+ if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "SESS")) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset session cookies (need libcurl >= v7.15.4)");
|
||
+#endif
|
||
+ } else {
|
||
+#if HTTP_CURL_VERSION(7,14,1)
|
||
+ if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "ALL")) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset cookies (need libcurl >= v7.14.1)");
|
||
+#endif
|
||
+ }
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request)
|
||
+{
|
||
+ int initialized = 1;
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
|
||
+ if (initialized) {
|
||
+ if (!http_request_cookies_enabled(request)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+#if HTTP_CURL_VERSION(7,17,1)
|
||
+ if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "FLUSH")) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not flush cookies (need libcurl >= v7.17.1)");
|
||
+#endif
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+
|
||
+/* {{{ void http_request_defaults(http_request *) */
|
||
+PHP_HTTP_API void _http_request_defaults(http_request *request)
|
||
+{
|
||
+ if (request->ch) {
|
||
+ HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_URL, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1L);
|
||
+#if HTTP_CURL_VERSION(7,19,4)
|
||
+ HTTP_CURL_OPT(CURLOPT_NOPROXY, NULL);
|
||
+#endif
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXY, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYPORT, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYTYPE, 0L);
|
||
+ /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
|
||
+#if HTTP_CURL_VERSION(7,19,1)
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYUSERNAME, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYPASSWORD, NULL);
|
||
+#endif
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYAUTH, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, 60L);
|
||
+ HTTP_CURL_OPT(CURLOPT_IPRESOLVE, 0);
|
||
+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, 0L);
|
||
+#if HTTP_CURL_VERSION(7,15,5)
|
||
+ /* LFS weirdance
|
||
+ HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) 0);
|
||
+ HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) 0);
|
||
+ */
|
||
+#endif
|
||
+ /* crashes
|
||
+ HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, 5L); */
|
||
+ HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_INTERFACE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_PORT, 0L);
|
||
+#if HTTP_CURL_VERSION(7,19,0)
|
||
+ HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, 0L);
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,15,2)
|
||
+ HTTP_CURL_OPT(CURLOPT_LOCALPORT, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, 0L);
|
||
+#endif
|
||
+ /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
|
||
+#if HTTP_CURL_VERSION(7,19,1)
|
||
+ HTTP_CURL_OPT(CURLOPT_USERNAME, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_PASSWORD, NULL);
|
||
+#endif
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPAUTH, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_ENCODING, NULL);
|
||
+#if HTTP_CURL_VERSION(7,16,2)
|
||
+ /* we do this ourself anyway */
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTP_CONTENT_DECODING, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTP_TRANSFER_DECODING, 0L);
|
||
+#endif
|
||
+ HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, 0L);
|
||
+#if HTTP_CURL_VERSION(7,19,1)
|
||
+ HTTP_CURL_OPT(CURLOPT_POSTREDIR, 0L);
|
||
+#elif HTTP_CURL_VERSION(7,17,1)
|
||
+ HTTP_CURL_OPT(CURLOPT_POST301, 0L);
|
||
+#endif
|
||
+ HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_REFERER, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_USERAGENT, "PECL::HTTP/" PHP_HTTP_VERSION " (PHP/" PHP_VERSION ")");
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPHEADER, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 0L);
|
||
+ /* these options would enable curl's cookie engine by default which we don't want
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIEFILE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIEJAR, NULL); */
|
||
+#if HTTP_CURL_VERSION(7,14,1)
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIELIST, NULL);
|
||
+#endif
|
||
+ HTTP_CURL_OPT(CURLOPT_RANGE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_RESUME_FROM, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMECONDITION, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMEVALUE, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMEOUT, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, 3);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLCERT, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLCERTTYPE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLCERTPASSWD, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLKEY, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLKEYTYPE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLKEYPASSWD, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLENGINE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSLVERSION, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSL_VERIFYPEER, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSL_VERIFYHOST, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_SSL_CIPHER_LIST, NULL);
|
||
+#if HTTP_CURL_VERSION(7,19,0)
|
||
+ HTTP_CURL_OPT(CURLOPT_ISSUERCERT, NULL);
|
||
+ #if defined(HTTP_HAVE_OPENSSL)
|
||
+ HTTP_CURL_OPT(CURLOPT_CRLFILE, NULL);
|
||
+ #endif
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
|
||
+ HTTP_CURL_OPT(CURLOPT_CERTINFO, NULL);
|
||
+#endif
|
||
+#ifdef HTTP_CURL_CAINFO
|
||
+ HTTP_CURL_OPT(CURLOPT_CAINFO, HTTP_CURL_CAINFO);
|
||
+#else
|
||
+ HTTP_CURL_OPT(CURLOPT_CAINFO, NULL);
|
||
+#endif
|
||
+ HTTP_CURL_OPT(CURLOPT_CAPATH, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_RANDOM_FILE, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_EGDSOCKET, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_POSTFIELDS, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPPOST, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_IOCTLDATA, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_READDATA, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_INFILESIZE, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE);
|
||
+ HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_NOBODY, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_POST, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_UPLOAD, 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb)
|
||
+{
|
||
+ if (request->_progress_callback) {
|
||
+ zval_ptr_dtor(&request->_progress_callback);
|
||
+ }
|
||
+ if ((request->_progress_callback = cb)) {
|
||
+ ZVAL_ADDREF(cb);
|
||
+ HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 0);
|
||
+ HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, request);
|
||
+ HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, http_curl_progress_callback);
|
||
+ } else {
|
||
+ HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1);
|
||
+ HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, NULL);
|
||
+ HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* {{{ STATUS http_request_prepare(http_request *, HashTable *) */
|
||
+PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options)
|
||
+{
|
||
+ zval *zoption;
|
||
+ zend_bool range_req = 0;
|
||
+ http_request_storage *storage;
|
||
+
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init(request), return FAILURE);
|
||
+
|
||
+ if (!request->url) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ if (!(storage = http_request_storage_get(request->ch))) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ storage->errorbuffer[0] = '\0';
|
||
+ /* set options */
|
||
+ if (storage->url) {
|
||
+ pefree(storage->url, 1);
|
||
+ }
|
||
+ storage->url = pestrdup(request->url, 1);
|
||
+ HTTP_CURL_OPT(CURLOPT_URL, storage->url);
|
||
+
|
||
+ /* progress callback */
|
||
+ if ((zoption = http_request_option(request, options, "onprogress", -1))) {
|
||
+ http_request_set_progress_callback(request, zoption);
|
||
+ }
|
||
+
|
||
+ /* proxy */
|
||
+ if ((zoption = http_request_option(request, options, "proxyhost", IS_STRING))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXY, Z_STRVAL_P(zoption));
|
||
+ /* type */
|
||
+ if ((zoption = http_request_option(request, options, "proxytype", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYTYPE, Z_LVAL_P(zoption));
|
||
+ }
|
||
+ /* port */
|
||
+ if ((zoption = http_request_option(request, options, "proxyport", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
|
||
+ }
|
||
+ /* user:pass */
|
||
+ if ((zoption = http_request_option(request, options, "proxyauth", IS_STRING)) && Z_STRLEN_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
|
||
+ }
|
||
+ /* auth method */
|
||
+ if ((zoption = http_request_option(request, options, "proxyauthtype", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
|
||
+ }
|
||
+ /* tunnel */
|
||
+ if ((zoption = http_request_option(request, options, "proxytunnel", IS_BOOL)) && Z_BVAL_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 1L);
|
||
+ }
|
||
+ }
|
||
+#if HTTP_CURL_VERSION(7,19,4)
|
||
+ if ((zoption = http_request_option(request, options, "noproxy", IS_STRING))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_NOPROXY, Z_STRVAL_P(zoption));
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ /* dns */
|
||
+ if ((zoption = http_request_option(request, options, "dns_cache_timeout", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, Z_LVAL_P(zoption));
|
||
+ }
|
||
+ if ((zoption = http_request_option(request, options, "ipresolve", IS_LONG)) && Z_LVAL_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_IPRESOLVE, Z_LVAL_P(zoption));
|
||
+ }
|
||
+
|
||
+ /* limits */
|
||
+ if ((zoption = http_request_option(request, options, "low_speed_limit", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, Z_LVAL_P(zoption));
|
||
+ }
|
||
+ if ((zoption = http_request_option(request, options, "low_speed_time", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, Z_LVAL_P(zoption));
|
||
+ }
|
||
+#if HTTP_CURL_VERSION(7,15,5)
|
||
+ /* LSF weirdance
|
||
+ if ((zoption = http_request_option(request, options, "max_send_speed", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
|
||
+ }
|
||
+ if ((zoption = http_request_option(request, options, "max_recv_speed", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
|
||
+ }
|
||
+ */
|
||
+#endif
|
||
+ /* crashes
|
||
+ if ((zoption = http_request_option(request, options, "maxconnects", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, Z_LVAL_P(zoption));
|
||
+ } */
|
||
+ if ((zoption = http_request_option(request, options, "fresh_connect", IS_BOOL)) && Z_BVAL_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 1L);
|
||
+ }
|
||
+ if ((zoption = http_request_option(request, options, "forbid_reuse", IS_BOOL)) && Z_BVAL_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 1L);
|
||
+ }
|
||
+
|
||
+ /* outgoing interface */
|
||
+ if ((zoption = http_request_option(request, options, "interface", IS_STRING))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_INTERFACE, Z_STRVAL_P(zoption));
|
||
+
|
||
+#if HTTP_CURL_VERSION(7,15,2)
|
||
+ if ((zoption = http_request_option(request, options, "portrange", IS_ARRAY))) {
|
||
+ zval **prs, **pre;
|
||
+
|
||
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
|
||
+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &prs)) {
|
||
+ zend_hash_move_forward(Z_ARRVAL_P(zoption));
|
||
+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &pre)) {
|
||
+ zval *prs_cpy = http_zsep(IS_LONG, *prs);
|
||
+ zval *pre_cpy = http_zsep(IS_LONG, *pre);
|
||
+
|
||
+ if (Z_LVAL_P(prs_cpy) && Z_LVAL_P(pre_cpy)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_LOCALPORT, MIN(Z_LVAL_P(prs_cpy), Z_LVAL_P(pre_cpy)));
|
||
+ HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, labs(Z_LVAL_P(prs_cpy)-Z_LVAL_P(pre_cpy))+1L);
|
||
+ }
|
||
+ zval_ptr_dtor(&prs_cpy);
|
||
+ zval_ptr_dtor(&pre_cpy);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+ }
|
||
+
|
||
+ /* another port */
|
||
+ if ((zoption = http_request_option(request, options, "port", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_PORT, Z_LVAL_P(zoption));
|
||
+ }
|
||
+
|
||
+ /* RFC4007 zone_id */
|
||
+#if HTTP_CURL_VERSION(7,19,0)
|
||
+ if ((zoption = http_request_option(request, options, "address_scope", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, Z_LVAL_P(zoption));
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ /* auth */
|
||
+ if ((zoption = http_request_option(request, options, "httpauth", IS_STRING)) && Z_STRLEN_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_USERPWD, Z_STRVAL_P(zoption));
|
||
+ }
|
||
+ if ((zoption = http_request_option(request, options, "httpauthtype", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPAUTH, Z_LVAL_P(zoption));
|
||
+ }
|
||
+
|
||
+ /* redirects, defaults to 0 */
|
||
+ if ((zoption = http_request_option(request, options, "redirect", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1L : 0L);
|
||
+ HTTP_CURL_OPT(CURLOPT_MAXREDIRS, Z_LVAL_P(zoption));
|
||
+ if ((zoption = http_request_option(request, options, "unrestrictedauth", IS_BOOL))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, Z_LVAL_P(zoption));
|
||
+ }
|
||
+#if HTTP_CURL_VERSION(7,17,1)
|
||
+ if ((zoption = http_request_option(request, options, "postredir", IS_BOOL))) {
|
||
+# if HTTP_CURL_VERSION(7,19,1)
|
||
+ HTTP_CURL_OPT(CURLOPT_POSTREDIR, Z_BVAL_P(zoption) ? 1L : 0L);
|
||
+# else
|
||
+ HTTP_CURL_OPT(CURLOPT_POST301, Z_BVAL_P(zoption) ? 1L : 0L);
|
||
+# endif
|
||
+ }
|
||
+#endif
|
||
+ }
|
||
+
|
||
+ /* retries, defaults to 0 */
|
||
+ if ((zoption = http_request_option(request, options, "retrycount", IS_LONG))) {
|
||
+ request->_retry.count = Z_LVAL_P(zoption);
|
||
+ if ((zoption = http_request_option(request, options, "retrydelay", IS_DOUBLE))) {
|
||
+ request->_retry.delay = Z_DVAL_P(zoption);
|
||
+ } else {
|
||
+ request->_retry.delay = 0;
|
||
+ }
|
||
+ } else {
|
||
+ request->_retry.count = 0;
|
||
+ }
|
||
+
|
||
+ /* referer */
|
||
+ if ((zoption = http_request_option(request, options, "referer", IS_STRING)) && Z_STRLEN_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_REFERER, Z_STRVAL_P(zoption));
|
||
+ }
|
||
+
|
||
+ /* useragent, default "PECL::HTTP/version (PHP/version)" */
|
||
+ if ((zoption = http_request_option(request, options, "useragent", IS_STRING))) {
|
||
+ /* allow to send no user agent, not even default one */
|
||
+ if (Z_STRLEN_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_USERAGENT, Z_STRVAL_P(zoption));
|
||
+ } else {
|
||
+ HTTP_CURL_OPT(CURLOPT_USERAGENT, NULL);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* resume */
|
||
+ if ((zoption = http_request_option(request, options, "resume", IS_LONG)) && (Z_LVAL_P(zoption) > 0)) {
|
||
+ range_req = 1;
|
||
+ HTTP_CURL_OPT(CURLOPT_RESUME_FROM, Z_LVAL_P(zoption));
|
||
+ }
|
||
+ /* or range of kind array(array(0,499), array(100,1499)) */
|
||
+ else if ((zoption = http_request_option(request, options, "range", IS_ARRAY)) && zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
|
||
+ HashPosition pos1, pos2;
|
||
+ zval **rr, **rb, **re;
|
||
+ phpstr rs;
|
||
+
|
||
+ phpstr_init(&rs);
|
||
+ FOREACH_VAL(pos1, zoption, rr) {
|
||
+ if (Z_TYPE_PP(rr) == IS_ARRAY) {
|
||
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(rr), &pos2);
|
||
+ if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &rb, &pos2)) {
|
||
+ zend_hash_move_forward_ex(Z_ARRVAL_PP(rr), &pos2);
|
||
+ if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &re, &pos2)) {
|
||
+ if ( ((Z_TYPE_PP(rb) == IS_LONG) || ((Z_TYPE_PP(rb) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(rb), Z_STRLEN_PP(rb), NULL, NULL, 1))) &&
|
||
+ ((Z_TYPE_PP(re) == IS_LONG) || ((Z_TYPE_PP(re) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(re), Z_STRLEN_PP(re), NULL, NULL, 1)))) {
|
||
+ zval *rbl = http_zsep(IS_LONG, *rb);
|
||
+ zval *rel = http_zsep(IS_LONG, *re);
|
||
+
|
||
+ if ((Z_LVAL_P(rbl) >= 0) && (Z_LVAL_P(rel) >= 0)) {
|
||
+ phpstr_appendf(&rs, "%ld-%ld,", Z_LVAL_P(rbl), Z_LVAL_P(rel));
|
||
+ }
|
||
+ zval_ptr_dtor(&rbl);
|
||
+ zval_ptr_dtor(&rel);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (PHPSTR_LEN(&rs)) {
|
||
+ zval *cached_range;
|
||
+
|
||
+ /* ditch last comma */
|
||
+ PHPSTR_VAL(&rs)[PHPSTR_LEN(&rs)-- -1] = '\0';
|
||
+ /* cache string */
|
||
+ MAKE_STD_ZVAL(cached_range);
|
||
+ ZVAL_STRINGL(cached_range, PHPSTR_VAL(&rs), PHPSTR_LEN(&rs), 0);
|
||
+ HTTP_CURL_OPT(CURLOPT_RANGE, Z_STRVAL_P(http_request_option_cache(request, "range", cached_range)));
|
||
+ zval_ptr_dtor(&cached_range);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* additional headers, array('name' => 'value') */
|
||
+ if (request->_cache.headers) {
|
||
+ curl_slist_free_all(request->_cache.headers);
|
||
+ request->_cache.headers = NULL;
|
||
+ }
|
||
+ if ((zoption = http_request_option(request, options, "headers", IS_ARRAY))) {
|
||
+ HashKey header_key = initHashKey(0);
|
||
+ zval **header_val;
|
||
+ HashPosition pos;
|
||
+ phpstr header;
|
||
+
|
||
+ phpstr_init(&header);
|
||
+ FOREACH_KEYVAL(pos, zoption, header_key, header_val) {
|
||
+ if (header_key.type == HASH_KEY_IS_STRING) {
|
||
+ zval *header_cpy = http_zsep(IS_STRING, *header_val);
|
||
+
|
||
+ if (!strcasecmp(header_key.str, "range")) {
|
||
+ range_req = 1;
|
||
+ }
|
||
+
|
||
+ phpstr_appendf(&header, "%s: %s", header_key.str, Z_STRVAL_P(header_cpy));
|
||
+ phpstr_fix(&header);
|
||
+ request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header));
|
||
+ phpstr_reset(&header);
|
||
+
|
||
+ zval_ptr_dtor(&header_cpy);
|
||
+ }
|
||
+ }
|
||
+ phpstr_dtor(&header);
|
||
+ }
|
||
+ /* etag */
|
||
+ if ((zoption = http_request_option(request, options, "etag", IS_STRING)) && Z_STRLEN_P(zoption)) {
|
||
+ zend_bool is_quoted = !((Z_STRVAL_P(zoption)[0] != '"') || (Z_STRVAL_P(zoption)[Z_STRLEN_P(zoption)-1] != '"'));
|
||
+ phpstr header;
|
||
+
|
||
+ phpstr_init(&header);
|
||
+ phpstr_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", range_req?"If-Match":"If-None-Match", Z_STRVAL_P(zoption));
|
||
+ phpstr_fix(&header);
|
||
+ request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header));
|
||
+ phpstr_dtor(&header);
|
||
+ }
|
||
+ /* compression */
|
||
+ if ((zoption = http_request_option(request, options, "compress", IS_BOOL)) && Z_LVAL_P(zoption)) {
|
||
+ request->_cache.headers = curl_slist_append(request->_cache.headers, "Accept-Encoding: gzip;q=1.0,deflate;q=0.5");
|
||
+ }
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPHEADER, request->_cache.headers);
|
||
+
|
||
+ /* lastmodified */
|
||
+ if ((zoption = http_request_option(request, options, "lastmodified", IS_LONG))) {
|
||
+ if (Z_LVAL_P(zoption)) {
|
||
+ if (Z_LVAL_P(zoption) > 0) {
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMEVALUE, Z_LVAL_P(zoption));
|
||
+ } else {
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMEVALUE, (long) HTTP_G->request.time + Z_LVAL_P(zoption));
|
||
+ }
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMECONDITION, (long) (range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE));
|
||
+ } else {
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* cookies, array('name' => 'value') */
|
||
+ if ((zoption = http_request_option(request, options, "cookies", IS_ARRAY))) {
|
||
+ phpstr_dtor(&request->_cache.cookies);
|
||
+ if (zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
|
||
+ zval *urlenc_cookies = NULL;
|
||
+ /* check whether cookies should not be urlencoded; default is to urlencode them */
|
||
+ if ((!(urlenc_cookies = http_request_option(request, options, "encodecookies", IS_BOOL))) || Z_BVAL_P(urlenc_cookies)) {
|
||
+ if (SUCCESS == http_urlencode_hash_recursive(HASH_OF(zoption), &request->_cache.cookies, "; ", lenof("; "), NULL, 0)) {
|
||
+ phpstr_fix(&request->_cache.cookies);
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIE, request->_cache.cookies.data);
|
||
+ }
|
||
+ } else {
|
||
+ HashPosition pos;
|
||
+ HashKey cookie_key = initHashKey(0);
|
||
+ zval **cookie_val;
|
||
+
|
||
+ FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) {
|
||
+ if (cookie_key.type == HASH_KEY_IS_STRING) {
|
||
+ zval *val = http_zsep(IS_STRING, *cookie_val);
|
||
+ phpstr_appendf(&request->_cache.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val));
|
||
+ zval_ptr_dtor(&val);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ phpstr_fix(&request->_cache.cookies);
|
||
+ if (PHPSTR_LEN(&request->_cache.cookies)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIE, PHPSTR_VAL(&request->_cache.cookies));
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* don't load session cookies from cookiestore */
|
||
+ if ((zoption = http_request_option(request, options, "cookiesession", IS_BOOL)) && Z_BVAL_P(zoption)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 1L);
|
||
+ }
|
||
+
|
||
+ /* cookiestore, read initial cookies from that file and store cookies back into that file */
|
||
+ if ((zoption = http_request_option(request, options, "cookiestore", IS_STRING))) {
|
||
+ if (Z_STRLEN_P(zoption)) {
|
||
+ HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(zoption), return FAILURE);
|
||
+ }
|
||
+ if (storage->cookiestore) {
|
||
+ pefree(storage->cookiestore, 1);
|
||
+ }
|
||
+ storage->cookiestore = pestrndup(Z_STRVAL_P(zoption), Z_STRLEN_P(zoption), 1);
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIEFILE, storage->cookiestore);
|
||
+ HTTP_CURL_OPT(CURLOPT_COOKIEJAR, storage->cookiestore);
|
||
+ }
|
||
+
|
||
+ /* maxfilesize */
|
||
+ if ((zoption = http_request_option(request, options, "maxfilesize", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, Z_LVAL_P(zoption));
|
||
+ }
|
||
+
|
||
+ /* http protocol */
|
||
+ if ((zoption = http_request_option(request, options, "protocol", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, Z_LVAL_P(zoption));
|
||
+ }
|
||
+
|
||
+#if HTTP_CURL_VERSION(7,16,2)
|
||
+ /* timeout, defaults to 0 */
|
||
+ if ((zoption = http_request_option(request, options, "timeout", IS_DOUBLE))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000));
|
||
+ }
|
||
+ /* connecttimeout, defaults to 0 */
|
||
+ if ((zoption = http_request_option(request, options, "connecttimeout", IS_DOUBLE))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000));
|
||
+ }
|
||
+#else
|
||
+ /* timeout, defaults to 0 */
|
||
+ if ((zoption = http_request_option(request, options, "timeout", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_TIMEOUT, Z_LVAL_P(zoption));
|
||
+ }
|
||
+ /* connecttimeout, defaults to 0 */
|
||
+ if ((zoption = http_request_option(request, options, "connecttimeout", IS_LONG))) {
|
||
+ HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, Z_LVAL_P(zoption));
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ /* ssl */
|
||
+ if ((zoption = http_request_option(request, options, "ssl", IS_ARRAY))) {
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **param;
|
||
+ HashPosition pos;
|
||
+
|
||
+ FOREACH_KEYVAL(pos, zoption, key, param) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSLCERT, 0, 1);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTTYPE, 0, 0);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTPASSWD, 0, 0);
|
||
+
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSLKEY, 0, 0);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYTYPE, 0, 0);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYPASSWD, 0, 0);
|
||
+
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSLENGINE, 0, 0);
|
||
+ HTTP_CURL_OPT_LONG(CURLOPT_SSLVERSION, 0);
|
||
+
|
||
+ HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYPEER, 1);
|
||
+ HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYHOST, 1);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_SSL_CIPHER_LIST, 1, 0);
|
||
+
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_CAINFO, -3, 1);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_CAPATH, -3, 1);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_RANDOM_FILE, -3, 1);
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_EGDSOCKET, -3, 1);
|
||
+#if HTTP_CURL_VERSION(7,19,0)
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_ISSUERCERT, -3, 1);
|
||
+ #if defined(HTTP_HAVE_OPENSSL)
|
||
+ HTTP_CURL_OPT_STRING(CURLOPT_CRLFILE, -3, 1);
|
||
+ #endif
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
|
||
+ HTTP_CURL_OPT_LONG(CURLOPT_CERTINFO, -3);
|
||
+#endif
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* request method */
|
||
+ switch (request->meth) {
|
||
+ case HTTP_GET:
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L);
|
||
+ break;
|
||
+
|
||
+ case HTTP_HEAD:
|
||
+ HTTP_CURL_OPT(CURLOPT_NOBODY, 1L);
|
||
+ break;
|
||
+
|
||
+ case HTTP_POST:
|
||
+ HTTP_CURL_OPT(CURLOPT_POST, 1L);
|
||
+ break;
|
||
+
|
||
+ case HTTP_PUT:
|
||
+ HTTP_CURL_OPT(CURLOPT_UPLOAD, 1L);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ if (http_request_method_exists(0, request->meth, NULL)) {
|
||
+ HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, http_request_method_name(request->meth));
|
||
+ } else {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unsupported request method: %d (%s)", request->meth, request->url);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ /* attach request body */
|
||
+ if (request->body && (request->meth != HTTP_GET) && (request->meth != HTTP_HEAD) && (request->meth != HTTP_OPTIONS)) {
|
||
+ switch (request->body->type) {
|
||
+ case HTTP_REQUEST_BODY_EMPTY:
|
||
+ /* nothing */
|
||
+ break;
|
||
+
|
||
+ case HTTP_REQUEST_BODY_CURLPOST:
|
||
+ HTTP_CURL_OPT(CURLOPT_HTTPPOST, (struct curl_httppost *) request->body->data);
|
||
+ break;
|
||
+
|
||
+ case HTTP_REQUEST_BODY_CSTRING:
|
||
+ if (request->meth != HTTP_PUT) {
|
||
+ HTTP_CURL_OPT(CURLOPT_POSTFIELDS, request->body->data);
|
||
+ HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, request->body->size);
|
||
+ break;
|
||
+ }
|
||
+ /* fallthrough, PUT/UPLOAD _needs_ READDATA */
|
||
+ case HTTP_REQUEST_BODY_UPLOADFILE:
|
||
+ HTTP_CURL_OPT(CURLOPT_IOCTLDATA, request);
|
||
+ HTTP_CURL_OPT(CURLOPT_READDATA, request);
|
||
+ HTTP_CURL_OPT(CURLOPT_INFILESIZE, request->body->size);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ /* shouldn't ever happen */
|
||
+ http_error_ex(HE_ERROR, 0, "Unknown request body type: %d (%s)", request->body->type, request->url);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_exec(http_request *) */
|
||
+PHP_HTTP_API void _http_request_exec(http_request *request)
|
||
+{
|
||
+ uint tries = 0;
|
||
+ CURLcode result;
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+retry:
|
||
+ if (CURLE_OK != (result = curl_easy_perform(request->ch))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(result), http_request_storage_get(request->ch)->errorbuffer, request->url);
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ if ((HTTP_G->only_exceptions || GLOBAL_ERROR_HANDLING == EH_THROW) && EG(exception)) {
|
||
+ add_property_long(EG(exception), "curlCode", result);
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if (request->_retry.count > tries++) {
|
||
+ switch (result) {
|
||
+ case CURLE_COULDNT_RESOLVE_PROXY:
|
||
+ case CURLE_COULDNT_RESOLVE_HOST:
|
||
+ case CURLE_COULDNT_CONNECT:
|
||
+ case CURLE_WRITE_ERROR:
|
||
+ case CURLE_READ_ERROR:
|
||
+ case CURLE_OPERATION_TIMEDOUT:
|
||
+ case CURLE_SSL_CONNECT_ERROR:
|
||
+ case CURLE_GOT_NOTHING:
|
||
+ case CURLE_SSL_ENGINE_SETFAILED:
|
||
+ case CURLE_SEND_ERROR:
|
||
+ case CURLE_RECV_ERROR:
|
||
+ case CURLE_SSL_ENGINE_INITFAILED:
|
||
+ case CURLE_LOGIN_DENIED:
|
||
+ if (request->_retry.delay >= HTTP_DIFFSEC) {
|
||
+ http_sleep(request->_retry.delay);
|
||
+ }
|
||
+ goto retry;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static size_t http_curl_read_callback(void *, size_t, size_t, void *) */
|
||
+static size_t http_curl_read_callback(void *data, size_t len, size_t n, void *ctx)
|
||
+{
|
||
+ http_request *request = (http_request *) ctx;
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ if (request->body) {
|
||
+ switch (request->body->type) {
|
||
+ case HTTP_REQUEST_BODY_CSTRING:
|
||
+ {
|
||
+ size_t out = MIN(len * n, request->body->size - request->body->priv);
|
||
+
|
||
+ if (out) {
|
||
+ memcpy(data, ((char *) request->body->data) + request->body->priv, out);
|
||
+ request->body->priv += out;
|
||
+ return out;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case HTTP_REQUEST_BODY_UPLOADFILE:
|
||
+ return php_stream_read((php_stream *) request->body->data, data, len * n);
|
||
+ }
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static int http_curl_progress_callback(void *, double, double, double, double) */
|
||
+static int http_curl_progress_callback(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow)
|
||
+{
|
||
+ zval *param, retval;
|
||
+ http_request *request = (http_request *) ctx;
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ INIT_PZVAL(&retval);
|
||
+ ZVAL_NULL(&retval);
|
||
+
|
||
+ MAKE_STD_ZVAL(param);
|
||
+ array_init(param);
|
||
+ add_assoc_double(param, "dltotal", dltotal);
|
||
+ add_assoc_double(param, "dlnow", dlnow);
|
||
+ add_assoc_double(param, "ultotal", ultotal);
|
||
+ add_assoc_double(param, "ulnow", ulnow);
|
||
+
|
||
+ with_error_handling(EH_NORMAL, NULL) {
|
||
+ request->_in_progress_cb = 1;
|
||
+ call_user_function(EG(function_table), NULL, request->_progress_callback, &retval, 1, ¶m TSRMLS_CC);
|
||
+ request->_in_progress_cb = 0;
|
||
+ } end_error_handling();
|
||
+
|
||
+ zval_ptr_dtor(¶m);
|
||
+ zval_dtor(&retval);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *) */
|
||
+static curlioerr http_curl_ioctl_callback(CURL *ch, curliocmd cmd, void *ctx)
|
||
+{
|
||
+ http_request *request = (http_request *) ctx;
|
||
+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
|
||
+
|
||
+ if (cmd != CURLIOCMD_RESTARTREAD) {
|
||
+ return CURLIOE_UNKNOWNCMD;
|
||
+ }
|
||
+
|
||
+ if (request->body) {
|
||
+ switch (request->body->type) {
|
||
+ case HTTP_REQUEST_BODY_CSTRING:
|
||
+ request->body->priv = 0;
|
||
+ return CURLIOE_OK;
|
||
+ break;
|
||
+
|
||
+ case HTTP_REQUEST_BODY_UPLOADFILE:
|
||
+ if (SUCCESS == php_stream_rewind((php_stream *) request->body->data)) {
|
||
+ return CURLIOE_OK;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return CURLIOE_FAILRESTART;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *) */
|
||
+static int http_curl_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx)
|
||
+{
|
||
+ http_request *request = (http_request *) ctx;
|
||
+
|
||
+#define EMPTY_HEADER(d, l) (!l || (l == 1 && d[0] == '\n') || (l == 2 && d[0] == '\r' && d[1] == '\n'))
|
||
+ switch (type) {
|
||
+ case CURLINFO_DATA_IN:
|
||
+ if (request->conv.last_type == CURLINFO_HEADER_IN) {
|
||
+ phpstr_appends(&request->conv.response, HTTP_CRLF);
|
||
+ }
|
||
+ phpstr_append(&request->conv.response, data, length);
|
||
+ break;
|
||
+ case CURLINFO_HEADER_IN:
|
||
+ if (!EMPTY_HEADER(data, length)) {
|
||
+ phpstr_append(&request->conv.response, data, length);
|
||
+ }
|
||
+ break;
|
||
+ case CURLINFO_DATA_OUT:
|
||
+ case CURLINFO_HEADER_OUT:
|
||
+ phpstr_append(&request->conv.request, data, length);
|
||
+ break;
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+
|
||
+#if 0
|
||
+ {
|
||
+ const char _sym[] = "><><><";
|
||
+ if (type) {
|
||
+ for (fprintf(stderr, "%c ", _sym[type-1]); length--; data++) {
|
||
+ fprintf(stderr, HTTP_IS_CTYPE(print, *data)?"%c":"\\x%02X", (int) *data);
|
||
+ if (*data == '\n' && length) {
|
||
+ fprintf(stderr, "\n%c ", _sym[type-1]);
|
||
+ }
|
||
+ }
|
||
+ fprintf(stderr, "\n");
|
||
+ } else {
|
||
+ fprintf(stderr, "# %s", data);
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if (type) {
|
||
+ request->conv.last_type = type;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static inline zval *http_request_option(http_request *, HashTable *, char *, size_t, int) */
|
||
+static inline zval *_http_request_option_ex(http_request *r, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC)
|
||
+{
|
||
+ if (options) {
|
||
+ zval **zoption;
|
||
+ ulong h = zend_hash_func(key, keylen);
|
||
+
|
||
+ if (SUCCESS == zend_hash_quick_find(options, key, keylen, h, (void *) &zoption)) {
|
||
+ zval *option, *cached;
|
||
+
|
||
+ option = http_zsep(type, *zoption);
|
||
+ cached = http_request_option_cache_ex(r, key, keylen, h, option);
|
||
+
|
||
+ zval_ptr_dtor(&option);
|
||
+ return cached;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static inline zval *http_request_option_cache(http_request *, char *key, zval *) */
|
||
+static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC)
|
||
+{
|
||
+ ZVAL_ADDREF(opt);
|
||
+
|
||
+ if (h) {
|
||
+ zend_hash_quick_update(&r->_cache.options, key, keylen, h, &opt, sizeof(zval *), NULL);
|
||
+ } else {
|
||
+ zend_hash_update(&r->_cache.options, key, keylen, &opt, sizeof(zval *), NULL);
|
||
+ }
|
||
+
|
||
+ return opt;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static inline int http_request_cookies_enabled(http_request *) */
|
||
+static inline int _http_request_cookies_enabled(http_request *request) {
|
||
+ http_request_storage *st;
|
||
+
|
||
+ if (request->ch && (st = http_request_storage_get(request->ch)) && st->cookiestore) {
|
||
+ /* cookies are enabled */
|
||
+ return 1;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* HTTP_HAVE_CURL */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_request_body_api.c
|
||
@@ -0,0 +1,332 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_request_body_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+#include "php_http_request_body_api.h"
|
||
+
|
||
+/* {{{ */
|
||
+typedef struct curl_httppost *post_data[2];
|
||
+static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC);
|
||
+static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC);
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_request_body *http_request_body_new() */
|
||
+PHP_HTTP_API http_request_body *_http_request_body_init_ex(http_request_body *body, int type, void *data, size_t size, zend_bool free ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ if (!body) {
|
||
+ body = emalloc_rel(sizeof(http_request_body));
|
||
+ }
|
||
+
|
||
+ body->type = type;
|
||
+ body->free = free;
|
||
+ body->priv = 0;
|
||
+ body->data = data;
|
||
+ body->size = size;
|
||
+
|
||
+ return body;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_request_body *http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */
|
||
+PHP_HTTP_API http_request_body *_http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
|
||
+{
|
||
+ if (files && (zend_hash_num_elements(files) > 0)) {
|
||
+ struct curl_httppost *http_post_data[2] = {NULL, NULL};
|
||
+
|
||
+ if (fields && SUCCESS != recursive_fields(http_post_data, fields, NULL TSRMLS_CC)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ if (SUCCESS != recursive_files(http_post_data, files, NULL TSRMLS_CC)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CURLPOST, http_post_data[0], 0, 1);
|
||
+ } else if (fields) {
|
||
+ char *encoded;
|
||
+ size_t encoded_len;
|
||
+
|
||
+ if (SUCCESS != http_urlencode_hash_ex(fields, 1, NULL, 0, &encoded, &encoded_len)) {
|
||
+ http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post data");
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, encoded, encoded_len, 1);
|
||
+ } else {
|
||
+ return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, estrndup("", 0), 0, 1);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* STATUS http_request_body_encode(http_request_body *, char**, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC)
|
||
+{
|
||
+ switch (body->type) {
|
||
+ case HTTP_REQUEST_BODY_CURLPOST:
|
||
+ {
|
||
+#ifdef HAVE_CURL_FORMGET
|
||
+ phpstr str;
|
||
+
|
||
+ phpstr_init_ex(&str, 0x8000, 0);
|
||
+ if (curl_formget(body->data, &str, (curl_formget_callback) phpstr_append)) {
|
||
+ phpstr_dtor(&str);
|
||
+ } else {
|
||
+ phpstr_fix(&str);
|
||
+ *buf = PHPSTR_VAL(&str);
|
||
+ *len = PHPSTR_LEN(&str);
|
||
+ return SUCCESS;
|
||
+ }
|
||
+#endif
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case HTTP_REQUEST_BODY_CSTRING:
|
||
+ *buf = estrndup(body->data, *len = body->size);
|
||
+ return SUCCESS;
|
||
+
|
||
+ default:
|
||
+ break;
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_body_dtor(http_request_body *) */
|
||
+PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC)
|
||
+{
|
||
+ if (body) {
|
||
+ if (body->free) {
|
||
+ switch (body->type) {
|
||
+ case HTTP_REQUEST_BODY_CSTRING:
|
||
+ if (body->data) {
|
||
+ efree(body->data);
|
||
+ }
|
||
+ break;
|
||
+
|
||
+ case HTTP_REQUEST_BODY_CURLPOST:
|
||
+ curl_formfree(body->data);
|
||
+ break;
|
||
+
|
||
+ case HTTP_REQUEST_BODY_UPLOADFILE:
|
||
+ php_stream_close(body->data);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ memset(body, 0, sizeof(http_request_body));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_body_free(http_request_body *) */
|
||
+PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC)
|
||
+{
|
||
+ if (*body) {
|
||
+ http_request_body_dtor(*body);
|
||
+ efree(*body);
|
||
+ *body = NULL;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+static inline char *format_key(uint type, char *str, ulong num, const char *prefix, int numeric_key_for_empty_prefix) {
|
||
+ char *new_key = NULL;
|
||
+
|
||
+ if (prefix && *prefix) {
|
||
+ if (type == HASH_KEY_IS_STRING) {
|
||
+ spprintf(&new_key, 0, "%s[%s]", prefix, str);
|
||
+ } else {
|
||
+ spprintf(&new_key, 0, "%s[%lu]", prefix, num);
|
||
+ }
|
||
+ } else if (type == HASH_KEY_IS_STRING) {
|
||
+ new_key = estrdup(str);
|
||
+ } else if (numeric_key_for_empty_prefix) {
|
||
+ spprintf(&new_key, 0, "%lu", num);
|
||
+ }
|
||
+
|
||
+ return new_key;
|
||
+}
|
||
+
|
||
+/* {{{ static STATUS recursive_fields(post_data d, HashTable *f, const char *p TSRMLS_DC) */
|
||
+static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC) {
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **data_ptr;
|
||
+ HashPosition pos;
|
||
+ char *new_key = NULL;
|
||
+ CURLcode err = 0;
|
||
+
|
||
+ if (fields && !fields->nApplyCount) {
|
||
+ FOREACH_HASH_KEYVAL(pos, fields, key, data_ptr) {
|
||
+ if (key.type != HASH_KEY_IS_STRING || *key.str) {
|
||
+ new_key = format_key(key.type, key.str, key.num, prefix, 1);
|
||
+
|
||
+ switch (Z_TYPE_PP(data_ptr)) {
|
||
+ case IS_ARRAY:
|
||
+ case IS_OBJECT: {
|
||
+ STATUS status;
|
||
+
|
||
+ ++fields->nApplyCount;
|
||
+ status = recursive_fields(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC);
|
||
+ --fields->nApplyCount;
|
||
+
|
||
+ if (SUCCESS != status) {
|
||
+ goto error;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ default: {
|
||
+ zval *data = http_zsep(IS_STRING, *data_ptr);
|
||
+
|
||
+ err = curl_formadd(&http_post_data[0], &http_post_data[1],
|
||
+ CURLFORM_COPYNAME, new_key,
|
||
+ CURLFORM_COPYCONTENTS, Z_STRVAL_P(data),
|
||
+ CURLFORM_CONTENTSLENGTH, (long) Z_STRLEN_P(data),
|
||
+ CURLFORM_END
|
||
+ );
|
||
+
|
||
+ zval_ptr_dtor(&data);
|
||
+
|
||
+ if (CURLE_OK != err) {
|
||
+ goto error;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ STR_FREE(new_key);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+
|
||
+error:
|
||
+ if (new_key) {
|
||
+ efree(new_key);
|
||
+ }
|
||
+ if (http_post_data[0]) {
|
||
+ curl_formfree(http_post_data[0]);
|
||
+ }
|
||
+ if (err) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: %s", curl_easy_strerror(err));
|
||
+ } else {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: unknown error");
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static STATUS recursive_files(post_data d, HashTable *f, const char *p TSRMLS_DC) */
|
||
+static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC) {
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **data_ptr;
|
||
+ HashPosition pos;
|
||
+ char *new_key = NULL;
|
||
+ CURLcode err = 0;
|
||
+
|
||
+ if (files && !files->nApplyCount) {
|
||
+ FOREACH_HASH_KEYVAL(pos, files, key, data_ptr) {
|
||
+ zval **file_ptr, **type_ptr, **name_ptr;
|
||
+
|
||
+ if (key.type != HASH_KEY_IS_STRING || *key.str) {
|
||
+ new_key = format_key(key.type, key.str, key.num, prefix, 0);
|
||
+
|
||
+ if (Z_TYPE_PP(data_ptr) != IS_ARRAY && Z_TYPE_PP(data_ptr) != IS_OBJECT) {
|
||
+ if (new_key || key.type == HASH_KEY_IS_STRING) {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%s'", new_key ? new_key : key.str);
|
||
+ } else {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%lu'", key.num);
|
||
+ }
|
||
+ } else if ( SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "name", sizeof("name"), (void *) &name_ptr) ||
|
||
+ SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "type", sizeof("type"), (void *) &type_ptr) ||
|
||
+ SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "file", sizeof("file"), (void *) &file_ptr)) {
|
||
+ STATUS status;
|
||
+
|
||
+ ++files->nApplyCount;
|
||
+ status = recursive_files(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC);
|
||
+ --files->nApplyCount;
|
||
+
|
||
+ if (SUCCESS != status) {
|
||
+ goto error;
|
||
+ }
|
||
+ } else {
|
||
+ const char *path;
|
||
+ zval *file = http_zsep(IS_STRING, *file_ptr);
|
||
+ zval *type = http_zsep(IS_STRING, *type_ptr);
|
||
+ zval *name = http_zsep(IS_STRING, *name_ptr);
|
||
+
|
||
+ HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(file), goto error);
|
||
+
|
||
+ /* this is blatant but should be sufficient for most cases */
|
||
+ if (strncasecmp(Z_STRVAL_P(file), "file://", lenof("file://"))) {
|
||
+ path = Z_STRVAL_P(file);
|
||
+ } else {
|
||
+ path = Z_STRVAL_P(file) + lenof("file://");
|
||
+ }
|
||
+
|
||
+ if (new_key) {
|
||
+ char *tmp_key = format_key(HASH_KEY_IS_STRING, Z_STRVAL_P(name), 0, new_key, 0);
|
||
+ STR_SET(new_key, tmp_key);
|
||
+ }
|
||
+
|
||
+ err = curl_formadd(&http_post_data[0], &http_post_data[1],
|
||
+ CURLFORM_COPYNAME, new_key ? new_key : Z_STRVAL_P(name),
|
||
+ CURLFORM_FILE, path,
|
||
+ CURLFORM_CONTENTTYPE, Z_STRVAL_P(type),
|
||
+ CURLFORM_END
|
||
+ );
|
||
+
|
||
+ zval_ptr_dtor(&file);
|
||
+ zval_ptr_dtor(&type);
|
||
+ zval_ptr_dtor(&name);
|
||
+
|
||
+ if (CURLE_OK != err) {
|
||
+ goto error;
|
||
+ }
|
||
+ }
|
||
+ STR_FREE(new_key);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+
|
||
+error:
|
||
+ if (new_key) {
|
||
+ efree(new_key);
|
||
+ }
|
||
+ if (http_post_data[0]) {
|
||
+ curl_formfree(http_post_data[0]);
|
||
+ }
|
||
+ if (err) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: %s", curl_easy_strerror(err));
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: unknown error");
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* HTTP_HAVE_CURL */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/http_request_datashare_api.c
|
||
@@ -0,0 +1,288 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_request_datashare_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_persistent_handle_api.h"
|
||
+#include "php_http_request_datashare_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_object.h"
|
||
+
|
||
+static HashTable http_request_datashare_options;
|
||
+static http_request_datashare http_request_datashare_global;
|
||
+static int http_request_datashare_compare_handles(void *h1, void *h2);
|
||
+static void http_request_datashare_destroy_handles(void *el);
|
||
+#ifdef ZTS
|
||
+static void *http_request_datashare_locks_init(void);
|
||
+static void http_request_datashare_locks_dtor(void *l);
|
||
+static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr);
|
||
+static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr);
|
||
+#endif
|
||
+
|
||
+http_request_datashare *_http_request_datashare_global_get(void)
|
||
+{
|
||
+ return &http_request_datashare_global;
|
||
+}
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_request_datashare)
|
||
+{
|
||
+ curl_lock_data val;
|
||
+
|
||
+ if (SUCCESS != http_persistent_handle_provide("http_request_datashare", curl_share_init, (http_persistent_handle_dtor) curl_share_cleanup, NULL)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+#ifdef ZTS
|
||
+ if (SUCCESS != http_persistent_handle_provide("http_request_datashare_lock", http_request_datashare_locks_init, http_request_datashare_locks_dtor, NULL)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if (!http_request_datashare_init_ex(&http_request_datashare_global, 1)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ zend_hash_init(&http_request_datashare_options, 4, NULL, NULL, 1);
|
||
+#define ADD_DATASHARE_OPT(name, opt) \
|
||
+ val = opt; \
|
||
+ zend_hash_add(&http_request_datashare_options, name, sizeof(name), &val, sizeof(curl_lock_data), NULL)
|
||
+ ADD_DATASHARE_OPT("cookie", CURL_LOCK_DATA_COOKIE);
|
||
+ ADD_DATASHARE_OPT("dns", CURL_LOCK_DATA_DNS);
|
||
+ ADD_DATASHARE_OPT("ssl", CURL_LOCK_DATA_SSL_SESSION);
|
||
+ ADD_DATASHARE_OPT("connect", CURL_LOCK_DATA_CONNECT);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_MSHUTDOWN_FUNCTION(http_request_datashare)
|
||
+{
|
||
+ http_request_datashare_dtor(&http_request_datashare_global);
|
||
+ zend_hash_destroy(&http_request_datashare_options);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_RINIT_FUNCTION(http_request_datashare)
|
||
+{
|
||
+ zend_llist_init(&HTTP_G->request.datashare.handles, sizeof(zval *), http_request_datashare_destroy_handles, 0);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_RSHUTDOWN_FUNCTION(http_request_datashare)
|
||
+{
|
||
+ zend_llist_destroy(&HTTP_G->request.datashare.handles);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC)
|
||
+{
|
||
+ zend_bool free_share;
|
||
+
|
||
+ if ((free_share = !share)) {
|
||
+ share = pemalloc(sizeof(http_request_datashare), persistent);
|
||
+ }
|
||
+ memset(share, 0, sizeof(http_request_datashare));
|
||
+
|
||
+ if (SUCCESS != http_persistent_handle_acquire("http_request_datashare", &share->ch)) {
|
||
+ if (free_share) {
|
||
+ pefree(share, persistent);
|
||
+ }
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ if (!(share->persistent = persistent)) {
|
||
+ share->handle.list = emalloc(sizeof(zend_llist));
|
||
+ zend_llist_init(share->handle.list, sizeof(zval *), ZVAL_PTR_DTOR, 0);
|
||
+#ifdef ZTS
|
||
+ } else {
|
||
+ if (SUCCESS == http_persistent_handle_acquire("http_request_datashare_lock", (void *) &share->handle.locks)) {
|
||
+ curl_share_setopt(share->ch, CURLSHOPT_LOCKFUNC, http_request_datashare_lock_func);
|
||
+ curl_share_setopt(share->ch, CURLSHOPT_UNLOCKFUNC, http_request_datashare_unlock_func);
|
||
+ curl_share_setopt(share->ch, CURLSHOPT_USERDATA, share->handle.locks);
|
||
+ }
|
||
+#endif
|
||
+ }
|
||
+
|
||
+ return share;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC)
|
||
+{
|
||
+ CURLcode rc;
|
||
+ getObjectEx(http_request_object, obj, request);
|
||
+
|
||
+ if (obj->share) {
|
||
+ if (obj->share == share) {
|
||
+ return SUCCESS;
|
||
+ } else if (SUCCESS != http_request_datashare_detach(obj->share, request)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init_ex(obj->request->ch, obj->request), return FAILURE);
|
||
+ if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, share->ch))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not attach HttpRequest object(#%d) to the HttpRequestDataShare: %s", Z_OBJ_HANDLE_P(request), curl_easy_strerror(rc));
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ obj->share = share;
|
||
+ ZVAL_ADDREF(request);
|
||
+ zend_llist_add_element(HTTP_RSHARE_HANDLES(share), (void *) &request);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC)
|
||
+{
|
||
+ CURLcode rc;
|
||
+ getObjectEx(http_request_object, obj, request);
|
||
+
|
||
+ if (!obj->share) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to any HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
|
||
+ } else if (obj->share != share) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to this HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
|
||
+ } else if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not detach HttpRequest object(#%d) from the HttpRequestDataShare: %s", Z_OBJ_HANDLE_P(request), curl_share_strerror(rc));
|
||
+ } else {
|
||
+ obj->share = NULL;
|
||
+ zend_llist_del_element(HTTP_RSHARE_HANDLES(share), request, http_request_datashare_compare_handles);
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC)
|
||
+{
|
||
+ zval **r;
|
||
+
|
||
+ while ((r = zend_llist_get_first(HTTP_RSHARE_HANDLES(share)))) {
|
||
+ http_request_datashare_detach(share, *r);
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC)
|
||
+{
|
||
+ if (!share->persistent) {
|
||
+ zend_llist_destroy(share->handle.list);
|
||
+ efree(share->handle.list);
|
||
+ }
|
||
+ http_persistent_handle_release("http_request_datashare", &share->ch);
|
||
+#ifdef ZTS
|
||
+ if (share->persistent) {
|
||
+ http_persistent_handle_release("http_request_datashare_lock", (void *) &share->handle.locks);
|
||
+ }
|
||
+#endif
|
||
+}
|
||
+
|
||
+PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC)
|
||
+{
|
||
+ http_request_datashare_dtor(*share);
|
||
+ pefree(*share, (*share)->persistent);
|
||
+ *share = NULL;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC)
|
||
+{
|
||
+ curl_lock_data *opt;
|
||
+ CURLSHcode rc;
|
||
+
|
||
+ if (SUCCESS == zend_hash_find(&http_request_datashare_options, (char *) option, option_len + 1, (void *) &opt)) {
|
||
+ if (CURLSHE_OK == (rc = curl_share_setopt(share->ch, enable ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, *opt))) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not %s sharing of %s data: %s", enable ? "enable" : "disable", option, curl_share_strerror(rc));
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+
|
||
+static int http_request_datashare_compare_handles(void *h1, void *h2)
|
||
+{
|
||
+ return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
|
||
+}
|
||
+
|
||
+static void http_request_datashare_destroy_handles(void *el)
|
||
+{
|
||
+ zval **r = (zval **) el;
|
||
+ TSRMLS_FETCH();
|
||
+
|
||
+ { /* gcc 2.95 needs these braces */
|
||
+ getObjectEx(http_request_object, obj, *r);
|
||
+
|
||
+ curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL);
|
||
+ zval_ptr_dtor(r);
|
||
+ }
|
||
+}
|
||
+
|
||
+#ifdef ZTS
|
||
+static void *http_request_datashare_locks_init(void)
|
||
+{
|
||
+ int i;
|
||
+ http_request_datashare_lock *locks = pecalloc(CURL_LOCK_DATA_LAST, sizeof(http_request_datashare_lock), 1);
|
||
+
|
||
+ if (locks) {
|
||
+ for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
|
||
+ locks[i].mx = tsrm_mutex_alloc();
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return locks;
|
||
+}
|
||
+
|
||
+static void http_request_datashare_locks_dtor(void *l)
|
||
+{
|
||
+ int i;
|
||
+ http_request_datashare_lock *locks = (http_request_datashare_lock *) l;
|
||
+
|
||
+ for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
|
||
+ tsrm_mutex_free(locks[i].mx);
|
||
+ }
|
||
+ pefree(locks, 1);
|
||
+}
|
||
+
|
||
+static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr)
|
||
+{
|
||
+ http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
|
||
+
|
||
+ /* TSRM can't distinguish shared/exclusive locks */
|
||
+ tsrm_mutex_lock(locks[data].mx);
|
||
+ locks[data].ch = handle;
|
||
+}
|
||
+
|
||
+static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr)
|
||
+{
|
||
+ http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
|
||
+
|
||
+ if (locks[data].ch == handle) {
|
||
+ tsrm_mutex_unlock(locks[data].mx);
|
||
+ }
|
||
+}
|
||
+#endif
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_request_info.c
|
||
@@ -0,0 +1,198 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_request_info.c 293136 2010-01-05 08:48:52Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+#include "php_http_request_api.h"
|
||
+
|
||
+/* {{{ void http_request_info(http_request *, HashTable *) */
|
||
+PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info)
|
||
+{
|
||
+ char *c;
|
||
+ long l;
|
||
+ double d;
|
||
+ struct curl_slist *s, *p;
|
||
+ zval *subarray, array;
|
||
+ INIT_ZARR(array, info);
|
||
+
|
||
+ /* BEGIN */
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_EFFECTIVE_URL, &c)) {
|
||
+ add_assoc_string_ex(&array, "effective_url", sizeof("effective_url"), c ? c : "", 1);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_RESPONSE_CODE, &l)) {
|
||
+ add_assoc_long_ex(&array, "response_code", sizeof("response_code"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_TOTAL_TIME, &d)) {
|
||
+ add_assoc_double_ex(&array, "total_time", sizeof("total_time"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NAMELOOKUP_TIME, &d)) {
|
||
+ add_assoc_double_ex(&array, "namelookup_time", sizeof("namelookup_time"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONNECT_TIME, &d)) {
|
||
+ add_assoc_double_ex(&array, "connect_time", sizeof("connect_time"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRETRANSFER_TIME, &d)) {
|
||
+ add_assoc_double_ex(&array, "pretransfer_time", sizeof("pretransfer_time"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_UPLOAD, &d)) {
|
||
+ add_assoc_double_ex(&array, "size_upload", sizeof("size_upload"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_DOWNLOAD, &d)) {
|
||
+ add_assoc_double_ex(&array, "size_download", sizeof("size_download"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_DOWNLOAD, &d)) {
|
||
+ add_assoc_double_ex(&array, "speed_download", sizeof("speed_download"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_UPLOAD, &d)) {
|
||
+ add_assoc_double_ex(&array, "speed_upload", sizeof("speed_upload"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HEADER_SIZE, &l)) {
|
||
+ add_assoc_long_ex(&array, "header_size", sizeof("header_size"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REQUEST_SIZE, &l)) {
|
||
+ add_assoc_long_ex(&array, "request_size", sizeof("request_size"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_VERIFYRESULT, &l)) {
|
||
+ add_assoc_long_ex(&array, "ssl_verifyresult", sizeof("ssl_verifyresult"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_FILETIME, &l)) {
|
||
+ add_assoc_long_ex(&array, "filetime", sizeof("filetime"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
|
||
+ add_assoc_double_ex(&array, "content_length_download", sizeof("content_length_download"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_UPLOAD, &d)) {
|
||
+ add_assoc_double_ex(&array, "content_length_upload", sizeof("content_length_upload"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_STARTTRANSFER_TIME, &d)) {
|
||
+ add_assoc_double_ex(&array, "starttransfer_time", sizeof("starttransfer_time"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_TYPE, &c)) {
|
||
+ add_assoc_string_ex(&array, "content_type", sizeof("content_type"), c ? c : "", 1);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_TIME, &d)) {
|
||
+ add_assoc_double_ex(&array, "redirect_time", sizeof("redirect_time"), d);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_COUNT, &l)) {
|
||
+ add_assoc_long_ex(&array, "redirect_count", sizeof("redirect_count"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTP_CONNECTCODE, &l)) {
|
||
+ add_assoc_long_ex(&array, "connect_code", sizeof("connect_code"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTPAUTH_AVAIL, &l)) {
|
||
+ add_assoc_long_ex(&array, "httpauth_avail", sizeof("httpauth_avail"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PROXYAUTH_AVAIL, &l)) {
|
||
+ add_assoc_long_ex(&array, "proxyauth_avail", sizeof("proxyauth_avail"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_OS_ERRNO, &l)) {
|
||
+ add_assoc_long_ex(&array, "os_errno", sizeof("os_errno"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NUM_CONNECTS, &l)) {
|
||
+ add_assoc_long_ex(&array, "num_connects", sizeof("num_connects"), l);
|
||
+ }
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_ENGINES, &s)) {
|
||
+ MAKE_STD_ZVAL(subarray);
|
||
+ array_init(subarray);
|
||
+ for (p = s; p; p = p->next) {
|
||
+ if (p->data) {
|
||
+ add_next_index_string(subarray, p->data, 1);
|
||
+ }
|
||
+ }
|
||
+ add_assoc_zval_ex(&array, "ssl_engines", sizeof("ssl_engines"), subarray);
|
||
+ curl_slist_free_all(s);
|
||
+ }
|
||
+#if HTTP_CURL_VERSION(7,14,1)
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_COOKIELIST, &s)) {
|
||
+ MAKE_STD_ZVAL(subarray);
|
||
+ array_init(subarray);
|
||
+ for (p = s; p; p = p->next) {
|
||
+ if (p->data) {
|
||
+ add_next_index_string(subarray, p->data, 1);
|
||
+ }
|
||
+ }
|
||
+ add_assoc_zval_ex(&array, "cookies", sizeof("cookies"), subarray);
|
||
+ curl_slist_free_all(s);
|
||
+ }
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,18,2)
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_URL, &c)) {
|
||
+ add_assoc_string_ex(&array, "redirect_url", sizeof("redirect_url"), c ? c : "", 1);
|
||
+ }
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,19,0)
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRIMARY_IP, &c)) {
|
||
+ add_assoc_string_ex(&array, "primary_ip", sizeof("primary_ip"), c ? c : "", 1);
|
||
+ }
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,19,0)
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_APPCONNECT_TIME, &d)) {
|
||
+ add_assoc_double_ex(&array, "appconnect_time", sizeof("appconnect_time"), d);
|
||
+ }
|
||
+#endif
|
||
+#if HTTP_CURL_VERSION(7,19,4)
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONDITION_UNMET, &l)) {
|
||
+ add_assoc_long_ex(&array, "condition_unmet", sizeof("condition_unmet"), l);
|
||
+ }
|
||
+#endif
|
||
+/* END */
|
||
+#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
|
||
+ {
|
||
+ int i;
|
||
+ zval *ci_array;
|
||
+ struct curl_certinfo *ci;
|
||
+ char *colon, *keyname;
|
||
+
|
||
+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CERTINFO, &ci)) {
|
||
+ MAKE_STD_ZVAL(ci_array);
|
||
+ array_init(ci_array);
|
||
+
|
||
+ for (i = 0; i < ci->num_of_certs; ++i) {
|
||
+ s = ci->certinfo[i];
|
||
+
|
||
+ MAKE_STD_ZVAL(subarray);
|
||
+ array_init(subarray);
|
||
+ for (p = s; p; p = p->next) {
|
||
+ if (p->data) {
|
||
+ if ((colon = strchr(p->data, ':'))) {
|
||
+ keyname = estrndup(p->data, colon - p->data);
|
||
+ add_assoc_string_ex(subarray, keyname, colon - p->data + 1, colon + 1, 1);
|
||
+ efree(keyname);
|
||
+ } else {
|
||
+ add_next_index_string(subarray, p->data, 1);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ add_next_index_zval(ci_array, subarray);
|
||
+ }
|
||
+ add_assoc_zval_ex(&array, "certinfo", sizeof("certinfo"), ci_array);
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+ add_assoc_string_ex(&array, "error", sizeof("error"), http_request_storage_get(request->ch)->errorbuffer, 1);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* HTTP_HAVE_CURL */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/http_request_method_api.c
|
||
@@ -0,0 +1,321 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_request_method_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_method_api.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
|
||
+# include "php_http_request_object.h"
|
||
+#endif
|
||
+
|
||
+/* {{{ char *http_request_methods[] */
|
||
+static const char *const http_request_methods[] = {
|
||
+ "UNKNOWN",
|
||
+ /* HTTP/1.1 */
|
||
+ "GET",
|
||
+ "HEAD",
|
||
+ "POST",
|
||
+ "PUT",
|
||
+ "DELETE",
|
||
+ "OPTIONS",
|
||
+ "TRACE",
|
||
+ "CONNECT",
|
||
+ /* WebDAV - RFC 2518 */
|
||
+ "PROPFIND",
|
||
+ "PROPPATCH",
|
||
+ "MKCOL",
|
||
+ "COPY",
|
||
+ "MOVE",
|
||
+ "LOCK",
|
||
+ "UNLOCK",
|
||
+ /* WebDAV Versioning - RFC 3253 */
|
||
+ "VERSION-CONTROL",
|
||
+ "REPORT",
|
||
+ "CHECKOUT",
|
||
+ "CHECKIN",
|
||
+ "UNCHECKOUT",
|
||
+ "MKWORKSPACE",
|
||
+ "UPDATE",
|
||
+ "LABEL",
|
||
+ "MERGE",
|
||
+ "BASELINE-CONTROL",
|
||
+ "MKACTIVITY",
|
||
+ /* WebDAV Access Control - RFC 3744 */
|
||
+ "ACL",
|
||
+ NULL
|
||
+};
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ */
|
||
+PHP_MINIT_FUNCTION(http_request_method)
|
||
+{
|
||
+ /* HTTP/1.1 */
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_GET", HTTP_GET);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_HEAD", HTTP_HEAD);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_POST", HTTP_POST);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_PUT", HTTP_PUT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_DELETE", HTTP_DELETE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_OPTIONS", HTTP_OPTIONS);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_TRACE", HTTP_TRACE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_CONNECT", HTTP_CONNECT);
|
||
+ /* WebDAV - RFC 2518 */
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_PROPFIND", HTTP_PROPFIND);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_PROPPATCH", HTTP_PROPPATCH);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_MKCOL", HTTP_MKCOL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_COPY", HTTP_COPY);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_MOVE", HTTP_MOVE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_LOCK", HTTP_LOCK);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_UNLOCK", HTTP_UNLOCK);
|
||
+ /* WebDAV Versioning - RFC 3253 */
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_VERSION_CONTROL", HTTP_VERSION_CONTROL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_REPORT", HTTP_REPORT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_CHECKOUT", HTTP_CHECKOUT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_CHECKIN", HTTP_CHECKIN);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_UNCHECKOUT", HTTP_UNCHECKOUT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_MKWORKSPACE", HTTP_MKWORKSPACE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_UPDATE", HTTP_UPDATE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_LABEL", HTTP_LABEL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_MERGE", HTTP_MERGE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_MKACTIVITY", HTTP_MKACTIVITY);
|
||
+ /* WebDAV Access Control - RFC 3744 */
|
||
+ HTTP_LONG_CONSTANT("HTTP_METH_ACL", HTTP_ACL);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+static void free_method(void *el)
|
||
+{
|
||
+ efree(*(char **)el);
|
||
+}
|
||
+
|
||
+static void unregister_method(const char *name TSRMLS_DC)
|
||
+{
|
||
+ char *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_";
|
||
+
|
||
+ strlcpy(tmp + lenof("HTTP_METH_"), name, HTTP_REQUEST_METHOD_MAXLEN);
|
||
+ for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) {
|
||
+ if (*ptr == '-') {
|
||
+ *ptr = '_';
|
||
+ }
|
||
+ }
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
|
||
+ if (SUCCESS != zend_hash_del(&http_request_object_ce->constants_table, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")) + 1)) {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: HttpRequest::%s", tmp + lenof("HTTP_"));
|
||
+ }
|
||
+#endif
|
||
+ if (SUCCESS != zend_hash_del(EG(zend_constants), tmp, strlen(tmp) + 1)) {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: %s", tmp);
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_RINIT_FUNCTION(http_request_method)
|
||
+{
|
||
+ HashTable ht;
|
||
+
|
||
+ zend_hash_init(&HTTP_G->request.methods.registered, 0, NULL, free_method, 0);
|
||
+#define HTTP_METH_REG(m) \
|
||
+ { \
|
||
+ char *_m=estrdup(m); \
|
||
+ zend_hash_next_index_insert(&HTTP_G->request.methods.registered, (void *) &_m, sizeof(char *), NULL); \
|
||
+ }
|
||
+ HTTP_METH_REG("UNKNOWN");
|
||
+ /* HTTP/1.1 */
|
||
+ HTTP_METH_REG("GET");
|
||
+ HTTP_METH_REG("HEAD");
|
||
+ HTTP_METH_REG("POST");
|
||
+ HTTP_METH_REG("PUT");
|
||
+ HTTP_METH_REG("DELETE");
|
||
+ HTTP_METH_REG("OPTIONS");
|
||
+ HTTP_METH_REG("TRACE");
|
||
+ HTTP_METH_REG("CONNECT");
|
||
+ /* WebDAV - RFC 2518 */
|
||
+ HTTP_METH_REG("PROPFIND");
|
||
+ HTTP_METH_REG("PROPPATCH");
|
||
+ HTTP_METH_REG("MKCOL");
|
||
+ HTTP_METH_REG("COPY");
|
||
+ HTTP_METH_REG("MOVE");
|
||
+ HTTP_METH_REG("LOCK");
|
||
+ HTTP_METH_REG("UNLOCK");
|
||
+ /* WebDAV Versioning - RFC 3253 */
|
||
+ HTTP_METH_REG("VERSION-CONTROL");
|
||
+ HTTP_METH_REG("REPORT");
|
||
+ HTTP_METH_REG("CHECKOUT");
|
||
+ HTTP_METH_REG("CHECKIN");
|
||
+ HTTP_METH_REG("UNCHECKOUT");
|
||
+ HTTP_METH_REG("MKWORKSPACE");
|
||
+ HTTP_METH_REG("UPDATE");
|
||
+ HTTP_METH_REG("LABEL");
|
||
+ HTTP_METH_REG("MERGE");
|
||
+ HTTP_METH_REG("BASELINE-CONTROL");
|
||
+ HTTP_METH_REG("MKACTIVITY");
|
||
+ /* WebDAV Access Control - RFC 3744 */
|
||
+ HTTP_METH_REG("ACL");
|
||
+
|
||
+ zend_hash_init(&ht, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+ if (*HTTP_G->request.methods.custom && SUCCESS == http_parse_params(HTTP_G->request.methods.custom, HTTP_PARAMS_DEFAULT, &ht)) {
|
||
+ HashPosition pos;
|
||
+ zval **val;
|
||
+
|
||
+ FOREACH_HASH_VAL(pos, &ht, val) {
|
||
+ if (Z_TYPE_PP(val) == IS_STRING) {
|
||
+ http_request_method_register(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ zend_hash_destroy(&ht);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_RSHUTDOWN_FUNCTION(http_request_method)
|
||
+{
|
||
+ char **name;
|
||
+ int i, c = zend_hash_next_free_element(&HTTP_G->request.methods.registered);
|
||
+
|
||
+ for (i = HTTP_MAX_REQUEST_METHOD; i < c; ++i) {
|
||
+ if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, i, (void *) &name)) {
|
||
+ unregister_method(*name TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ zend_hash_destroy(&HTTP_G->request.methods.registered);
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+#define http_request_method_cncl(m, c) _http_request_method_cncl_ex((m), strlen(m), (c) TSRMLS_CC)
|
||
+#define http_request_method_cncl_ex(m, l, c) _http_request_method_cncl_ex((m), (l), (c) TSRMLS_CC)
|
||
+static STATUS _http_request_method_cncl_ex(const char *method_name, int method_name_len, char **cnst TSRMLS_DC)
|
||
+{
|
||
+ int i;
|
||
+ char *cncl;
|
||
+
|
||
+ if (method_name_len >= HTTP_REQUEST_METHOD_MAXLEN) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method too long (%s)", method_name);
|
||
+ }
|
||
+ cncl = emalloc(method_name_len + 1);
|
||
+
|
||
+ for (i = 0; i < method_name_len; ++i) {
|
||
+ switch (method_name[i]) {
|
||
+ case '-':
|
||
+ cncl[i] = '-';
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ if (!HTTP_IS_CTYPE(alnum, method_name[i])) {
|
||
+ efree(cncl);
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method contains illegal characters (%s)", method_name);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ cncl[i] = HTTP_TO_CTYPE(upper, method_name[i]);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ cncl[method_name_len] = '\0';
|
||
+
|
||
+ *cnst = cncl;
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC)
|
||
+{
|
||
+ char **name;
|
||
+
|
||
+ if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, m, (void *) &name)) {
|
||
+ return *name;
|
||
+ }
|
||
+ return "UNKNOWN";
|
||
+}
|
||
+
|
||
+PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id_num, const char *id_str TSRMLS_DC)
|
||
+{
|
||
+ char *id_dup;
|
||
+
|
||
+ if (by_name && (SUCCESS == http_request_method_cncl(id_str, &id_dup))) {
|
||
+ char **name;
|
||
+ HashPosition pos;
|
||
+ HashKey key = initHashKey(0);
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos, &HTTP_G->request.methods.registered, key, name) {
|
||
+ if (key.type == HASH_KEY_IS_LONG && !strcmp(*name, id_dup)) {
|
||
+ efree(id_dup);
|
||
+ return key.num;
|
||
+ }
|
||
+ }
|
||
+ efree(id_dup);
|
||
+ } else if (zend_hash_index_exists(&HTTP_G->request.methods.registered, id_num)){
|
||
+ return id_num;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API int _http_request_method_register(const char *method_str, int method_len TSRMLS_DC)
|
||
+{
|
||
+ char *method_dup, *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_";
|
||
+ int method_num = http_request_method_exists(1, 0, method_str);
|
||
+
|
||
+ if (!method_num && (SUCCESS == http_request_method_cncl_ex(method_str, method_len, &method_dup))) {
|
||
+ method_num = zend_hash_next_free_element(&HTTP_G->request.methods.registered);
|
||
+ zend_hash_index_update(&HTTP_G->request.methods.registered, method_num, (void *) &method_dup, sizeof(char *), NULL);
|
||
+
|
||
+ strlcpy(tmp + lenof("HTTP_METH_"), method_dup, HTTP_REQUEST_METHOD_MAXLEN);
|
||
+ for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) {
|
||
+ if (*ptr == '-') {
|
||
+ *ptr = '_';
|
||
+ }
|
||
+ }
|
||
+
|
||
+ zend_register_long_constant(tmp, strlen(tmp) + 1, method_num, CONST_CS, http_module_number TSRMLS_CC);
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
|
||
+ zend_declare_class_constant_long(http_request_object_ce, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")), method_num TSRMLS_CC);
|
||
+#endif
|
||
+ }
|
||
+
|
||
+ return method_num;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC)
|
||
+{
|
||
+ char **name;
|
||
+
|
||
+ if (HTTP_STD_REQUEST_METHOD(method)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Standard request methods cannot be unregistered");
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (SUCCESS != zend_hash_index_find(&HTTP_G->request.methods.registered, method, (void *) &name)) {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Custom request method with id %d does not exist", method);
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ unregister_method(*name TSRMLS_CC);
|
||
+
|
||
+ zend_hash_index_del(&HTTP_G->request.methods.registered, method);
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_request_object.c
|
||
@@ -0,0 +1,1922 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_request_object.c 300299 2010-06-09 06:23:16Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
|
||
+
|
||
+#include "zend_interfaces.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_cookie_api.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_message_api.h"
|
||
+#include "php_http_message_object.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_object.h"
|
||
+#include "php_http_request_pool_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequest, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequest, method, 0)
|
||
+#define HTTP_REQUEST_ME(method, visibility) PHP_ME(HttpRequest, method, HTTP_ARGS(HttpRequest, method), visibility)
|
||
+#define HTTP_REQUEST_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpRequest, method))
|
||
+#define HTTP_REQUEST_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpRequest_##al), HTTP_ARGS(HttpRequest, al), vis)
|
||
+
|
||
+HTTP_BEGIN_ARGS(__construct, 0)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(method, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(factory, 0)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(method, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getOptions);
|
||
+HTTP_BEGIN_ARGS(setOptions, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getSslOptions);
|
||
+HTTP_BEGIN_ARGS(setSslOptions, 0)
|
||
+ HTTP_ARG_VAL(ssl_options, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addSslOptions, 0)
|
||
+ HTTP_ARG_VAL(ssl_optins, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getHeaders);
|
||
+HTTP_BEGIN_ARGS(setHeaders, 0)
|
||
+ HTTP_ARG_VAL(headers, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addHeaders, 1)
|
||
+ HTTP_ARG_VAL(headers, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getCookies);
|
||
+HTTP_BEGIN_ARGS(setCookies, 0)
|
||
+ HTTP_ARG_VAL(cookies, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addCookies, 1)
|
||
+ HTTP_ARG_VAL(cookies, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(enableCookies);
|
||
+HTTP_BEGIN_ARGS(resetCookies, 0)
|
||
+ HTTP_ARG_VAL(session_only, 0)
|
||
+HTTP_END_ARGS;
|
||
+HTTP_EMPTY_ARGS(flushCookies);
|
||
+
|
||
+HTTP_EMPTY_ARGS(getUrl);
|
||
+HTTP_BEGIN_ARGS(setUrl, 1)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getMethod);
|
||
+HTTP_BEGIN_ARGS(setMethod, 1)
|
||
+ HTTP_ARG_VAL(request_method, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getContentType);
|
||
+HTTP_BEGIN_ARGS(setContentType, 1)
|
||
+ HTTP_ARG_VAL(content_type, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getQueryData);
|
||
+HTTP_BEGIN_ARGS(setQueryData, 0)
|
||
+ HTTP_ARG_VAL(query_data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addQueryData, 1)
|
||
+ HTTP_ARG_VAL(query_data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getPostFields);
|
||
+HTTP_BEGIN_ARGS(setPostFields, 0)
|
||
+ HTTP_ARG_VAL(post_fields, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addPostFields, 1)
|
||
+ HTTP_ARG_VAL(post_fields, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getPostFiles);
|
||
+HTTP_BEGIN_ARGS(setPostFiles, 0)
|
||
+ HTTP_ARG_VAL(post_files, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addPostFile, 2)
|
||
+ HTTP_ARG_VAL(formname, 0)
|
||
+ HTTP_ARG_VAL(filename, 0)
|
||
+ HTTP_ARG_VAL(content_type, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getBody);
|
||
+HTTP_BEGIN_ARGS(setBody, 0)
|
||
+ HTTP_ARG_VAL(request_body_data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addBody, 1)
|
||
+ HTTP_ARG_VAL(request_body_data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getPutFile);
|
||
+HTTP_BEGIN_ARGS(setPutFile, 0)
|
||
+ HTTP_ARG_VAL(filename, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getPutData);
|
||
+HTTP_BEGIN_ARGS(setPutData, 0)
|
||
+ HTTP_ARG_VAL(put_data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(addPutData, 1)
|
||
+ HTTP_ARG_VAL(put_data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getResponseData);
|
||
+HTTP_BEGIN_ARGS(getResponseHeader, 0)
|
||
+ HTTP_ARG_VAL(name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(getResponseCookies, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+ HTTP_ARG_VAL(allowed_extras, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getResponseBody);
|
||
+HTTP_EMPTY_ARGS(getResponseCode);
|
||
+HTTP_EMPTY_ARGS(getResponseStatus);
|
||
+HTTP_BEGIN_ARGS(getResponseInfo, 0)
|
||
+ HTTP_ARG_VAL(name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getMessageClass);
|
||
+HTTP_BEGIN_ARGS(setMessageClass, 1)
|
||
+ HTTP_ARG_VAL(message_class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getResponseMessage);
|
||
+HTTP_EMPTY_ARGS(getRawResponseMessage);
|
||
+HTTP_EMPTY_ARGS(getRequestMessage);
|
||
+HTTP_EMPTY_ARGS(getRawRequestMessage);
|
||
+HTTP_EMPTY_ARGS(getHistory);
|
||
+HTTP_EMPTY_ARGS(clearHistory);
|
||
+HTTP_EMPTY_ARGS(send);
|
||
+
|
||
+HTTP_BEGIN_ARGS(get, 1)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(info, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(head, 1)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(info, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(postData, 2)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(info, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(postFields, 2)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(info, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(putData, 2)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(info, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(putFile, 2)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(file, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(info, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(putStream, 2)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(stream, 0)
|
||
+ HTTP_ARG_VAL(options, 0)
|
||
+ HTTP_ARG_VAL(info, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(methodRegister, 1)
|
||
+ HTTP_ARG_VAL(method_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(methodUnregister, 1)
|
||
+ HTTP_ARG_VAL(method, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(methodName, 1)
|
||
+ HTTP_ARG_VAL(method_id, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(methodExists, 1)
|
||
+ HTTP_ARG_VAL(method, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+#ifdef HAVE_CURL_FORMGET
|
||
+HTTP_BEGIN_ARGS(encodeBody, 2)
|
||
+ HTTP_ARG_VAL(fields, 0)
|
||
+ HTTP_ARG_VAL(files, 0)
|
||
+HTTP_END_ARGS;
|
||
+#endif
|
||
+
|
||
+#define THIS_CE http_request_object_ce
|
||
+zend_class_entry *http_request_object_ce;
|
||
+zend_function_entry http_request_object_fe[] = {
|
||
+ HTTP_REQUEST_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
|
||
+
|
||
+ HTTP_REQUEST_ME(setOptions, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getOptions, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(setSslOptions, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getSslOptions, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(addSslOptions, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(addHeaders, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getHeaders, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(setHeaders, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(addCookies, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getCookies, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(setCookies, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(enableCookies, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(resetCookies, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(flushCookies, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setMethod, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getMethod, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setUrl, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getUrl, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setContentType, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getContentType, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setQueryData, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getQueryData, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(addQueryData, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setPostFields, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getPostFields, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(addPostFields, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setBody, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getBody, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(addBody, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_MALIAS(setRawPostData, setBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
|
||
+ HTTP_REQUEST_MALIAS(getRawPostData, getBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
|
||
+ HTTP_REQUEST_MALIAS(addRawPostData, addBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
|
||
+
|
||
+ HTTP_REQUEST_ME(setPostFiles, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(addPostFile, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getPostFiles, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setPutFile, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getPutFile, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(setPutData, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getPutData, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(addPutData, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(send, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(getResponseData, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getResponseHeader, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getResponseCookies, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getResponseCode, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getResponseStatus, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getResponseBody, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getResponseInfo, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getResponseMessage, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getRawResponseMessage, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getRequestMessage, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getRawRequestMessage, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(getHistory, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(clearHistory, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(getMessageClass, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQUEST_ME(setMessageClass, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQUEST_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+
|
||
+ HTTP_REQUEST_ALIAS(get, http_get)
|
||
+ HTTP_REQUEST_ALIAS(head, http_head)
|
||
+ HTTP_REQUEST_ALIAS(postData, http_post_data)
|
||
+ HTTP_REQUEST_ALIAS(postFields, http_post_fields)
|
||
+ HTTP_REQUEST_ALIAS(putData, http_put_data)
|
||
+ HTTP_REQUEST_ALIAS(putFile, http_put_file)
|
||
+ HTTP_REQUEST_ALIAS(putStream, http_put_stream)
|
||
+
|
||
+ HTTP_REQUEST_ALIAS(methodRegister, http_request_method_register)
|
||
+ HTTP_REQUEST_ALIAS(methodUnregister, http_request_method_unregister)
|
||
+ HTTP_REQUEST_ALIAS(methodName, http_request_method_name)
|
||
+ HTTP_REQUEST_ALIAS(methodExists, http_request_method_exists)
|
||
+#ifdef HAVE_CURL_FORMGET
|
||
+ HTTP_REQUEST_ALIAS(encodeBody, http_request_body_encode)
|
||
+#endif
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+static zend_object_handlers http_request_object_handlers;
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_request_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS_EX(HttpRequest, http_request_object, NULL, 0);
|
||
+ http_request_object_handlers.clone_obj = _http_request_object_clone_obj;
|
||
+
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("options")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("postFields")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("postFiles")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("responseInfo")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("responseMessage")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("method")-1, HTTP_GET, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("url")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("contentType")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("requestBody")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("queryData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("putFile")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("putData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("history")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("recordHistory")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
||
+ zend_declare_property_string(THIS_CE, ZEND_STRS("messageClass")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
|
||
+
|
||
+#ifndef WONKY
|
||
+ /*
|
||
+ * Request Method Constants
|
||
+ */
|
||
+ /* HTTP/1.1 */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_GET")-1, HTTP_GET TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_HEAD")-1, HTTP_HEAD TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_POST")-1, HTTP_POST TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PUT")-1, HTTP_PUT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_DELETE")-1, HTTP_DELETE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_OPTIONS")-1, HTTP_OPTIONS TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_TRACE")-1, HTTP_TRACE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CONNECT")-1, HTTP_CONNECT TSRMLS_CC);
|
||
+ /* WebDAV - RFC 2518 */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPFIND")-1, HTTP_PROPFIND TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPPATCH")-1, HTTP_PROPPATCH TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKCOL")-1, HTTP_MKCOL TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_COPY")-1, HTTP_COPY TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MOVE")-1, HTTP_MOVE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LOCK")-1, HTTP_LOCK TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNLOCK")-1, HTTP_UNLOCK TSRMLS_CC);
|
||
+ /* WebDAV Versioning - RFC 3253 */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_VERSION_CONTROL")-1, HTTP_VERSION_CONTROL TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_REPORT")-1, HTTP_REPORT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKOUT")-1, HTTP_CHECKOUT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKIN")-1, HTTP_CHECKIN TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNCHECKOUT")-1, HTTP_UNCHECKOUT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKWORKSPACE")-1, HTTP_MKWORKSPACE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UPDATE")-1, HTTP_UPDATE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LABEL")-1, HTTP_LABEL TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MERGE")-1, HTTP_MERGE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_BASELINE_CONTROL")-1, HTTP_BASELINE_CONTROL TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKACTIVITY")-1, HTTP_MKACTIVITY TSRMLS_CC);
|
||
+ /* WebDAV Access Control - RFC 3744 */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_ACL")-1, HTTP_ACL TSRMLS_CC);
|
||
+
|
||
+ /*
|
||
+ * HTTP Protocol Version Constants
|
||
+ */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_0")-1, CURL_HTTP_VERSION_1_0 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_1")-1, CURL_HTTP_VERSION_1_1 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_NONE")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC); /* to be removed */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_ANY")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC);
|
||
+
|
||
+ /*
|
||
+ * SSL Version Constants
|
||
+ */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_TLSv1")-1, CURL_SSLVERSION_TLSv1 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv2")-1, CURL_SSLVERSION_SSLv2 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv3")-1, CURL_SSLVERSION_SSLv3 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_ANY")-1, CURL_SSLVERSION_DEFAULT TSRMLS_CC);
|
||
+
|
||
+ /*
|
||
+ * DNS IPvX resolving
|
||
+ */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V4")-1, CURL_IPRESOLVE_V4 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V6")-1, CURL_IPRESOLVE_V6 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_ANY")-1, CURL_IPRESOLVE_WHATEVER TSRMLS_CC);
|
||
+
|
||
+ /*
|
||
+ * Auth Constants
|
||
+ */
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_BASIC")-1, CURLAUTH_BASIC TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST")-1, CURLAUTH_DIGEST TSRMLS_CC);
|
||
+#if HTTP_CURL_VERSION(7,19,3)
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST_IE")-1, CURLAUTH_DIGEST_IE TSRMLS_CC);
|
||
+#endif
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_NTLM")-1, CURLAUTH_NTLM TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_GSSNEG")-1, CURLAUTH_GSSNEGOTIATE TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_ANY")-1, CURLAUTH_ANY TSRMLS_CC);
|
||
+
|
||
+ /*
|
||
+ * Proxy Type Constants
|
||
+ */
|
||
+# if HTTP_CURL_VERSION(7,15,2)
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4")-1, CURLPROXY_SOCKS4 TSRMLS_CC);
|
||
+# endif
|
||
+#if HTTP_CURL_VERSION(7,18,0)
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4A")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5_HOSTNAME")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
|
||
+#endif
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP")-1, CURLPROXY_HTTP TSRMLS_CC);
|
||
+# if HTTP_CURL_VERSION(7,19,4)
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP_1_0")-1, CURLPROXY_HTTP_1_0 TSRMLS_CC);
|
||
+# endif
|
||
+#endif /* WONKY */
|
||
+
|
||
+ /*
|
||
+ * Post Redirection Constants
|
||
+ */
|
||
+#if HTTP_CURL_VERSION(7,19,1)
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_301")-1, CURL_REDIR_POST_301 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_302")-1, CURL_REDIR_POST_302 TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_ALL")-1, CURL_REDIR_POST_ALL TSRMLS_CC);
|
||
+#endif
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ return http_request_object_new_ex(ce, NULL, NULL);
|
||
+}
|
||
+
|
||
+zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ http_request_object *o;
|
||
+
|
||
+ o = ecalloc(1, sizeof(http_request_object));
|
||
+ o->zo.ce = ce;
|
||
+ o->request = http_request_init_ex(NULL, ch, 0, NULL);
|
||
+
|
||
+ if (ptr) {
|
||
+ *ptr = o;
|
||
+ }
|
||
+
|
||
+ ALLOC_HASHTABLE(OBJ_PROP(o));
|
||
+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+
|
||
+ ov.handle = putObject(http_request_object, o);
|
||
+ ov.handlers = &http_request_object_handlers;
|
||
+
|
||
+ return ov;
|
||
+}
|
||
+
|
||
+zend_object_value _http_request_object_clone_obj(zval *this_ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value new_ov;
|
||
+ http_request_object *new_obj;
|
||
+ getObject(http_request_object, old_obj);
|
||
+
|
||
+ new_ov = http_request_object_new_ex(old_obj->zo.ce, NULL, &new_obj);
|
||
+ if (old_obj->request->ch) {
|
||
+ http_curl_init_ex(http_curl_copy(old_obj->request->ch), new_obj->request);
|
||
+ }
|
||
+
|
||
+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
|
||
+ phpstr_append(&new_obj->request->conv.request, old_obj->request->conv.request.data, old_obj->request->conv.request.used);
|
||
+ phpstr_append(&new_obj->request->conv.response, old_obj->request->conv.response.data, old_obj->request->conv.response.used);
|
||
+
|
||
+ return new_ov;
|
||
+}
|
||
+
|
||
+void _http_request_object_free(zend_object *object TSRMLS_DC)
|
||
+{
|
||
+ http_request_object *o = (http_request_object *) object;
|
||
+
|
||
+ http_request_free(&o->request);
|
||
+ freeObject(o);
|
||
+}
|
||
+
|
||
+#define http_request_object_check_request_content_type(t) _http_request_object_check_request_content_type((t) TSRMLS_CC)
|
||
+static inline void _http_request_object_check_request_content_type(zval *this_ptr TSRMLS_DC)
|
||
+{
|
||
+ zval *ctype = zend_read_property(THIS_CE, getThis(), ZEND_STRS("contentType")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_STRLEN_P(ctype)) {
|
||
+ zval **headers, *opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if ( (Z_TYPE_P(opts) == IS_ARRAY) &&
|
||
+ (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void *) &headers)) &&
|
||
+ (Z_TYPE_PP(headers) == IS_ARRAY)) {
|
||
+ zval **ct_header;
|
||
+
|
||
+ /* only override if not already set */
|
||
+ if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(headers), "Content-Type", sizeof("Content-Type"), (void *) &ct_header))) {
|
||
+ add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
|
||
+ } else
|
||
+ /* or not a string, zero length string or a string of spaces */
|
||
+ if ((Z_TYPE_PP(ct_header) != IS_STRING) || !Z_STRLEN_PP(ct_header)) {
|
||
+ add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
|
||
+ } else {
|
||
+ int i, only_space = 1;
|
||
+
|
||
+ /* check for spaces only */
|
||
+ for (i = 0; i < Z_STRLEN_PP(ct_header); ++i) {
|
||
+ if (!HTTP_IS_CTYPE(space, Z_STRVAL_PP(ct_header)[i])) {
|
||
+ only_space = 0;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ if (only_space) {
|
||
+ add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
|
||
+ }
|
||
+ }
|
||
+ } else {
|
||
+ zval *headers;
|
||
+
|
||
+ MAKE_STD_ZVAL(headers);
|
||
+ array_init(headers);
|
||
+ add_assoc_stringl(headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, headers);
|
||
+ zval_ptr_dtor(&headers);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+#define http_request_object_message(zo, msg) _http_request_object_message((zo), (msg) TSRMLS_CC)
|
||
+static inline zend_object_value _http_request_object_message(zval *this_ptr, http_message *msg TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ zval *zcn = zend_read_property(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_STRLEN_P(zcn) && (SUCCESS == http_object_new(&ov, Z_STRVAL_P(zcn), Z_STRLEN_P(zcn), _http_message_object_new_ex, http_message_object_ce, msg, NULL))) {
|
||
+ return ov;
|
||
+ } else {
|
||
+ return http_message_object_new_ex(http_message_object_ce, msg, NULL);
|
||
+ }
|
||
+}
|
||
+
|
||
+STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC)
|
||
+{
|
||
+ STATUS status = SUCCESS;
|
||
+ char *url = http_absolute_url(Z_STRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("url")-1, 0 TSRMLS_CC)));
|
||
+
|
||
+ if (!url) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ http_request_reset(obj->request);
|
||
+ obj->request->url = url;
|
||
+ HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init(obj->request), return FAILURE);
|
||
+
|
||
+ switch (obj->request->meth = Z_LVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("method")-1, 0 TSRMLS_CC)))
|
||
+ {
|
||
+ case HTTP_GET:
|
||
+ case HTTP_HEAD:
|
||
+ break;
|
||
+
|
||
+ case HTTP_PUT:
|
||
+ {
|
||
+ zval *put_file = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putFile")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ http_request_object_check_request_content_type(getThis());
|
||
+
|
||
+ if (Z_STRLEN_P(put_file)) {
|
||
+ php_stream_statbuf ssb;
|
||
+ php_stream *stream = php_stream_open_wrapper_ex(Z_STRVAL_P(put_file), "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT);
|
||
+
|
||
+ if (stream && SUCCESS == php_stream_stat(stream, &ssb)) {
|
||
+ obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
|
||
+ } else {
|
||
+ status = FAILURE;
|
||
+ }
|
||
+ } else {
|
||
+ zval *put_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC);
|
||
+ obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING,
|
||
+ estrndup(Z_STRVAL_P(put_data), Z_STRLEN_P(put_data)), Z_STRLEN_P(put_data), 1);
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case HTTP_POST:
|
||
+ default:
|
||
+ {
|
||
+ /* check for raw request body */
|
||
+ zval *raw_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_STRLEN_P(raw_data)) {
|
||
+ http_request_object_check_request_content_type(getThis());
|
||
+ obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING,
|
||
+ estrndup(Z_STRVAL_P(raw_data), Z_STRLEN_P(raw_data)), Z_STRLEN_P(raw_data), 1);
|
||
+ } else {
|
||
+ zval *zfields = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, 0 TSRMLS_CC), *zfiles = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, 0 TSRMLS_CC);
|
||
+ HashTable *fields;
|
||
+ HashTable *files;
|
||
+
|
||
+ fields = (Z_TYPE_P(zfields) == IS_ARRAY) ? Z_ARRVAL_P(zfields) : NULL;
|
||
+ files = (Z_TYPE_P(zfiles) == IS_ARRAY) ? Z_ARRVAL_P(zfiles) : NULL;
|
||
+
|
||
+ if ((fields && zend_hash_num_elements(fields)) || (files && zend_hash_num_elements(files))) {
|
||
+ if (!(obj->request->body = http_request_body_fill(obj->request->body, fields, files))) {
|
||
+ status = FAILURE;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (status == SUCCESS) {
|
||
+ zval *qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC);
|
||
+ zval *options = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_STRLEN_P(qdata)) {
|
||
+ if (!strchr(obj->request->url, '?')) {
|
||
+ strlcat(obj->request->url, "?", HTTP_URL_MAXLEN);
|
||
+ } else {
|
||
+ strlcat(obj->request->url, "&", HTTP_URL_MAXLEN);
|
||
+ }
|
||
+ strlcat(obj->request->url, Z_STRVAL_P(qdata), HTTP_URL_MAXLEN);
|
||
+ }
|
||
+
|
||
+ http_request_prepare(obj->request, Z_ARRVAL_P(options));
|
||
+
|
||
+ /* check if there's a onProgress method and add it as progress callback if one isn't already set */
|
||
+ if (zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onprogress", sizeof("onprogress"))) {
|
||
+ zval **entry, *pcb;
|
||
+
|
||
+ if ( (Z_TYPE_P(options) != IS_ARRAY)
|
||
+ || (SUCCESS != zend_hash_find(Z_ARRVAL_P(options), "onprogress", sizeof("onprogress"), (void *) &entry)
|
||
+ || (!IS_CALLABLE(*entry, 0, NULL)))) {
|
||
+ MAKE_STD_ZVAL(pcb);
|
||
+ array_init(pcb);
|
||
+ ZVAL_ADDREF(getThis());
|
||
+ add_next_index_zval(pcb, getThis());
|
||
+ add_next_index_stringl(pcb, "onprogress", lenof("onprogress"), 1);
|
||
+ http_request_set_progress_callback(obj->request, pcb);
|
||
+ zval_ptr_dtor(&pcb);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return status;
|
||
+}
|
||
+
|
||
+STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC)
|
||
+{
|
||
+ STATUS ret;
|
||
+ zval *info;
|
||
+ http_message *msg;
|
||
+
|
||
+ /* always fetch info */
|
||
+ MAKE_STD_ZVAL(info);
|
||
+ array_init(info);
|
||
+ http_request_info(obj->request, Z_ARRVAL_P(info));
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, info TSRMLS_CC);
|
||
+ zval_ptr_dtor(&info);
|
||
+
|
||
+ /* parse response message */
|
||
+ phpstr_fix(&obj->request->conv.request);
|
||
+ phpstr_fix(&obj->request->conv.response);
|
||
+
|
||
+ if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response)))) {
|
||
+ zval *message;
|
||
+
|
||
+ if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) {
|
||
+ zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
|
||
+ http_message *response = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response));
|
||
+ http_message *request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request));
|
||
+
|
||
+ MAKE_STD_ZVAL(hist);
|
||
+ ZVAL_OBJVAL(hist, http_request_object_message(getThis(), http_message_interconnect(response, request)), 0);
|
||
+ if (Z_TYPE_P(history) == IS_OBJECT) {
|
||
+ http_message_object_prepend(hist, history);
|
||
+ }
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
|
||
+ zval_ptr_dtor(&hist);
|
||
+ }
|
||
+
|
||
+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, msg->http.info.response.code TSRMLS_CC);
|
||
+ zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, STR_PTR(msg->http.info.response.status) TSRMLS_CC);
|
||
+
|
||
+ MAKE_STD_ZVAL(message);
|
||
+ ZVAL_OBJVAL(message, http_request_object_message(getThis(), msg), 0);
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, message TSRMLS_CC);
|
||
+ zval_ptr_dtor(&message);
|
||
+
|
||
+ ret = SUCCESS;
|
||
+ } else {
|
||
+ /* update properties with empty values*/
|
||
+ zval *znull;
|
||
+
|
||
+ MAKE_STD_ZVAL(znull);
|
||
+ ZVAL_NULL(znull);
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, znull TSRMLS_CC);
|
||
+ zval_ptr_dtor(&znull);
|
||
+
|
||
+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, 0 TSRMLS_CC);
|
||
+ zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, "" TSRMLS_CC);
|
||
+
|
||
+ /* append request message to history */
|
||
+ if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) {
|
||
+ http_message *request;
|
||
+
|
||
+ if ((request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) {
|
||
+ zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ MAKE_STD_ZVAL(hist);
|
||
+ ZVAL_OBJVAL(hist, http_request_object_message(getThis(), request), 0);
|
||
+ if (Z_TYPE_P(history) == IS_OBJECT) {
|
||
+ http_message_object_prepend(hist, history);
|
||
+ }
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
|
||
+ zval_ptr_dtor(&hist);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ ret = FAILURE;
|
||
+ }
|
||
+
|
||
+ http_request_set_progress_callback(obj->request, NULL);
|
||
+
|
||
+ if (!EG(exception) && zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onfinish", sizeof("onfinish"))) {
|
||
+ zval *param;
|
||
+
|
||
+ MAKE_STD_ZVAL(param);
|
||
+ ZVAL_BOOL(param, ret == SUCCESS);
|
||
+ with_error_handling(EH_NORMAL, NULL) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "onfinish", NULL, param);
|
||
+ } end_error_handling();
|
||
+ zval_ptr_dtor(¶m);
|
||
+ }
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+static int apply_pretty_key(void *pDest, int num_args, va_list args, zend_hash_key *hash_key)
|
||
+{
|
||
+ if (hash_key->arKey && hash_key->nKeyLength > 1) {
|
||
+ hash_key->h = zend_hash_func(pretty_key(hash_key->arKey, hash_key->nKeyLength - 1, 1, 0), hash_key->nKeyLength);
|
||
+ }
|
||
+ return ZEND_HASH_APPLY_KEEP;
|
||
+}
|
||
+
|
||
+#define http_request_object_set_options_subr(key, ow, pk) \
|
||
+ _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key), (ow), (pk))
|
||
+static inline void _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len, int overwrite, int prettify_keys)
|
||
+{
|
||
+ zval *old_opts, *new_opts, *opts = NULL, **entry = NULL;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opts)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(new_opts);
|
||
+ array_init(new_opts);
|
||
+ old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
|
||
+ if (Z_TYPE_P(old_opts) == IS_ARRAY) {
|
||
+ array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
|
||
+ }
|
||
+
|
||
+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), key, len, (void *) &entry)) {
|
||
+ if (overwrite) {
|
||
+ zend_hash_clean(Z_ARRVAL_PP(entry));
|
||
+ }
|
||
+ if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
|
||
+ if (overwrite) {
|
||
+ array_copy(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry));
|
||
+ } else {
|
||
+ array_join(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry), 0, prettify_keys ? ARRAY_JOIN_PRETTIFY : 0);
|
||
+ }
|
||
+ }
|
||
+ } else if (opts) {
|
||
+ if (prettify_keys) {
|
||
+ zend_hash_apply_with_arguments(Z_ARRVAL_P(opts) HTTP_ZAPI_HASH_TSRMLS_CC, apply_pretty_key, 0, NULL);
|
||
+ }
|
||
+ ZVAL_ADDREF(opts);
|
||
+ add_assoc_zval_ex(new_opts, key, len, opts);
|
||
+ }
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
|
||
+ zval_ptr_dtor(&new_opts);
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+
|
||
+#define http_request_object_get_options_subr(key) \
|
||
+ _http_request_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key))
|
||
+static inline void _http_request_get_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *opts, **options;
|
||
+
|
||
+ opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
|
||
+ array_init(return_value);
|
||
+
|
||
+ if ( (Z_TYPE_P(opts) == IS_ARRAY) &&
|
||
+ (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), key, len, (void *) &options))) {
|
||
+ convert_to_array(*options);
|
||
+ array_copy(Z_ARRVAL_PP(options), Z_ARRVAL_P(return_value));
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+/* ### USERLAND ### */
|
||
+
|
||
+/* {{{ proto void HttpRequest::__construct([string url[, int request_method = HTTP_METH_GET[, array options]]])
|
||
+ Create a new HttpRequest object instance. */
|
||
+PHP_METHOD(HttpRequest, __construct)
|
||
+{
|
||
+ char *URL = NULL;
|
||
+ int URL_len;
|
||
+ long meth = -1;
|
||
+ zval *options = NULL;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!", &URL, &URL_len, &meth, &options)) {
|
||
+ if (URL) {
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
|
||
+ }
|
||
+ if (meth > -1) {
|
||
+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
|
||
+ }
|
||
+ if (options) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpRequest HttpRequest::factory([string url[, int request_method HTTP_METH_GET[, array options[, string class_name = "HttpRequest"]]]])
|
||
+ Create a new HttpRequest object instance. */
|
||
+PHP_METHOD(HttpRequest, factory)
|
||
+{
|
||
+ char *cn = NULL, *URL = NULL;
|
||
+ int cl = 0, URL_len = 0;
|
||
+ long meth = -1;
|
||
+ zval *options = NULL;
|
||
+ zend_object_value ov;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!s", &URL, &URL_len, &meth, &options, &cn, &cl) &&
|
||
+ SUCCESS == http_object_new(&ov, cn, cl, _http_request_object_new_ex, http_request_object_ce, NULL, NULL)) {
|
||
+ RETVAL_OBJVAL(ov, 0);
|
||
+ getThis() = return_value;
|
||
+ if (URL) {
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
|
||
+ }
|
||
+ if (meth > -1) {
|
||
+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
|
||
+ }
|
||
+ if (options) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setOptions([array options])
|
||
+ Set the request options to use. See http_get() for a full list of available options. */
|
||
+PHP_METHOD(HttpRequest, setOptions)
|
||
+{
|
||
+ HashKey key = initHashKey(0);
|
||
+ HashPosition pos;
|
||
+ zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(new_opts);
|
||
+ array_init(new_opts);
|
||
+
|
||
+ if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
|
||
+ zval_ptr_dtor(&new_opts);
|
||
+ RETURN_TRUE;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(add_opts);
|
||
+ array_init(add_opts);
|
||
+ /* some options need extra attention -- thus cannot use array_merge() directly */
|
||
+ FOREACH_KEYVAL(pos, opts, key, opt) {
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+#define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
|
||
+ if (KEYMATCH(key, "headers")) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, *opt);
|
||
+ } else if (KEYMATCH(key, "cookies")) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt);
|
||
+ } else if (KEYMATCH(key, "ssl")) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt);
|
||
+ } else if (KEYMATCH(key, "url") || KEYMATCH(key, "uri")) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "seturl", NULL, *opt);
|
||
+ } else if (KEYMATCH(key, "method")) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmethod", NULL, *opt);
|
||
+ } else if (KEYMATCH(key, "flushcookies")) {
|
||
+ getObject(http_request_object, obj);
|
||
+ if (i_zend_is_true(*opt)) {
|
||
+ http_request_flush_cookies(obj->request);
|
||
+ }
|
||
+ } else if (KEYMATCH(key, "resetcookies")) {
|
||
+ getObject(http_request_object, obj);
|
||
+ http_request_reset_cookies(obj->request, (zend_bool) i_zend_is_true(*opt));
|
||
+ } else if (KEYMATCH(key, "enablecookies")) {
|
||
+ getObject(http_request_object, obj);
|
||
+ http_request_enable_cookies(obj->request);
|
||
+ } else if (KEYMATCH(key, "recordHistory")) {
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, *opt TSRMLS_CC);
|
||
+ } else if (KEYMATCH(key, "messageClass")) {
|
||
+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmessageclass", NULL, *opt);
|
||
+ } else if (Z_TYPE_PP(opt) == IS_NULL) {
|
||
+ old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
|
||
+ if (Z_TYPE_P(old_opts) == IS_ARRAY) {
|
||
+ zend_hash_del(Z_ARRVAL_P(old_opts), key.str, key.len);
|
||
+ }
|
||
+ } else {
|
||
+ ZVAL_ADDREF(*opt);
|
||
+ add_assoc_zval_ex(add_opts, key.str, key.len, *opt);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
|
||
+ if (Z_TYPE_P(old_opts) == IS_ARRAY) {
|
||
+ array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
|
||
+ }
|
||
+ array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0);
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
|
||
+ zval_ptr_dtor(&new_opts);
|
||
+ zval_ptr_dtor(&add_opts);
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequest::getOptions()
|
||
+ Get currently set options. */
|
||
+PHP_METHOD(HttpRequest, getOptions)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(options);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setSslOptions([array options])
|
||
+ Set SSL options. */
|
||
+PHP_METHOD(HttpRequest, setSslOptions)
|
||
+{
|
||
+ http_request_object_set_options_subr("ssl", 1, 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addSslOptions(array options)
|
||
+ Set additional SSL options. */
|
||
+PHP_METHOD(HttpRequest, addSslOptions)
|
||
+{
|
||
+ http_request_object_set_options_subr("ssl", 0, 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequest::getSslOtpions()
|
||
+ Get previously set SSL options. */
|
||
+PHP_METHOD(HttpRequest, getSslOptions)
|
||
+{
|
||
+ http_request_object_get_options_subr("ssl");
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addHeaders(array headers)
|
||
+ Add request header name/value pairs. */
|
||
+PHP_METHOD(HttpRequest, addHeaders)
|
||
+{
|
||
+ http_request_object_set_options_subr("headers", 0, 1);
|
||
+}
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setHeaders([array headers])
|
||
+ Set request header name/value pairs. */
|
||
+PHP_METHOD(HttpRequest, setHeaders)
|
||
+{
|
||
+ http_request_object_set_options_subr("headers", 1, 1);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequest::getHeaders()
|
||
+ Get previously set request headers. */
|
||
+PHP_METHOD(HttpRequest, getHeaders)
|
||
+{
|
||
+ http_request_object_get_options_subr("headers");
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setCookies([array cookies])
|
||
+ Set cookies. */
|
||
+PHP_METHOD(HttpRequest, setCookies)
|
||
+{
|
||
+ http_request_object_set_options_subr("cookies", 1, 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addCookies(array cookies)
|
||
+ Add cookies. */
|
||
+PHP_METHOD(HttpRequest, addCookies)
|
||
+{
|
||
+ http_request_object_set_options_subr("cookies", 0, 0);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequest::getCookies()
|
||
+ Get previously set cookies. */
|
||
+PHP_METHOD(HttpRequest, getCookies)
|
||
+{
|
||
+ http_request_object_get_options_subr("cookies");
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::enableCookies()
|
||
+ Enable automatic sending of received cookies. Note that customly set cookies will be sent anyway. */
|
||
+PHP_METHOD(HttpRequest, enableCookies)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_request_object, obj);
|
||
+ RETURN_SUCCESS(http_request_enable_cookies(obj->request));
|
||
+ }
|
||
+
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::resetCookies([bool session_only = FALSE])
|
||
+ Reset all automatically received/sent cookies. Note that customly set cookies are not affected. */
|
||
+PHP_METHOD(HttpRequest, resetCookies)
|
||
+{
|
||
+ zend_bool session_only = 0;
|
||
+ getObject(http_request_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &session_only)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ RETURN_SUCCESS(http_request_reset_cookies(obj->request, session_only));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::flushCookies()
|
||
+ Flush internal cookies to the cookiestore file */
|
||
+PHP_METHOD(HttpRequest, flushCookies)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_request_object, obj);
|
||
+ RETURN_SUCCESS(http_request_flush_cookies(obj->request));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setUrl(string url)
|
||
+ Set the request URL. */
|
||
+PHP_METHOD(HttpRequest, setUrl)
|
||
+{
|
||
+ char *URL = NULL;
|
||
+ int URL_len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getUrl()
|
||
+ Get the previously set request URL. */
|
||
+PHP_METHOD(HttpRequest, getUrl)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(url);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setMethod(int request_method)
|
||
+ Set the request method. */
|
||
+PHP_METHOD(HttpRequest, setMethod)
|
||
+{
|
||
+ long meth;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpRequest::getMethod()
|
||
+ Get the previously set request method. */
|
||
+PHP_METHOD(HttpRequest, getMethod)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(method);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setContentType(string content_type)
|
||
+ Set the content type the post request should have. */
|
||
+PHP_METHOD(HttpRequest, setContentType)
|
||
+{
|
||
+ char *ctype;
|
||
+ int ct_len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (ct_len) {
|
||
+ HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
|
||
+ }
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("contentType")-1, ctype, ct_len TSRMLS_CC);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getContentType()
|
||
+ Get the previously content type. */
|
||
+PHP_METHOD(HttpRequest, getContentType)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(contentType);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setQueryData([mixed query_data])
|
||
+ Set the URL query parameters to use, overwriting previously set query parameters. */
|
||
+PHP_METHOD(HttpRequest, setQueryData)
|
||
+{
|
||
+ zval *qdata = NULL;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!", &qdata)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if ((!qdata) || Z_TYPE_P(qdata) == IS_NULL) {
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, "", 0 TSRMLS_CC);
|
||
+ } else if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
|
||
+ char *query_data = NULL;
|
||
+
|
||
+ if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data TSRMLS_CC);
|
||
+ efree(query_data);
|
||
+ } else {
|
||
+ zval *data = http_zsep(IS_STRING, qdata);
|
||
+
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, Z_STRVAL_P(data), Z_STRLEN_P(data) TSRMLS_CC);
|
||
+ zval_ptr_dtor(&data);
|
||
+ }
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getQueryData()
|
||
+ Get the current query data in form of an urlencoded query string. */
|
||
+PHP_METHOD(HttpRequest, getQueryData)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(queryData);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addQueryData(array query_params)
|
||
+ Add parameters to the query parameter list, leaving previously set unchanged. */
|
||
+PHP_METHOD(HttpRequest, addQueryData)
|
||
+{
|
||
+ zval *qdata, *old_qdata;
|
||
+ char *query_data = NULL;
|
||
+ size_t query_data_len = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &qdata)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ old_qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, &query_data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data, query_data_len TSRMLS_CC);
|
||
+ efree(query_data);
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addPostFields(array post_data)
|
||
+ Adds POST data entries, leaving previously set unchanged, unless a post entry with the same name already exists. */
|
||
+PHP_METHOD(HttpRequest, addPostFields)
|
||
+{
|
||
+ zval *post_data, *old_post, *new_post;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &post_data)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
|
||
+ MAKE_STD_ZVAL(new_post);
|
||
+ array_init(new_post);
|
||
+ old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, 0 TSRMLS_CC);
|
||
+ if (Z_TYPE_P(old_post) == IS_ARRAY) {
|
||
+ array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
|
||
+ }
|
||
+ array_join(Z_ARRVAL_P(post_data), Z_ARRVAL_P(new_post), 0, 0);
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, new_post TSRMLS_CC);
|
||
+ zval_ptr_dtor(&new_post);
|
||
+ }
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setPostFields([array post_data])
|
||
+ Set the POST data entries, overwriting previously set POST data. */
|
||
+PHP_METHOD(HttpRequest, setPostFields)
|
||
+{
|
||
+ zval *post, *post_data = NULL;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &post_data)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(post);
|
||
+ array_init(post);
|
||
+ if (post_data && zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
|
||
+ array_copy(Z_ARRVAL_P(post_data), Z_ARRVAL_P(post));
|
||
+ }
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, post TSRMLS_CC);
|
||
+ zval_ptr_dtor(&post);
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}}*/
|
||
+
|
||
+/* {{{ proto array HttpRequest::getPostFields()
|
||
+ Get previously set POST data. */
|
||
+PHP_METHOD(HttpRequest, getPostFields)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(postFields);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setBody([string request_body_data])
|
||
+ Set request body to send, overwriting previously set request body. Don't forget to specify a content type. */
|
||
+PHP_METHOD(HttpRequest, setBody)
|
||
+{
|
||
+ char *raw_data = NULL;
|
||
+ int data_len = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &raw_data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!raw_data) {
|
||
+ raw_data = "";
|
||
+ }
|
||
+
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addBody(string request_body_data)
|
||
+ Add request body data, leaving previously set request body data unchanged. */
|
||
+PHP_METHOD(HttpRequest, addBody)
|
||
+{
|
||
+ char *raw_data;
|
||
+ int data_len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &raw_data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (data_len) {
|
||
+ zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_STRLEN_P(data)) {
|
||
+ Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1);
|
||
+ Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0';
|
||
+ memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, raw_data, data_len);
|
||
+ } else {
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getBody()
|
||
+ Get previously set request body data. */
|
||
+PHP_METHOD(HttpRequest, getBody)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(requestBody);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
|
||
+ Add a file to the POST request, leaving previously set files unchanged. */
|
||
+PHP_METHOD(HttpRequest, addPostFile)
|
||
+{
|
||
+ zval *entry, *old_post, *new_post;
|
||
+ char *name, *file, *type = NULL;
|
||
+ int name_len, file_len, type_len = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (type_len) {
|
||
+ HTTP_CHECK_CONTENT_TYPE(type, RETURN_FALSE);
|
||
+ } else {
|
||
+ type = "application/x-octetstream";
|
||
+ type_len = sizeof("application/x-octetstream") - 1;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(entry);
|
||
+ array_init(entry);
|
||
+
|
||
+ add_assoc_stringl(entry, "name", name, name_len, 1);
|
||
+ add_assoc_stringl(entry, "type", type, type_len, 1);
|
||
+ add_assoc_stringl(entry, "file", file, file_len, 1);
|
||
+
|
||
+ MAKE_STD_ZVAL(new_post);
|
||
+ array_init(new_post);
|
||
+ old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, 0 TSRMLS_CC);
|
||
+ if (Z_TYPE_P(old_post) == IS_ARRAY) {
|
||
+ array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
|
||
+ }
|
||
+ add_next_index_zval(new_post, entry);
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, new_post TSRMLS_CC);
|
||
+ zval_ptr_dtor(&new_post);
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setPostFiles([array post_files])
|
||
+ Set files to post, overwriting previously set post files. */
|
||
+PHP_METHOD(HttpRequest, setPostFiles)
|
||
+{
|
||
+ zval *files = NULL, *post;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!/", &files)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ MAKE_STD_ZVAL(post);
|
||
+ array_init(post);
|
||
+ if (files && (Z_TYPE_P(files) == IS_ARRAY)) {
|
||
+ array_copy(Z_ARRVAL_P(files), Z_ARRVAL_P(post));
|
||
+ }
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, post TSRMLS_CC);
|
||
+ zval_ptr_dtor(&post);
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequest::getPostFiles()
|
||
+ Get all previously added POST files. */
|
||
+PHP_METHOD(HttpRequest, getPostFiles)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(postFiles);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setPutFile([string file])
|
||
+ Set file to put. Affects only PUT requests. */
|
||
+PHP_METHOD(HttpRequest, setPutFile)
|
||
+{
|
||
+ char *file = "";
|
||
+ int file_len = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &file, &file_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putFile")-1, file, file_len TSRMLS_CC);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getPutFile()
|
||
+ Get previously set put file. */
|
||
+PHP_METHOD(HttpRequest, getPutFile)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(putFile);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::setPutData([string put_data])
|
||
+ Set PUT data to send, overwriting previously set PUT data. */
|
||
+PHP_METHOD(HttpRequest, setPutData)
|
||
+{
|
||
+ char *put_data = NULL;
|
||
+ int data_len = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &put_data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (!put_data) {
|
||
+ put_data = "";
|
||
+ }
|
||
+
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequest::addPutData(string put_data)
|
||
+ Add PUT data, leaving previously set PUT data unchanged. */
|
||
+PHP_METHOD(HttpRequest, addPutData)
|
||
+{
|
||
+ char *put_data;
|
||
+ int data_len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &put_data, &data_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (data_len) {
|
||
+ zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_STRLEN_P(data)) {
|
||
+ Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1);
|
||
+ Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0';
|
||
+ memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, put_data, data_len);
|
||
+ } else {
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getPutData()
|
||
+ Get previously set PUT data. */
|
||
+PHP_METHOD(HttpRequest, getPutData)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(putData);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequest::getResponseData()
|
||
+ Get all response data after the request has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseData)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ char *body;
|
||
+ size_t body_len;
|
||
+ zval *headers, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_TYPE_P(message) == IS_OBJECT) {
|
||
+ getObjectEx(http_message_object, msg, message);
|
||
+
|
||
+ array_init(return_value);
|
||
+
|
||
+ MAKE_STD_ZVAL(headers);
|
||
+ array_init(headers);
|
||
+ zend_hash_copy(Z_ARRVAL_P(headers), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ add_assoc_zval(return_value, "headers", headers);
|
||
+
|
||
+ phpstr_data(PHPSTR(msg->message), &body, &body_len);
|
||
+ add_assoc_stringl(return_value, "body", body, body_len, 0);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto mixed HttpRequest::getResponseHeader([string name])
|
||
+ Get response header(s) after the request has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseHeader)
|
||
+{
|
||
+ if (return_value_used) {
|
||
+ zval *header;
|
||
+ char *header_name = NULL;
|
||
+ int header_len = 0;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) {
|
||
+ zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_TYPE_P(message) == IS_OBJECT) {
|
||
+ getObjectEx(http_message_object, msg, message);
|
||
+
|
||
+ if (header_len) {
|
||
+ if ((header = http_message_header_ex(msg->message, pretty_key(header_name, header_len, 1, 1), header_len + 1, 0))) {
|
||
+ RETURN_ZVAL(header, 1, 1);
|
||
+ }
|
||
+ } else {
|
||
+ array_init(return_value);
|
||
+ zend_hash_copy(Z_ARRVAL_P(return_value), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequest::getResponseCookies([int flags[, array allowed_extras]])
|
||
+ Get response cookie(s) after the request has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseCookies)
|
||
+{
|
||
+ if (return_value_used) {
|
||
+ long flags = 0;
|
||
+ zval *allowed_extras_array = NULL;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|la!", &flags, &allowed_extras_array)) {
|
||
+ int i = 0;
|
||
+ HashKey key = initHashKey(0);
|
||
+ char **allowed_extras = NULL;
|
||
+ zval **header = NULL, **entry = NULL, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
|
||
+ HashPosition pos, pos1, pos2;
|
||
+
|
||
+ if (Z_TYPE_P(message) == IS_OBJECT) {
|
||
+ getObjectEx(http_message_object, msg, message);
|
||
+
|
||
+ array_init(return_value);
|
||
+
|
||
+ if (allowed_extras_array) {
|
||
+ allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
|
||
+ FOREACH_VAL(pos, allowed_extras_array, entry) {
|
||
+ zval *data = http_zsep(IS_STRING, *entry);
|
||
+ allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
|
||
+ zval_ptr_dtor(&data);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos1, &msg->message->hdrs, key, header) {
|
||
+ if (key.type == HASH_KEY_IS_STRING && !strcasecmp(key.str, "Set-Cookie")) {
|
||
+ http_cookie_list list;
|
||
+
|
||
+ if (Z_TYPE_PP(header) == IS_ARRAY) {
|
||
+ zval **single_header;
|
||
+
|
||
+ FOREACH_VAL(pos2, *header, single_header) {
|
||
+ zval *data = http_zsep(IS_STRING, *single_header);
|
||
+
|
||
+ if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) {
|
||
+ zval *cookie;
|
||
+
|
||
+ MAKE_STD_ZVAL(cookie);
|
||
+ object_init(cookie);
|
||
+ http_cookie_list_tostruct(&list, cookie);
|
||
+ add_next_index_zval(return_value, cookie);
|
||
+ http_cookie_list_dtor(&list);
|
||
+ }
|
||
+ zval_ptr_dtor(&data);
|
||
+ }
|
||
+ } else {
|
||
+ zval *data = http_zsep(IS_STRING, *header);
|
||
+ if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) {
|
||
+ zval *cookie;
|
||
+
|
||
+ MAKE_STD_ZVAL(cookie);
|
||
+ object_init(cookie);
|
||
+ http_cookie_list_tostruct(&list, cookie);
|
||
+ add_next_index_zval(return_value, cookie);
|
||
+ http_cookie_list_dtor(&list);
|
||
+ }
|
||
+ zval_ptr_dtor(&data);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (allowed_extras) {
|
||
+ for (i = 0; allowed_extras[i]; ++i) {
|
||
+ efree(allowed_extras[i]);
|
||
+ }
|
||
+ efree(allowed_extras);
|
||
+ }
|
||
+
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getResponseBody()
|
||
+ Get the response body after the request has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseBody)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_TYPE_P(message) == IS_OBJECT) {
|
||
+ getObjectEx(http_message_object, msg, message);
|
||
+ RETURN_PHPSTR_DUP(&msg->message->body);
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpRequest::getResponseCode()
|
||
+ Get the response code after the request has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseCode)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(responseCode);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getResponseStatus()
|
||
+ Get the response status (i.e. the string after the response code) after the message has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseStatus)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP(responseStatus);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto mixed HttpRequest::getResponseInfo([string name])
|
||
+ Get response info after the request has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseInfo)
|
||
+{
|
||
+ if (return_value_used) {
|
||
+ zval *info, **infop;
|
||
+ char *info_name = NULL;
|
||
+ int info_len = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ info = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, 0 TSRMLS_CC);
|
||
+
|
||
+ if (Z_TYPE_P(info) != IS_ARRAY) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (info_len && info_name) {
|
||
+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void *) &infop)) {
|
||
+ RETURN_ZVAL(*infop, 1, 0);
|
||
+ } else {
|
||
+ http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Could not find response info named %s", info_name);
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ } else {
|
||
+ RETURN_ZVAL(info, 1, 0);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}}*/
|
||
+
|
||
+/* {{{ proto HttpMessage HttpRequest::getResponseMessage()
|
||
+ Get the full response as HttpMessage object after the request has been sent. */
|
||
+PHP_METHOD(HttpRequest, getResponseMessage)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ zval *message;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
|
||
+ if (Z_TYPE_P(message) == IS_OBJECT) {
|
||
+ RETVAL_OBJECT(message, 1);
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpRequest does not contain a response message");
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpMessage HttpRequest::getRequestMessage()
|
||
+ Get sent HTTP message. */
|
||
+PHP_METHOD(HttpRequest, getRequestMessage)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ http_message *msg;
|
||
+ getObject(http_request_object, obj);
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) {
|
||
+ RETVAL_OBJVAL(http_request_object_message(getThis(), msg), 0);
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getRawRequestMessage()
|
||
+ Get sent HTTP message. */
|
||
+PHP_METHOD(HttpRequest, getRawRequestMessage)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_request_object, obj);
|
||
+
|
||
+ RETURN_PHPSTR_DUP(&obj->request->conv.request);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getRawResponseMessage()
|
||
+ Get the entire HTTP response. */
|
||
+PHP_METHOD(HttpRequest, getRawResponseMessage)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_request_object, obj);
|
||
+
|
||
+ RETURN_PHPSTR_DUP(&obj->request->conv.response);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpMessage HttpRequest::getHistory()
|
||
+ Get all sent requests and received responses as an HttpMessage object. */
|
||
+PHP_METHOD(HttpRequest, getHistory)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *hist;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ hist = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
|
||
+ if (Z_TYPE_P(hist) == IS_OBJECT) {
|
||
+ RETVAL_OBJECT(hist, 1);
|
||
+ } else {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "The history is empty");
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpRequest::clearHistory()
|
||
+ Clear the history. */
|
||
+PHP_METHOD(HttpRequest, clearHistory)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ zval *hist;
|
||
+
|
||
+ MAKE_STD_ZVAL(hist);
|
||
+ ZVAL_NULL(hist);
|
||
+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
|
||
+ zval_ptr_dtor(&hist);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto string HttpRequest::getMessageClass()
|
||
+ Get the message class name. */
|
||
+PHP_METHOD(HttpRequest, getMessageClass)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ RETURN_PROP("messageClass");
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void setMessageClass(string class_name)
|
||
+ Set the message class name. */
|
||
+PHP_METHOD(HttpRequest, setMessageClass)
|
||
+{
|
||
+ char *cn;
|
||
+ int cl;
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &cn, &cl)) {
|
||
+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, cn, cl TSRMLS_CC);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpMessage HttpRequest::send()
|
||
+ Send the HTTP request. */
|
||
+PHP_METHOD(HttpRequest, send)
|
||
+{
|
||
+ getObject(http_request_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+
|
||
+ if (obj->pool) {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool");
|
||
+ } else if (SUCCESS == http_request_object_requesthandler(obj, getThis())) {
|
||
+ http_request_exec(obj->request);
|
||
+ if (SUCCESS == http_request_object_responsehandler(obj, getThis())) {
|
||
+ RETVAL_OBJECT(zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC), 1);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_request_pool_api.c
|
||
@@ -0,0 +1,660 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_request_pool_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#define HTTP_WANT_EVENT
|
||
+#include "php_http.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_persistent_handle_api.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_object.h"
|
||
+#include "php_http_request_pool_api.h"
|
||
+#include "php_http_requestpool_object.h"
|
||
+
|
||
+#ifndef HTTP_DEBUG_REQPOOLS
|
||
+# define HTTP_DEBUG_REQPOOLS 0
|
||
+#endif
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+typedef struct _http_request_pool_event_t {
|
||
+ struct event evnt;
|
||
+ http_request_pool *pool;
|
||
+} http_request_pool_event;
|
||
+
|
||
+static void http_request_pool_timeout_callback(int socket, short action, void *event_data);
|
||
+static void http_request_pool_event_callback(int socket, short action, void *event_data);
|
||
+static int http_request_pool_socket_callback(CURL *easy, curl_socket_t s, int action, void *, void *);
|
||
+static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data);
|
||
+#endif
|
||
+
|
||
+static int http_request_pool_compare_handles(void *h1, void *h2);
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_request_pool)
|
||
+{
|
||
+ if (SUCCESS != http_persistent_handle_provide("http_request_pool", curl_multi_init, (http_persistent_handle_dtor) curl_multi_cleanup, NULL)) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+PHP_RINIT_FUNCTION(http_request_pool)
|
||
+{
|
||
+ if (!HTTP_G->request.pool.event.base && !(HTTP_G->request.pool.event.base = event_init())) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+#endif
|
||
+
|
||
+/* {{{ http_request_pool *http_request_pool_init(http_request_pool *) */
|
||
+PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC)
|
||
+{
|
||
+ zend_bool free_pool;
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Initializing request pool %p\n", pool);
|
||
+#endif
|
||
+
|
||
+ if ((free_pool = (!pool))) {
|
||
+ pool = emalloc(sizeof(http_request_pool));
|
||
+ pool->ch = NULL;
|
||
+ }
|
||
+
|
||
+ if (SUCCESS != http_persistent_handle_acquire("http_request_pool", &pool->ch)) {
|
||
+ if (free_pool) {
|
||
+ efree(pool);
|
||
+ }
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ TSRMLS_SET_CTX(pool->tsrm_ls);
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+ pool->timeout = ecalloc(1, sizeof(struct event));
|
||
+ curl_multi_setopt(pool->ch, CURLMOPT_SOCKETDATA, pool);
|
||
+ curl_multi_setopt(pool->ch, CURLMOPT_SOCKETFUNCTION, http_request_pool_socket_callback);
|
||
+ curl_multi_setopt(pool->ch, CURLMOPT_TIMERDATA, pool);
|
||
+ curl_multi_setopt(pool->ch, CURLMOPT_TIMERFUNCTION, http_request_pool_timer_callback);
|
||
+#endif
|
||
+
|
||
+ pool->unfinished = 0;
|
||
+ zend_llist_init(&pool->finished, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0);
|
||
+ zend_llist_init(&pool->handles, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Initialized request pool %p\n", pool);
|
||
+#endif
|
||
+
|
||
+ return pool;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_request_pool_attach(http_request_pool *, zval *) */
|
||
+PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request)
|
||
+{
|
||
+#ifdef ZTS
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+#endif
|
||
+ getObjectEx(http_request_object, req, request);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Attaching HttpRequest(#%d) %p to pool %p\n", Z_OBJ_HANDLE_P(request), req, pool);
|
||
+#endif
|
||
+
|
||
+ if (req->pool) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is already member of %s HttpRequestPool", Z_OBJ_HANDLE_P(request), req->pool == pool ? "this" : "another");
|
||
+ } else if (SUCCESS != http_request_object_requesthandler(req, request)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not initialize HttpRequest object(#%d) for attaching to the HttpRequestPool", Z_OBJ_HANDLE_P(request));
|
||
+ } else {
|
||
+ CURLMcode code = curl_multi_add_handle(pool->ch, req->request->ch);
|
||
+
|
||
+ if (CURLM_OK != code) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "Could not attach HttpRequest object(#%d) to the HttpRequestPool: %s", Z_OBJ_HANDLE_P(request), curl_multi_strerror(code));
|
||
+ } else {
|
||
+ req->pool = pool;
|
||
+
|
||
+ ZVAL_ADDREF(request);
|
||
+ zend_llist_add_element(&pool->handles, &request);
|
||
+ ++pool->unfinished;
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "> %d HttpRequests attached to pool %p\n", zend_llist_count(&pool->handles), pool);
|
||
+#endif
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_request_pool_detach(http_request_pool *, zval *) */
|
||
+PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request)
|
||
+{
|
||
+ CURLMcode code;
|
||
+#ifdef ZTS
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+#endif
|
||
+ getObjectEx(http_request_object, req, request);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Detaching HttpRequest(#%d) %p from pool %p\n", Z_OBJ_HANDLE_P(request), req, pool);
|
||
+#endif
|
||
+
|
||
+ if (!req->pool) {
|
||
+ /* not attached to any pool */
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "HttpRequest object(#%d) %p is not attached to any HttpRequestPool\n", Z_OBJ_HANDLE_P(request), req);
|
||
+#endif
|
||
+ } else if (req->pool != pool) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is not attached to this HttpRequestPool", Z_OBJ_HANDLE_P(request));
|
||
+ } else if (req->request->_in_progress_cb) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback", Z_OBJ_HANDLE_P(request));
|
||
+ } else if (CURLM_OK != (code = curl_multi_remove_handle(pool->ch, req->request->ch))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "Could not detach HttpRequest object(#%d) from the HttpRequestPool: %s", Z_OBJ_HANDLE_P(request), curl_multi_strerror(code));
|
||
+ } else {
|
||
+ req->pool = NULL;
|
||
+ zend_llist_del_element(&pool->finished, request, http_request_pool_compare_handles);
|
||
+ zend_llist_del_element(&pool->handles, request, http_request_pool_compare_handles);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "> %d HttpRequests remaining in pool %p\n", zend_llist_count(&pool->handles), pool);
|
||
+#endif
|
||
+
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_pool_apply(http_request_pool *, http_request_pool_apply_func) */
|
||
+PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb)
|
||
+{
|
||
+ int count = zend_llist_count(&pool->handles);
|
||
+
|
||
+ if (count) {
|
||
+ int i = 0;
|
||
+ zend_llist_position pos;
|
||
+ zval **handle, **handles = emalloc(count * sizeof(zval *));
|
||
+
|
||
+ for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) {
|
||
+ handles[i++] = *handle;
|
||
+ }
|
||
+
|
||
+ /* should never happen */
|
||
+ if (i != count) {
|
||
+ zend_error(E_ERROR, "number of fetched request handles do not match overall count");
|
||
+ count = i;
|
||
+ }
|
||
+
|
||
+ for (i = 0; i < count; ++i) {
|
||
+ if (cb(pool, handles[i])) {
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ efree(handles);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_pool_apply_with_arg(http_request_pool *, http_request_pool_apply_with_arg_func, void *) */
|
||
+PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg)
|
||
+{
|
||
+ int count = zend_llist_count(&pool->handles);
|
||
+
|
||
+ if (count) {
|
||
+ int i = 0;
|
||
+ zend_llist_position pos;
|
||
+ zval **handle, **handles = emalloc(count * sizeof(zval *));
|
||
+
|
||
+ for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) {
|
||
+ handles[i++] = *handle;
|
||
+ }
|
||
+
|
||
+ /* should never happen */
|
||
+ if (i != count) {
|
||
+ zend_error(E_ERROR, "number of fetched request handles do not match overall count");
|
||
+ count = i;
|
||
+ }
|
||
+
|
||
+ for (i = 0; i < count; ++i) {
|
||
+ if (cb(pool, handles[i], arg)) {
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ efree(handles);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_pool_detach_all(http_request_pool *) */
|
||
+PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool)
|
||
+{
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Detaching %d requests from pool %p\n", zend_llist_count(&pool->handles), pool);
|
||
+#endif
|
||
+ http_request_pool_apply(pool, _http_request_pool_detach);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_request_pool_send(http_request_pool *) */
|
||
+PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool)
|
||
+{
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Attempt to send %d requests of pool %p\n", zend_llist_count(&pool->handles), pool);
|
||
+#endif
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+ if (pool->useevents) {
|
||
+ do {
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "& Starting event dispatcher of pool %p\n", pool);
|
||
+#endif
|
||
+ event_base_dispatch(HTTP_G->request.pool.event.base);
|
||
+ } while (pool->unfinished);
|
||
+ } else
|
||
+#endif
|
||
+ {
|
||
+ while (http_request_pool_perform(pool)) {
|
||
+ if (SUCCESS != http_request_pool_select(pool)) {
|
||
+#ifdef PHP_WIN32
|
||
+ /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */
|
||
+ http_error_ex(HE_WARNING, HTTP_E_SOCKET, "WinSock error: %d", WSAGetLastError());
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_SOCKET, strerror(errno));
|
||
+#endif
|
||
+ return FAILURE;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Finished sending %d HttpRequests of pool %p (still unfinished: %d)\n", zend_llist_count(&pool->handles), pool, pool->unfinished);
|
||
+#endif
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_pool_dtor(http_request_pool *) */
|
||
+PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool)
|
||
+{
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Destructing request pool %p\n", pool);
|
||
+#endif
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+ efree(pool->timeout);
|
||
+#endif
|
||
+
|
||
+ http_request_pool_detach_all(pool);
|
||
+
|
||
+ pool->unfinished = 0;
|
||
+ zend_llist_clean(&pool->finished);
|
||
+ zend_llist_clean(&pool->handles);
|
||
+ http_persistent_handle_release("http_request_pool", &pool->ch);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef PHP_WIN32
|
||
+# define SELECT_ERROR SOCKET_ERROR
|
||
+#else
|
||
+# define SELECT_ERROR -1
|
||
+#endif
|
||
+
|
||
+/* {{{ STATUS http_request_pool_select(http_request_pool *) */
|
||
+PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool)
|
||
+{
|
||
+ return http_request_pool_select_ex(pool, NULL);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_request_pool_select_ex(http_request_pool *, struct timeval *) */
|
||
+PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout)
|
||
+{
|
||
+ int MAX;
|
||
+ fd_set R, W, E;
|
||
+ struct timeval timeout;
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+ if (pool->useevents) {
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks");
|
||
+ return FAILURE;
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ if (custom_timeout && timerisset(custom_timeout)) {
|
||
+ timeout = *custom_timeout;
|
||
+ } else {
|
||
+ http_request_pool_timeout(pool, &timeout);
|
||
+ }
|
||
+
|
||
+ FD_ZERO(&R);
|
||
+ FD_ZERO(&W);
|
||
+ FD_ZERO(&E);
|
||
+
|
||
+ if (CURLM_OK == curl_multi_fdset(pool->ch, &R, &W, &E, &MAX)) {
|
||
+ if (MAX == -1) {
|
||
+ http_sleep((double) timeout.tv_sec + (double) (timeout.tv_usec / HTTP_MCROSEC));
|
||
+ return SUCCESS;
|
||
+ } else if (SELECT_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ int http_request_pool_perform(http_request_pool *) */
|
||
+PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool)
|
||
+{
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+ if (pool->useevents) {
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks");
|
||
+ return FAILURE;
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(pool->ch, &pool->unfinished));
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "%u unfinished requests of pool %p remaining\n", pool->unfinished, pool);
|
||
+#endif
|
||
+
|
||
+ http_request_pool_responsehandler(pool);
|
||
+
|
||
+ return pool->unfinished;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_request_pool_responsehandler(http_request_pool *) */
|
||
+void _http_request_pool_responsehandler(http_request_pool *pool)
|
||
+{
|
||
+ CURLMsg *msg;
|
||
+ int remaining = 0;
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+
|
||
+ do {
|
||
+ msg = curl_multi_info_read(pool->ch, &remaining);
|
||
+ if (msg && CURLMSG_DONE == msg->msg) {
|
||
+ if (CURLE_OK != msg->data.result) {
|
||
+ http_request_storage *st = http_request_storage_get(msg->easy_handle);
|
||
+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(msg->data.result), st?st->errorbuffer:"", st?st->url:"");
|
||
+ }
|
||
+ http_request_pool_apply_with_arg(pool, _http_request_pool_apply_responsehandler, msg->easy_handle);
|
||
+ }
|
||
+ } while (remaining);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ int http_request_pool_apply_responsehandler(http_request_pool *, zval *, void *) */
|
||
+int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch)
|
||
+{
|
||
+#ifdef ZTS
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+#endif
|
||
+ getObjectEx(http_request_object, obj, req);
|
||
+
|
||
+ if ((!ch) || obj->request->ch == (CURL *) ch) {
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Fetching data from HttpRequest(#%d) %p of pool %p\n", Z_OBJ_HANDLE_P(req), obj, obj->pool);
|
||
+#endif
|
||
+
|
||
+ ZVAL_ADDREF(req);
|
||
+ zend_llist_add_element(&obj->pool->finished, &req);
|
||
+ http_request_object_responsehandler(obj, req);
|
||
+ return 1;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ struct timeval *_http_request_pool_timeout(http_request_pool *, struct timeval *) */
|
||
+struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout)
|
||
+{
|
||
+#ifdef HAVE_CURL_MULTI_TIMEOUT
|
||
+ long max_tout = 1000;
|
||
+
|
||
+ if ((CURLM_OK == curl_multi_timeout(pool->ch, &max_tout)) && (max_tout > 0)) {
|
||
+ timeout->tv_sec = max_tout / 1000;
|
||
+ timeout->tv_usec = (max_tout % 1000) * 1000;
|
||
+ } else {
|
||
+#endif
|
||
+ timeout->tv_sec = 0;
|
||
+ timeout->tv_usec = 1000;
|
||
+#ifdef HAVE_CURL_MULTI_TIMEOUT
|
||
+ }
|
||
+#endif
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Calculating timeout (%lu, %lu) of pool %p\n", (ulong) timeout->tv_sec, (ulong) timeout->tv_usec, pool);
|
||
+#endif
|
||
+
|
||
+ return timeout;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*#*/
|
||
+
|
||
+/* {{{ static int http_request_pool_compare_handles(void *, void *) */
|
||
+static int http_request_pool_compare_handles(void *h1, void *h2)
|
||
+{
|
||
+ return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+/* {{{ static void http_request_pool_timeout_callback(int, short, void *) */
|
||
+static void http_request_pool_timeout_callback(int socket, short action, void *event_data)
|
||
+{
|
||
+ http_request_pool *pool = event_data;
|
||
+
|
||
+ if (pool->useevents) {
|
||
+ CURLMcode rc;
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Timeout occurred of pool %p\n", pool);
|
||
+#endif
|
||
+
|
||
+ while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket(pool->ch, CURL_SOCKET_TIMEOUT, &pool->unfinished)));
|
||
+
|
||
+ if (CURLM_OK != rc) {
|
||
+ http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc));
|
||
+ }
|
||
+
|
||
+ http_request_pool_responsehandler(pool);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static void http_request_pool_event_callback(int, short, void *) */
|
||
+static void http_request_pool_event_callback(int socket, short action, void *event_data)
|
||
+{
|
||
+ http_request_pool_event *ev = event_data;
|
||
+ http_request_pool *pool = ev->pool;
|
||
+
|
||
+ if (pool->useevents) {
|
||
+ CURLMcode rc = CURLE_OK;
|
||
+ TSRMLS_FETCH_FROM_CTX(ev->pool->tsrm_ls);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ {
|
||
+ static const char event_strings[][20] = {"NONE","TIMEOUT","READ","TIMEOUT|READ","WRITE","TIMEOUT|WRITE","READ|WRITE","TIMEOUT|READ|WRITE","SIGNAL"};
|
||
+ fprintf(stderr, "Event on socket %d (%s) event %p of pool %p\n", socket, event_strings[action], ev, pool);
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ /* don't use 'ev' below this loop as it might 've been freed in the socket callback */
|
||
+ do {
|
||
+#ifdef HAVE_CURL_MULTI_SOCKET_ACTION
|
||
+ switch (action & (EV_READ|EV_WRITE)) {
|
||
+ case EV_READ:
|
||
+ rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN, &pool->unfinished);
|
||
+ break;
|
||
+ case EV_WRITE:
|
||
+ rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_OUT, &pool->unfinished);
|
||
+ break;
|
||
+ case EV_READ|EV_WRITE:
|
||
+ rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN|CURL_CSELECT_OUT, &pool->unfinished);
|
||
+ break;
|
||
+ default:
|
||
+ http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown event %d", (int) action);
|
||
+ return;
|
||
+ }
|
||
+#else
|
||
+ rc = curl_multi_socket(pool->ch, socket, &pool->unfinished);
|
||
+#endif
|
||
+ } while (CURLM_CALL_MULTI_PERFORM == rc);
|
||
+
|
||
+ switch (rc) {
|
||
+ case CURLM_BAD_SOCKET:
|
||
+#if 0
|
||
+ fprintf(stderr, "!!! Bad socket: %d (%d)\n", socket, (int) action);
|
||
+#endif
|
||
+ case CURLM_OK:
|
||
+ break;
|
||
+ default:
|
||
+ http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc));
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ http_request_pool_responsehandler(pool);
|
||
+
|
||
+ /* remove timeout if there are no transfers left */
|
||
+ if (!pool->unfinished && event_initialized(pool->timeout) && event_pending(pool->timeout, EV_TIMEOUT, NULL)) {
|
||
+ event_del(pool->timeout);
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Removed timeout of pool %p\n", pool);
|
||
+#endif
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static int http_request_pool_socket_callback(CURL *, curl_socket_t, int, void *, void *) */
|
||
+static int http_request_pool_socket_callback(CURL *easy, curl_socket_t sock, int action, void *socket_data, void *assign_data)
|
||
+{
|
||
+ http_request_pool *pool = socket_data;
|
||
+
|
||
+ if (pool->useevents) {
|
||
+ int events = EV_PERSIST;
|
||
+ http_request_pool_event *ev = assign_data;
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+
|
||
+ if (!ev) {
|
||
+ ev = ecalloc(1, sizeof(http_request_pool_event));
|
||
+ ev->pool = pool;
|
||
+ curl_multi_assign(pool->ch, sock, ev);
|
||
+ event_base_set(HTTP_G->request.pool.event.base, &ev->evnt);
|
||
+ } else {
|
||
+ event_del(&ev->evnt);
|
||
+ }
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ {
|
||
+ static const char action_strings[][8] = {"NONE", "IN", "OUT", "INOUT", "REMOVE"};
|
||
+ http_request *r;
|
||
+ curl_easy_getinfo(easy, CURLINFO_PRIVATE, &r);
|
||
+ fprintf(stderr, "Callback on socket %2d (%8s) event %p of pool %p (%d)\n", (int) sock, action_strings[action], ev, pool, pool->unfinished);
|
||
+ }
|
||
+#endif
|
||
+
|
||
+ switch (action) {
|
||
+ case CURL_POLL_IN:
|
||
+ events |= EV_READ;
|
||
+ break;
|
||
+ case CURL_POLL_OUT:
|
||
+ events |= EV_WRITE;
|
||
+ break;
|
||
+ case CURL_POLL_INOUT:
|
||
+ events |= EV_READ|EV_WRITE;
|
||
+ break;
|
||
+
|
||
+ case CURL_POLL_REMOVE:
|
||
+ efree(ev);
|
||
+ case CURL_POLL_NONE:
|
||
+ return 0;
|
||
+
|
||
+ default:
|
||
+ http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown socket action %d", action);
|
||
+ return -1;
|
||
+ }
|
||
+
|
||
+ event_set(&ev->evnt, sock, events, http_request_pool_event_callback, ev);
|
||
+ event_add(&ev->evnt, NULL);
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ static void http_request_pool_timer_callback(CURLM *, long, void*) */
|
||
+static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data)
|
||
+{
|
||
+ http_request_pool *pool = timer_data;
|
||
+
|
||
+ if (pool->useevents) {
|
||
+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
|
||
+ struct timeval timeout;
|
||
+
|
||
+ if (!event_initialized(pool->timeout)) {
|
||
+ event_set(pool->timeout, -1, 0, http_request_pool_timeout_callback, pool);
|
||
+ event_base_set(HTTP_G->request.pool.event.base, pool->timeout);
|
||
+ } else if (event_pending(pool->timeout, EV_TIMEOUT, NULL)) {
|
||
+ event_del(pool->timeout);
|
||
+ }
|
||
+
|
||
+ if (timeout_ms > 0) {
|
||
+ timeout.tv_sec = timeout_ms / 1000;
|
||
+ timeout.tv_usec = (timeout_ms % 1000) * 1000;
|
||
+ } else {
|
||
+ http_request_pool_timeout(pool, &timeout);
|
||
+ }
|
||
+
|
||
+ event_add(pool->timeout, &timeout);
|
||
+
|
||
+#if HTTP_DEBUG_REQPOOLS
|
||
+ fprintf(stderr, "Updating timeout %lu (%lu, %lu) of pool %p\n", (ulong) timeout_ms, (ulong) timeout.tv_sec, (ulong) timeout.tv_usec, pool);
|
||
+#endif
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+#endif /* HTTP_HAVE_EVENT */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
|
||
+
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_requestdatashare_object.c
|
||
@@ -0,0 +1,315 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_requestdatashare_object.c 300299 2010-06-09 06:23:16Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
|
||
+
|
||
+#include "zend_interfaces.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_object.h"
|
||
+#include "php_http_request_datashare_api.h"
|
||
+#include "php_http_requestdatashare_object.h"
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestDataShare, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestDataShare, method, 0)
|
||
+#define HTTP_RSHARE_ME(method, visibility) PHP_ME(HttpRequestDataShare, method, HTTP_ARGS(HttpRequestDataShare, method), visibility)
|
||
+
|
||
+#if defined(HAVE_SPL) && !defined(WONKY)
|
||
+/* SPL doesn't install its headers */
|
||
+extern PHPAPI zend_class_entry *spl_ce_Countable;
|
||
+#endif
|
||
+
|
||
+HTTP_EMPTY_ARGS(__destruct);
|
||
+HTTP_EMPTY_ARGS(count);
|
||
+
|
||
+HTTP_BEGIN_ARGS(attach, 1)
|
||
+ HTTP_ARG_OBJ(HttpRequest, request, 0)
|
||
+HTTP_END_ARGS;
|
||
+HTTP_BEGIN_ARGS(detach, 1)
|
||
+ HTTP_ARG_OBJ(HttpRequest, request, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(reset);
|
||
+
|
||
+HTTP_BEGIN_ARGS(factory, 0)
|
||
+ HTTP_ARG_VAL(global, 0)
|
||
+ HTTP_ARG_VAL(class_name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+#ifndef WONKY
|
||
+HTTP_BEGIN_ARGS(singleton, 0)
|
||
+ HTTP_ARG_VAL(global, 0)
|
||
+HTTP_END_ARGS;
|
||
+#endif
|
||
+
|
||
+
|
||
+#define http_requestdatashare_object_read_prop _http_requestdatashare_object_read_prop
|
||
+static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC);
|
||
+#define http_requestdatashare_object_write_prop _http_requestdatashare_object_write_prop
|
||
+static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC);
|
||
+#define http_requestdatashare_instantiate(t, g) _http_requestdatashare_instantiate((t), (g) TSRMLS_CC)
|
||
+static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC);
|
||
+
|
||
+#define THIS_CE http_requestdatashare_object_ce
|
||
+zend_class_entry *http_requestdatashare_object_ce;
|
||
+zend_function_entry http_requestdatashare_object_fe[] = {
|
||
+ HTTP_RSHARE_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
|
||
+ HTTP_RSHARE_ME(count, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RSHARE_ME(attach, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RSHARE_ME(detach, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RSHARE_ME(reset, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RSHARE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+#ifndef WONKY
|
||
+ HTTP_RSHARE_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||
+#endif
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+static zend_object_handlers http_requestdatashare_object_handlers;
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_requestdatashare_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS_EX(HttpRequestDataShare, http_requestdatashare_object, NULL, 0);
|
||
+ http_requestdatashare_object_handlers.clone_obj = NULL;
|
||
+ http_requestdatashare_object_handlers.read_property = http_requestdatashare_object_read_prop;
|
||
+ http_requestdatashare_object_handlers.write_property = http_requestdatashare_object_write_prop;
|
||
+
|
||
+#if defined(HAVE_SPL) && !defined(WONKY)
|
||
+ zend_class_implements(http_requestdatashare_object_ce TSRMLS_CC, 1, spl_ce_Countable);
|
||
+#endif
|
||
+
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("cookie")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("dns")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("ssl")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("connect")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ return http_requestdatashare_object_new_ex(ce, NULL, NULL);
|
||
+}
|
||
+
|
||
+zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ http_requestdatashare_object *o;
|
||
+
|
||
+ o = ecalloc(1, sizeof(http_requestdatashare_object));
|
||
+ o->zo.ce = ce;
|
||
+
|
||
+ if (share) {
|
||
+ o->share = share;
|
||
+ } else {
|
||
+ o->share = http_request_datashare_new();
|
||
+ }
|
||
+
|
||
+ if (ptr) {
|
||
+ *ptr = o;
|
||
+ }
|
||
+
|
||
+ ALLOC_HASHTABLE(OBJ_PROP(o));
|
||
+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+
|
||
+ ov.handle = putObject(http_requestdatashare_object, o);
|
||
+ ov.handlers = &http_requestdatashare_object_handlers;
|
||
+
|
||
+ return ov;
|
||
+}
|
||
+
|
||
+void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC)
|
||
+{
|
||
+ http_requestdatashare_object *o = (http_requestdatashare_object *) object;
|
||
+
|
||
+ if (!o->share->persistent) {
|
||
+ http_request_datashare_free(&o->share);
|
||
+ }
|
||
+ freeObject(o);
|
||
+}
|
||
+
|
||
+static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC)
|
||
+{
|
||
+ if (type == BP_VAR_W && zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)) {
|
||
+ zend_error(E_ERROR, "Cannot access HttpRequestDataShare default properties by reference or array key/index");
|
||
+ return NULL;
|
||
+ }
|
||
+
|
||
+ return zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC);
|
||
+}
|
||
+
|
||
+static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC)
|
||
+{
|
||
+ if (zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)) {
|
||
+ int status;
|
||
+ getObjectEx(http_requestdatashare_object, obj, object);
|
||
+
|
||
+ status = http_request_datashare_set(obj->share, Z_STRVAL_P(member), Z_STRLEN_P(member), (zend_bool) i_zend_is_true(value));
|
||
+ if (SUCCESS != status) {
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC);
|
||
+}
|
||
+
|
||
+/* {{{ proto void HttpRequestDataShare::__destruct()
|
||
+ Clean up HttpRequestDataShare object. */
|
||
+PHP_METHOD(HttpRequestDataShare, __destruct)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_requestdatashare_object, obj);
|
||
+ http_request_datashare_detach_all(obj->share);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpRequestDataShare::count()
|
||
+ Implements Countable::count(). */
|
||
+PHP_METHOD(HttpRequestDataShare, count)
|
||
+{
|
||
+ getObject(http_requestdatashare_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ RETURN_LONG(zend_llist_count(HTTP_RSHARE_HANDLES(obj->share)));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+PHP_METHOD(HttpRequestDataShare, attach)
|
||
+{
|
||
+ zval *request;
|
||
+ getObject(http_requestdatashare_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_request_datashare_attach(obj->share, request));
|
||
+}
|
||
+
|
||
+PHP_METHOD(HttpRequestDataShare, detach)
|
||
+{
|
||
+ zval *request;
|
||
+ getObject(http_requestdatashare_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_request_datashare_detach(obj->share, request));
|
||
+}
|
||
+
|
||
+PHP_METHOD(HttpRequestDataShare, reset)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_requestdatashare_object, obj);
|
||
+ http_request_datashare_detach_all(obj->share);
|
||
+ }
|
||
+}
|
||
+
|
||
+PHP_METHOD(HttpRequestDataShare, factory)
|
||
+{
|
||
+ zend_bool global = 0;
|
||
+ char *cn = NULL;
|
||
+ int cl = 0;
|
||
+ zend_object_value ov;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs", &global, &cn, &cl) &&
|
||
+ SUCCESS == http_object_new(&ov, cn, cl, _http_requestdatashare_object_new_ex, http_requestdatashare_object_ce, NULL, NULL)) {
|
||
+ RETVAL_OBJVAL(ov, 0);
|
||
+ http_requestdatashare_instantiate(return_value, global);
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+
|
||
+#ifndef WONKY
|
||
+/* {{{ proto static HttpRequestDataShare HttpRequestDataShare::singleton([bool global = false])
|
||
+ Get a single instance (differentiates between the global setting). */
|
||
+PHP_METHOD(HttpRequestDataShare, singleton)
|
||
+{
|
||
+ zend_bool global = 0;
|
||
+ zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) {
|
||
+ zval **zobj_ptr = NULL, *zobj = NULL;
|
||
+
|
||
+ if (Z_TYPE_P(instance) == IS_ARRAY) {
|
||
+ if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) {
|
||
+ RETVAL_ZVAL(*zobj_ptr, 1, 0);
|
||
+ } else {
|
||
+ zobj = http_requestdatashare_instantiate(NULL, global);
|
||
+ add_index_zval(instance, global, zobj);
|
||
+ RETVAL_OBJECT(zobj, 1);
|
||
+ }
|
||
+ } else {
|
||
+ MAKE_STD_ZVAL(instance);
|
||
+ array_init(instance);
|
||
+
|
||
+ zobj = http_requestdatashare_instantiate(NULL, global);
|
||
+ add_index_zval(instance, global, zobj);
|
||
+ RETVAL_OBJECT(zobj, 1);
|
||
+
|
||
+ zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC);
|
||
+ zval_ptr_dtor(&instance);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+#endif /* !WONKY */
|
||
+
|
||
+static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC)
|
||
+{
|
||
+ if (!this_ptr) {
|
||
+ MAKE_STD_ZVAL(this_ptr);
|
||
+ Z_TYPE_P(this_ptr) = IS_OBJECT;
|
||
+ this_ptr->value.obj = http_requestdatashare_object_new_ex(http_requestdatashare_object_ce, global ? http_request_datashare_global_get() : NULL, NULL);
|
||
+ }
|
||
+ if (global) {
|
||
+ if (HTTP_G->request.datashare.cookie) {
|
||
+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("cookie")-1, HTTP_G->request.datashare.cookie TSRMLS_CC);
|
||
+ }
|
||
+ if (HTTP_G->request.datashare.dns) {
|
||
+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("dns")-1, HTTP_G->request.datashare.dns TSRMLS_CC);
|
||
+ }
|
||
+ if (HTTP_G->request.datashare.ssl) {
|
||
+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("ssl")-1, HTTP_G->request.datashare.ssl TSRMLS_CC);
|
||
+ }
|
||
+ if (HTTP_G->request.datashare.connect) {
|
||
+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("connect")-1, HTTP_G->request.datashare.connect TSRMLS_CC);
|
||
+ }
|
||
+ }
|
||
+ return this_ptr;
|
||
+}
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_requestpool_object.c
|
||
@@ -0,0 +1,466 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_requestpool_object.c 300299 2010-06-09 06:23:16Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_CURL
|
||
+#include "php_http.h"
|
||
+
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
|
||
+
|
||
+#include "zend_interfaces.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_object.h"
|
||
+#include "php_http_request_pool_api.h"
|
||
+#include "php_http_requestpool_object.h"
|
||
+
|
||
+#if defined(HAVE_SPL) && !defined(WONKY)
|
||
+/* SPL doesn't install its headers */
|
||
+extern PHPAPI zend_class_entry *spl_ce_Countable;
|
||
+#endif
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestPool, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestPool, method, 0)
|
||
+#define HTTP_REQPOOL_ME(method, visibility) PHP_ME(HttpRequestPool, method, HTTP_ARGS(HttpRequestPool, method), visibility)
|
||
+
|
||
+HTTP_EMPTY_ARGS(__construct);
|
||
+
|
||
+HTTP_EMPTY_ARGS(__destruct);
|
||
+HTTP_EMPTY_ARGS(reset);
|
||
+
|
||
+HTTP_BEGIN_ARGS(attach, 1)
|
||
+ HTTP_ARG_OBJ(HttpRequest, request, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(detach, 1)
|
||
+ HTTP_ARG_OBJ(HttpRequest, request, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(send);
|
||
+HTTP_EMPTY_ARGS(socketPerform);
|
||
+HTTP_BEGIN_ARGS(socketSelect, 0)
|
||
+ HTTP_ARG_VAL(timeout, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(valid);
|
||
+HTTP_EMPTY_ARGS(current);
|
||
+HTTP_EMPTY_ARGS(key);
|
||
+HTTP_EMPTY_ARGS(next);
|
||
+HTTP_EMPTY_ARGS(rewind);
|
||
+
|
||
+HTTP_EMPTY_ARGS(count);
|
||
+
|
||
+HTTP_EMPTY_ARGS(getAttachedRequests);
|
||
+HTTP_EMPTY_ARGS(getFinishedRequests);
|
||
+
|
||
+HTTP_BEGIN_ARGS(enablePipelining, 0)
|
||
+ HTTP_ARG_VAL(enable, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(enableEvents, 0)
|
||
+ HTTP_ARG_VAL(enable, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+zend_class_entry *http_requestpool_object_ce;
|
||
+zend_function_entry http_requestpool_object_fe[] = {
|
||
+ HTTP_REQPOOL_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
|
||
+ HTTP_REQPOOL_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
|
||
+ HTTP_REQPOOL_ME(attach, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(detach, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(send, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(reset, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQPOOL_ME(socketPerform, ZEND_ACC_PROTECTED)
|
||
+ HTTP_REQPOOL_ME(socketSelect, ZEND_ACC_PROTECTED)
|
||
+
|
||
+ /* implements Iterator */
|
||
+ HTTP_REQPOOL_ME(valid, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(current, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(key, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(next, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(rewind, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ /* implmenents Countable */
|
||
+ HTTP_REQPOOL_ME(count, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQPOOL_ME(getAttachedRequests, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(getFinishedRequests, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_REQPOOL_ME(enablePipelining, ZEND_ACC_PUBLIC)
|
||
+ HTTP_REQPOOL_ME(enableEvents, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+static zend_object_handlers http_requestpool_object_handlers;
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_requestpool_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS_EX(HttpRequestPool, http_requestpool_object, NULL, 0);
|
||
+ http_requestpool_object_handlers.clone_obj = NULL;
|
||
+
|
||
+#if defined(HAVE_SPL) && !defined(WONKY)
|
||
+ zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 2, spl_ce_Countable, zend_ce_iterator);
|
||
+#else
|
||
+ zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 1, zend_ce_iterator);
|
||
+#endif
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC)
|
||
+{
|
||
+ zend_object_value ov;
|
||
+ http_requestpool_object *o;
|
||
+
|
||
+ o = ecalloc(1, sizeof(http_requestpool_object));
|
||
+ o->zo.ce = ce;
|
||
+
|
||
+ http_request_pool_init(&o->pool);
|
||
+
|
||
+ ALLOC_HASHTABLE(OBJ_PROP(o));
|
||
+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
|
||
+
|
||
+ ov.handle = putObject(http_requestpool_object, o);
|
||
+ ov.handlers = &http_requestpool_object_handlers;
|
||
+
|
||
+ return ov;
|
||
+}
|
||
+
|
||
+void _http_requestpool_object_free(zend_object *object TSRMLS_DC)
|
||
+{
|
||
+ http_requestpool_object *o = (http_requestpool_object *) object;
|
||
+
|
||
+ http_request_pool_dtor(&o->pool);
|
||
+ freeObject(o);
|
||
+}
|
||
+
|
||
+#define http_requestpool_object_llist2array _http_requestpool_object_llist2array
|
||
+static void _http_requestpool_object_llist2array(zval **req, zval *array TSRMLS_DC)
|
||
+{
|
||
+ ZVAL_ADDREF(*req);
|
||
+ add_next_index_zval(array, *req);
|
||
+}
|
||
+
|
||
+/* ### USERLAND ### */
|
||
+
|
||
+/* {{{ proto void HttpRequestPool::__construct([HttpRequest request[, ...]])
|
||
+ Creates a new HttpRequestPool object instance. */
|
||
+PHP_METHOD(HttpRequestPool, __construct)
|
||
+{
|
||
+ int argc = ZEND_NUM_ARGS();
|
||
+ zval ***argv = safe_emalloc(argc, sizeof(zval *), 0);
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_get_parameters_array_ex(argc, argv)) {
|
||
+ int i;
|
||
+
|
||
+ for (i = 0; i < argc; ++i) {
|
||
+ if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), http_request_object_ce TSRMLS_CC)) {
|
||
+ http_request_pool_attach(&obj->pool, *(argv[i]));
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ efree(argv);
|
||
+ http_final(HTTP_EX_CE(request_pool));
|
||
+ SET_EH_NORMAL();
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpRequestPool::__destruct()
|
||
+ Clean up HttpRequestPool object. */
|
||
+PHP_METHOD(HttpRequestPool, __destruct)
|
||
+{
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ http_request_pool_detach_all(&obj->pool);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpRequestPool::reset()
|
||
+ Detach all attached HttpRequest objects. */
|
||
+PHP_METHOD(HttpRequestPool, reset)
|
||
+{
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ obj->iterator.pos = 0;
|
||
+ http_request_pool_detach_all(&obj->pool);
|
||
+}
|
||
+
|
||
+/* {{{ proto bool HttpRequestPool::attach(HttpRequest request)
|
||
+ Attach an HttpRequest object to this HttpRequestPool. WARNING: set all options prior attaching! */
|
||
+PHP_METHOD(HttpRequestPool, attach)
|
||
+{
|
||
+ zval *request;
|
||
+ STATUS status = FAILURE;
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
|
||
+ if (obj->iterator.pos > 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles)) {
|
||
+ http_error(HE_THROW, HTTP_E_REQUEST_POOL, "Cannot attach to the HttpRequestPool while the iterator is active");
|
||
+ } else {
|
||
+ status = http_request_pool_attach(&obj->pool, request);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+ RETURN_SUCCESS(status);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequestPool::detach(HttpRequest request)
|
||
+ Detach an HttpRequest object from this HttpRequestPool. */
|
||
+PHP_METHOD(HttpRequestPool, detach)
|
||
+{
|
||
+ zval *request;
|
||
+ STATUS status = FAILURE;
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
|
||
+ obj->iterator.pos = -1;
|
||
+ status = http_request_pool_detach(&obj->pool, request);
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+ RETURN_SUCCESS(status);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequestPool::send()
|
||
+ Send all attached HttpRequest objects in parallel. */
|
||
+PHP_METHOD(HttpRequestPool, send)
|
||
+{
|
||
+ STATUS status;
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ SET_EH_THROW_HTTP();
|
||
+ status = http_request_pool_send(&obj->pool);
|
||
+ SET_EH_NORMAL();
|
||
+
|
||
+ /* rethrow as HttpRequestPoolException */
|
||
+ http_final(HTTP_EX_CE(request_pool));
|
||
+
|
||
+ RETURN_SUCCESS(status);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto protected bool HttpRequestPool::socketPerform()
|
||
+ Returns TRUE until each request has finished its transaction. */
|
||
+PHP_METHOD(HttpRequestPool, socketPerform)
|
||
+{
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (0 < http_request_pool_perform(&obj->pool)) {
|
||
+ RETURN_TRUE;
|
||
+ } else {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto protected bool HttpRequestPool::socketSelect([double timeout]) */
|
||
+PHP_METHOD(HttpRequestPool, socketSelect)
|
||
+{
|
||
+ double timeout = 0;
|
||
+ struct timeval custom_timeout, *custom_timeout_ptr = NULL;
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|d", &timeout)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (ZEND_NUM_ARGS() && timeout > 0) {
|
||
+ custom_timeout.tv_sec = (time_t) timeout;
|
||
+ custom_timeout.tv_usec = HTTP_USEC(timeout) % HTTP_MCROSEC;
|
||
+ custom_timeout_ptr = &custom_timeout;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(http_request_pool_select_ex(&obj->pool, custom_timeout_ptr));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequestPool::valid()
|
||
+ Implements Iterator::valid(). */
|
||
+PHP_METHOD(HttpRequestPool, valid)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_requestpool_object, obj);
|
||
+ RETURN_BOOL(obj->iterator.pos >= 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto HttpRequest HttpRequestPool::current()
|
||
+ Implements Iterator::current(). */
|
||
+PHP_METHOD(HttpRequestPool, current)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ long pos = 0;
|
||
+ zval **current = NULL;
|
||
+ zend_llist_position lpos;
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ if (obj->iterator.pos < zend_llist_count(&obj->pool.handles)) {
|
||
+ for ( current = zend_llist_get_first_ex(&obj->pool.handles, &lpos);
|
||
+ current && obj->iterator.pos != pos++;
|
||
+ current = zend_llist_get_next_ex(&obj->pool.handles, &lpos));
|
||
+ if (current) {
|
||
+ RETURN_OBJECT(*current, 1);
|
||
+ }
|
||
+ }
|
||
+ RETURN_NULL();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpRequestPool::key()
|
||
+ Implements Iterator::key(). */
|
||
+PHP_METHOD(HttpRequestPool, key)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ getObject(http_requestpool_object, obj);
|
||
+ RETURN_LONG(obj->iterator.pos);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpRequestPool::next()
|
||
+ Implements Iterator::next(). */
|
||
+PHP_METHOD(HttpRequestPool, next)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_requestpool_object, obj);
|
||
+ ++(obj->iterator.pos);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto void HttpRequestPool::rewind()
|
||
+ Implements Iterator::rewind(). */
|
||
+PHP_METHOD(HttpRequestPool, rewind)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_requestpool_object, obj);
|
||
+ obj->iterator.pos = 0;
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto int HttpRequestPool::count()
|
||
+ Implements Countable::count(). */
|
||
+PHP_METHOD(HttpRequestPool, count)
|
||
+{
|
||
+ NO_ARGS {
|
||
+ getObject(http_requestpool_object, obj);
|
||
+ RETURN_LONG((long) zend_llist_count(&obj->pool.handles));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequestPool::getAttachedRequests()
|
||
+ Get attached HttpRequest objects. */
|
||
+PHP_METHOD(HttpRequestPool, getAttachedRequests)
|
||
+{
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ array_init(return_value);
|
||
+ zend_llist_apply_with_argument(&obj->pool.handles,
|
||
+ (llist_apply_with_arg_func_t) http_requestpool_object_llist2array,
|
||
+ return_value TSRMLS_CC);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto array HttpRequestPool::getFinishedRequests()
|
||
+ Get attached HttpRequest objects that already have finished their work. */
|
||
+PHP_METHOD(HttpRequestPool, getFinishedRequests)
|
||
+{
|
||
+ getObject(http_requestpool_object, obj);
|
||
+
|
||
+ NO_ARGS;
|
||
+
|
||
+ array_init(return_value);
|
||
+ zend_llist_apply_with_argument(&obj->pool.finished,
|
||
+ (llist_apply_with_arg_func_t) http_requestpool_object_llist2array,
|
||
+ return_value TSRMLS_CC);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequestPool::enablePipelining([bool enable = true])
|
||
+ Enables pipelining support for all attached requests if support in libcurl is given. */
|
||
+PHP_METHOD(HttpRequestPool, enablePipelining)
|
||
+{
|
||
+ zend_bool enable = 1;
|
||
+#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0)
|
||
+ getObject(http_requestpool_object, obj);
|
||
+#endif
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0)
|
||
+ if (CURLM_OK == curl_multi_setopt(obj->pool.ch, CURLMOPT_PIPELINING, (long) enable)) {
|
||
+ RETURN_TRUE;
|
||
+ }
|
||
+#endif
|
||
+ RETURN_FALSE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto bool HttpRequestPool::enableEvents([bool enable = true])
|
||
+ Enables event-driven I/O if support in libcurl is given. */
|
||
+PHP_METHOD(HttpRequestPool, enableEvents)
|
||
+{
|
||
+ zend_bool enable = 1;
|
||
+#if defined(HTTP_HAVE_EVENT)
|
||
+ getObject(http_requestpool_object, obj);
|
||
+#endif
|
||
+
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) {
|
||
+#if defined(HTTP_HAVE_EVENT)
|
||
+ obj->pool.useevents = enable;
|
||
+ RETURN_TRUE;
|
||
+#endif
|
||
+ }
|
||
+ RETURN_FALSE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_response_object.c
|
||
@@ -0,0 +1,915 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_response_object.c 298891 2010-05-03 08:26:38Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_MAGIC
|
||
+#include "php_http.h"
|
||
+
|
||
+/* broken static properties in PHP 5.0 */
|
||
+#if defined(ZEND_ENGINE_2) && !defined(WONKY)
|
||
+
|
||
+#include "php_ini.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_cache_api.h"
|
||
+#include "php_http_exception_object.h"
|
||
+#include "php_http_headers_api.h"
|
||
+#include "php_http_response_object.h"
|
||
+#include "php_http_send_api.h"
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpResponse, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpResponse, method, 0)
|
||
+#define HTTP_RESPONSE_ME(method, visibility) PHP_ME(HttpResponse, method, HTTP_ARGS(HttpResponse, method), visibility|ZEND_ACC_STATIC)
|
||
+#define HTTP_RESPONSE_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpResponse, method))
|
||
+
|
||
+HTTP_BEGIN_ARGS(setHeader, 1)
|
||
+ HTTP_ARG_VAL(name, 0)
|
||
+ HTTP_ARG_VAL(value, 0)
|
||
+ HTTP_ARG_VAL(replace, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(getHeader, 0)
|
||
+ HTTP_ARG_VAL(name, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getETag);
|
||
+HTTP_BEGIN_ARGS(setETag, 1)
|
||
+ HTTP_ARG_VAL(etag, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getLastModified);
|
||
+HTTP_BEGIN_ARGS(setLastModified, 1)
|
||
+ HTTP_ARG_VAL(timestamp, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getCache);
|
||
+HTTP_BEGIN_ARGS(setCache, 1)
|
||
+ HTTP_ARG_VAL(cache, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getGzip);
|
||
+HTTP_BEGIN_ARGS(setGzip, 1)
|
||
+ HTTP_ARG_VAL(gzip, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getCacheControl);
|
||
+HTTP_BEGIN_ARGS(setCacheControl, 1)
|
||
+ HTTP_ARG_VAL(cache_control, 0)
|
||
+ HTTP_ARG_VAL(max_age, 0)
|
||
+ HTTP_ARG_VAL(must_revalidate, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getContentType);
|
||
+HTTP_BEGIN_ARGS(setContentType, 1)
|
||
+ HTTP_ARG_VAL(content_type, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(guessContentType, 1)
|
||
+ HTTP_ARG_VAL(magic_file, 0)
|
||
+ HTTP_ARG_VAL(magic_mode, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getContentDisposition);
|
||
+HTTP_BEGIN_ARGS(setContentDisposition, 1)
|
||
+ HTTP_ARG_VAL(filename, 0)
|
||
+ HTTP_ARG_VAL(send_inline, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getThrottleDelay);
|
||
+HTTP_BEGIN_ARGS(setThrottleDelay, 1)
|
||
+ HTTP_ARG_VAL(seconds, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getBufferSize);
|
||
+HTTP_BEGIN_ARGS(setBufferSize, 1)
|
||
+ HTTP_ARG_VAL(bytes, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getData);
|
||
+HTTP_BEGIN_ARGS(setData, 1)
|
||
+ HTTP_ARG_VAL(data, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getStream);
|
||
+HTTP_BEGIN_ARGS(setStream, 1)
|
||
+ HTTP_ARG_VAL(stream, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getFile);
|
||
+HTTP_BEGIN_ARGS(setFile, 1)
|
||
+ HTTP_ARG_VAL(filepath, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(send, 0)
|
||
+ HTTP_ARG_VAL(clean_ob, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(capture);
|
||
+
|
||
+HTTP_BEGIN_ARGS(redirect, 0)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(params, 0)
|
||
+ HTTP_ARG_VAL(session, 0)
|
||
+ HTTP_ARG_VAL(permanent, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(status, 1)
|
||
+ HTTP_ARG_VAL(code, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_EMPTY_ARGS(getRequestHeaders);
|
||
+HTTP_EMPTY_ARGS(getRequestBody);
|
||
+HTTP_EMPTY_ARGS(getRequestBodyStream);
|
||
+
|
||
+#define THIS_CE http_response_object_ce
|
||
+zend_class_entry *http_response_object_ce;
|
||
+zend_function_entry http_response_object_fe[] = {
|
||
+
|
||
+ HTTP_RESPONSE_ME(setHeader, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getHeader, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setETag, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getETag, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setLastModified, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getLastModified, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setContentDisposition, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getContentDisposition, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setContentType, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getContentType, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(guessContentType, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setCache, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getCache, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setCacheControl, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getCacheControl, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setGzip, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getGzip, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setThrottleDelay, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getThrottleDelay, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setBufferSize, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getBufferSize, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setData, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getData, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setFile, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getFile, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(setStream, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(getStream, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ME(send, ZEND_ACC_PUBLIC)
|
||
+ HTTP_RESPONSE_ME(capture, ZEND_ACC_PUBLIC)
|
||
+
|
||
+ HTTP_RESPONSE_ALIAS(redirect, http_redirect)
|
||
+ HTTP_RESPONSE_ALIAS(status, http_send_status)
|
||
+ HTTP_RESPONSE_ALIAS(getRequestHeaders, http_get_request_headers)
|
||
+ HTTP_RESPONSE_ALIAS(getRequestBody, http_get_request_body)
|
||
+ HTTP_RESPONSE_ALIAS(getRequestBodyStream, http_get_request_body_stream)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_response_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS(HttpResponse, http_response_object, NULL, 0);
|
||
+
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("sent")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("catch")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("mode")-1, -1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("stream")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("file")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("data")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("cache")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_bool(THIS_CE, ZEND_STRS("gzip")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("eTag")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("lastModified")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("cacheControl")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("contentType")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_null(THIS_CE, ZEND_STRS("contentDisposition")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+ zend_declare_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, 0.0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
|
||
+
|
||
+#ifndef WONKY
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT")-1, HTTP_REDIRECT TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PERM")-1, HTTP_REDIRECT_PERM TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_FOUND")-1, HTTP_REDIRECT_FOUND TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_POST")-1, HTTP_REDIRECT_POST TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PROXY")-1, HTTP_REDIRECT_PROXY TSRMLS_CC);
|
||
+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_TEMP")-1, HTTP_REDIRECT_TEMP TSRMLS_CC);
|
||
+#endif /* WONKY */
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+/* ### USERLAND ### */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setHeader(string name[, mixed value[, bool replace = true]])
|
||
+ Send an HTTP header. */
|
||
+PHP_METHOD(HttpResponse, setHeader)
|
||
+{
|
||
+ zend_bool replace = 1;
|
||
+ char *name;
|
||
+ int name_len = 0;
|
||
+ zval *value = NULL;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/!b", &name, &name_len, &value, &replace)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (SG(headers_sent)) {
|
||
+ http_error(HE_WARNING, HTTP_E_HEADER, "Cannot add another header when headers have already been sent");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (!name_len) {
|
||
+ http_error(HE_WARNING, HTTP_E_HEADER, "Cannot send anonymous headers");
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ http_send_header_zval_ex(name, name_len, &value, replace);
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static mixed HttpResponse::getHeader([string name])
|
||
+ Get header(s) about to be sent. */
|
||
+PHP_METHOD(HttpResponse, getHeader)
|
||
+{
|
||
+ char *name = NULL;
|
||
+ int name_len = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (name && name_len) {
|
||
+ zval **header;
|
||
+ HashTable headers_ht;
|
||
+
|
||
+ zend_hash_init(&headers_ht, sizeof(zval *), NULL, ZVAL_PTR_DTOR, 0);
|
||
+ if ( (SUCCESS == http_get_response_headers(&headers_ht)) &&
|
||
+ (SUCCESS == zend_hash_find(&headers_ht, name, name_len + 1, (void *) &header))) {
|
||
+ RETVAL_ZVAL(*header, 1, 0);
|
||
+ } else {
|
||
+ RETVAL_NULL();
|
||
+ }
|
||
+ zend_hash_destroy(&headers_ht);
|
||
+ } else {
|
||
+ array_init(return_value);
|
||
+ http_get_response_headers(Z_ARRVAL_P(return_value));
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setCache(bool cache)
|
||
+ Whether it should be attempted to cache the entity. */
|
||
+PHP_METHOD(HttpResponse, setCache)
|
||
+{
|
||
+ zend_bool do_cache = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("cache")-1, do_cache TSRMLS_CC));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::getCache()
|
||
+ Get current caching setting. */
|
||
+PHP_METHOD(HttpResponse, getCache)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *cache = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(cache, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}}*/
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setGzip(bool gzip)
|
||
+ Enable on-thy-fly gzipping of the sent entity. */
|
||
+PHP_METHOD(HttpResponse, setGzip)
|
||
+{
|
||
+ zend_bool do_gzip = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("gzip")-1, do_gzip TSRMLS_CC));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::getGzip()
|
||
+ Get current gzipping setting. */
|
||
+PHP_METHOD(HttpResponse, getGzip)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *gzip = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(gzip, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setCacheControl(string control[, int max_age = 0[, bool must_revalidate = true]])
|
||
+ Set a custom cache-control header, usually being "private" or "public"; The max_age parameter controls how long the cache entry is valid on the client side. */
|
||
+PHP_METHOD(HttpResponse, setCacheControl)
|
||
+{
|
||
+ char *ccontrol, *cctl;
|
||
+ int cc_len;
|
||
+ long max_age = 0;
|
||
+ zend_bool must_revalidate = 1;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &ccontrol, &cc_len, &max_age, &must_revalidate)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache")) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
|
||
+ RETURN_FALSE;
|
||
+ } else {
|
||
+ size_t cctl_len = spprintf(&cctl, 0, "%s,%s max-age=%ld", ccontrol, must_revalidate?" must-revalidate,":"", max_age);
|
||
+ RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("cacheControl")-1, cctl, cctl_len TSRMLS_CC));
|
||
+ efree(cctl);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static string HttpResponse::getCacheControl()
|
||
+ Get current Cache-Control header setting. */
|
||
+PHP_METHOD(HttpResponse, getCacheControl)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(cctl, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setContentType(string content_type)
|
||
+ Set the content-type of the sent entity. */
|
||
+PHP_METHOD(HttpResponse, setContentType)
|
||
+{
|
||
+ char *ctype;
|
||
+ int ctype_len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
|
||
+ RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentType")-1, ctype, ctype_len TSRMLS_CC));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static string HttpResponse::getContentType()
|
||
+ Get current Content-Type header setting. */
|
||
+PHP_METHOD(HttpResponse, getContentType)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(ctype, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static string HttpResponse::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
|
||
+ Attempts to guess the content type of supplied payload through libmagic. */
|
||
+PHP_METHOD(HttpResponse, guessContentType)
|
||
+{
|
||
+#ifdef HTTP_HAVE_MAGIC
|
||
+ char *magic_file, *ct = NULL;
|
||
+ int magic_file_len;
|
||
+ long magic_mode = MAGIC_MIME;
|
||
+
|
||
+ RETVAL_FALSE;
|
||
+ SET_EH_THROW_HTTP();
|
||
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
|
||
+ switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
|
||
+ case SEND_DATA:
|
||
+ {
|
||
+ zval *data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
|
||
+ ct = http_guess_content_type(magic_file, magic_mode, Z_STRVAL_P(data), Z_STRLEN_P(data), SEND_DATA);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case SEND_RSRC:
|
||
+ {
|
||
+ php_stream *s;
|
||
+ zval *z = *zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
|
||
+ z->type = IS_RESOURCE;
|
||
+ php_stream_from_zval(s, &z);
|
||
+ ct = http_guess_content_type(magic_file, magic_mode, s, 0, SEND_RSRC);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ default:
|
||
+ ct = http_guess_content_type(magic_file, magic_mode, Z_STRVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)), 0, -1);
|
||
+ break;
|
||
+ }
|
||
+ if (ct) {
|
||
+ zend_update_static_property_string(THIS_CE, ZEND_STRS("contentType")-1, ct TSRMLS_CC);
|
||
+ RETVAL_STRING(ct, 0);
|
||
+ }
|
||
+ }
|
||
+ SET_EH_NORMAL();
|
||
+#else
|
||
+ http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
|
||
+ RETURN_FALSE;
|
||
+#endif
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
|
||
+ Set the Content-Disposition. */
|
||
+PHP_METHOD(HttpResponse, setContentDisposition)
|
||
+{
|
||
+ char *file, *cd;
|
||
+ int file_len;
|
||
+ size_t cd_len;
|
||
+ zend_bool send_inline = 0;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &send_inline)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ cd_len = spprintf(&cd, 0, "%s; filename=\"%s\"", send_inline ? "inline" : "attachment", file);
|
||
+ RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentDisposition")-1, cd, cd_len TSRMLS_CC));
|
||
+ efree(cd);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static string HttpResponse::getContentDisposition()
|
||
+ Get current Content-Disposition setting. */
|
||
+PHP_METHOD(HttpResponse, getContentDisposition)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *cdisp = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(cdisp, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setETag(string etag)
|
||
+ Set a custom ETag. Use this only if you know what you're doing. */
|
||
+PHP_METHOD(HttpResponse, setETag)
|
||
+{
|
||
+ char *etag;
|
||
+ int etag_len;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("eTag")-1, etag, etag_len TSRMLS_CC));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static string HttpResponse::getETag()
|
||
+ Get calculated or previously set custom ETag. */
|
||
+PHP_METHOD(HttpResponse, getETag)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(etag, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setLastModified(int timestamp)
|
||
+ Set a custom Last-Modified date. */
|
||
+PHP_METHOD(HttpResponse, setLastModified)
|
||
+{
|
||
+ long lm;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lm)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, lm TSRMLS_CC));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static int HttpResponse::getLastModified()
|
||
+ Get calculated or previously set custom Last-Modified date. */
|
||
+PHP_METHOD(HttpResponse, getLastModified)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(lmod, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setThrottleDelay(double seconds)
|
||
+ Sets the throttle delay for use with HttpResponse::setBufferSize(). */
|
||
+PHP_METHOD(HttpResponse, setThrottleDelay)
|
||
+{
|
||
+ double seconds;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ RETURN_SUCCESS(zend_update_static_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, seconds TSRMLS_CC));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static double HttpResponse::getThrottleDelay()
|
||
+ Get the current throttle delay. */
|
||
+PHP_METHOD(HttpResponse, getThrottleDelay)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *tdel = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(tdel, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setBufferSize(int bytes)
|
||
+ Sets the send buffer size for use with HttpResponse::setThrottleDelay(). */
|
||
+PHP_METHOD(HttpResponse, setBufferSize)
|
||
+{
|
||
+ long bytes;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, bytes TSRMLS_CC));
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static int HttpResponse::getBufferSize()
|
||
+ Get current buffer size. */
|
||
+PHP_METHOD(HttpResponse, getBufferSize)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(bsize, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setData(mixed data)
|
||
+ Set the data to be sent. */
|
||
+PHP_METHOD(HttpResponse, setData)
|
||
+{
|
||
+ char *etag;
|
||
+ zval *the_data;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ if (Z_TYPE_P(the_data) != IS_STRING) {
|
||
+ convert_to_string(the_data);
|
||
+ }
|
||
+
|
||
+ if ( (SUCCESS != zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC)) ||
|
||
+ (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_DATA TSRMLS_CC))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_data, SEND_DATA) TSRMLS_CC);
|
||
+ if ((etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA))) {
|
||
+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
|
||
+ efree(etag);
|
||
+ }
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static string HttpResponse::getData()
|
||
+ Get the previously set data to be sent. */
|
||
+PHP_METHOD(HttpResponse, getData)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *the_data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
|
||
+
|
||
+ RETURN_ZVAL(the_data, 1, 0);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setStream(resource stream)
|
||
+ Set the resource to be sent. */
|
||
+PHP_METHOD(HttpResponse, setStream)
|
||
+{
|
||
+ char *etag;
|
||
+ zval *the_stream;
|
||
+ php_stream *the_real_stream;
|
||
+ php_stream_statbuf ssb;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ php_stream_from_zval(the_real_stream, &the_stream);
|
||
+ if (php_stream_stat(the_real_stream, &ssb)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if ( (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("stream")-1, Z_LVAL_P(the_stream) TSRMLS_CC)) ||
|
||
+ (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_RSRC TSRMLS_CC))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+ zend_list_addref(Z_LVAL_P(the_stream));
|
||
+
|
||
+ zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_real_stream, SEND_RSRC) TSRMLS_CC);
|
||
+ if ((etag = http_etag(the_real_stream, 0, SEND_RSRC))) {
|
||
+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
|
||
+ efree(etag);
|
||
+ }
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static resource HttpResponse::getStream()
|
||
+ Get the previously set resource to be sent. */
|
||
+PHP_METHOD(HttpResponse, getStream)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *stream = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_RESOURCE(Z_LVAL_P(stream));
|
||
+ zval_ptr_dtor(&stream);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::setFile(string file)
|
||
+ Set the file to be sent. */
|
||
+PHP_METHOD(HttpResponse, setFile)
|
||
+{
|
||
+ char *the_file, *etag;
|
||
+ int file_len;
|
||
+ php_stream_statbuf ssb;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &the_file, &file_len)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if (php_stream_stat_path(the_file, &ssb)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ if ( (SUCCESS != zend_update_static_property_stringl(THIS_CE, ZEND_STRS("file")-1, the_file, file_len TSRMLS_CC)) ||
|
||
+ (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, -1 TSRMLS_CC))) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_file, -1) TSRMLS_CC);
|
||
+ if ((etag = http_etag(the_file, 0, -1))) {
|
||
+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
|
||
+ efree(etag);
|
||
+ }
|
||
+
|
||
+ RETURN_TRUE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static string HttpResponse::getFile()
|
||
+ Get the previously set file to be sent. */
|
||
+PHP_METHOD(HttpResponse, getFile)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ if (return_value_used) {
|
||
+ zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_ZVAL(file, 1, 1);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static bool HttpResponse::send([bool clean_ob = true])
|
||
+ Finally send the entity. */
|
||
+PHP_METHOD(HttpResponse, send)
|
||
+{
|
||
+ zval *sent;
|
||
+ zend_bool clean_ob = 1;
|
||
+
|
||
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) {
|
||
+ RETURN_FALSE;
|
||
+ }
|
||
+
|
||
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
|
||
+
|
||
+ sent = *zend_std_get_static_property(THIS_CE, ZEND_STRS("sent")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
|
||
+ if (Z_LVAL_P(sent)) {
|
||
+ http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, response has already been sent");
|
||
+ RETURN_FALSE;
|
||
+ } else {
|
||
+ Z_LVAL_P(sent) = 1;
|
||
+ }
|
||
+
|
||
+ /* capture mode */
|
||
+ if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("catch")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
|
||
+ zval *zetag, *the_data;
|
||
+
|
||
+ MAKE_STD_ZVAL(the_data);
|
||
+ php_ob_get_buffer(the_data TSRMLS_CC);
|
||
+ zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC);
|
||
+ ZVAL_LONG(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC), SEND_DATA);
|
||
+
|
||
+ zetag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ if (!Z_STRLEN_P(zetag)) {
|
||
+ char *etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA);
|
||
+ if (etag) {
|
||
+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
|
||
+ efree(etag);
|
||
+ }
|
||
+ }
|
||
+ zval_ptr_dtor(&the_data);
|
||
+ zval_ptr_dtor(&zetag);
|
||
+
|
||
+ clean_ob = 1;
|
||
+ }
|
||
+
|
||
+ if (clean_ob) {
|
||
+ /* interrupt on-the-fly etag generation */
|
||
+ HTTP_G->etag.started = 0;
|
||
+ /* discard previous output buffers */
|
||
+ php_end_ob_buffers(0 TSRMLS_CC);
|
||
+ }
|
||
+
|
||
+ /* caching */
|
||
+ if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
|
||
+ zval *cctl, *etag, *lmod;
|
||
+
|
||
+ lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+
|
||
+ if (Z_LVAL_P(lmod) || Z_STRLEN_P(etag)) {
|
||
+ if (Z_STRLEN_P(cctl)) {
|
||
+ http_send_cache_control(Z_STRVAL_P(cctl), Z_STRLEN_P(cctl));
|
||
+ } else {
|
||
+ http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
|
||
+ }
|
||
+ if (Z_STRLEN_P(etag)) {
|
||
+ http_send_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag));
|
||
+ }
|
||
+ if (Z_LVAL_P(lmod)) {
|
||
+ http_send_last_modified(Z_LVAL_P(lmod));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ zval_ptr_dtor(&etag);
|
||
+ zval_ptr_dtor(&lmod);
|
||
+ zval_ptr_dtor(&cctl);
|
||
+ }
|
||
+
|
||
+ /* content type */
|
||
+ {
|
||
+ zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ if (Z_STRLEN_P(ctype)) {
|
||
+ http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
|
||
+ } else {
|
||
+ char *ctypes = INI_STR("default_mimetype");
|
||
+ size_t ctlen = ctypes ? strlen(ctypes) : 0;
|
||
+
|
||
+ if (ctlen) {
|
||
+ http_send_content_type(ctypes, ctlen);
|
||
+ } else {
|
||
+ http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
|
||
+ }
|
||
+ }
|
||
+ zval_ptr_dtor(&ctype);
|
||
+ }
|
||
+
|
||
+ /* content disposition */
|
||
+ {
|
||
+ zval *cd = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ if (Z_STRLEN_P(cd)) {
|
||
+ http_send_header_ex("Content-Disposition", lenof("Content-Disposition"), Z_STRVAL_P(cd), Z_STRLEN_P(cd), 1, NULL);
|
||
+ }
|
||
+ zval_ptr_dtor(&cd);
|
||
+ }
|
||
+
|
||
+ /* throttling */
|
||
+ {
|
||
+ zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ zval *delay = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ HTTP_G->send.buffer_size = Z_LVAL_P(bsize);
|
||
+ HTTP_G->send.throttle_delay = Z_DVAL_P(delay);
|
||
+ zval_ptr_dtor(&bsize);
|
||
+ zval_ptr_dtor(&delay);
|
||
+ }
|
||
+
|
||
+ /* gzip */
|
||
+ HTTP_G->send.deflate.response = i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC));
|
||
+
|
||
+ /* send */
|
||
+ switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
|
||
+ case SEND_DATA:
|
||
+ {
|
||
+ zval *zdata = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
|
||
+ zval_ptr_dtor(&zdata);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ case SEND_RSRC:
|
||
+ {
|
||
+ php_stream *the_real_stream;
|
||
+ zval *the_stream = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ the_stream->type = IS_RESOURCE;
|
||
+ php_stream_from_zval(the_real_stream, &the_stream);
|
||
+ RETVAL_SUCCESS(http_send_stream(the_real_stream));
|
||
+ zval_ptr_dtor(&the_stream);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ default:
|
||
+ {
|
||
+ zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
|
||
+ RETVAL_SUCCESS(http_send_file(Z_STRVAL_P(file)));
|
||
+ zval_ptr_dtor(&file);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ proto static void HttpResponse::capture()
|
||
+ Capture script output.
|
||
+ */
|
||
+PHP_METHOD(HttpResponse, capture)
|
||
+{
|
||
+ NO_ARGS;
|
||
+
|
||
+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
|
||
+
|
||
+ zend_update_static_property_long(THIS_CE, ZEND_STRS("catch")-1, 1 TSRMLS_CC);
|
||
+
|
||
+ php_end_ob_buffers(0 TSRMLS_CC);
|
||
+ php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC);
|
||
+
|
||
+ /* register shutdown function */
|
||
+ {
|
||
+ zval func, retval, arg, *argp[1];
|
||
+
|
||
+ INIT_PZVAL(&arg);
|
||
+ INIT_PZVAL(&func);
|
||
+ INIT_PZVAL(&retval);
|
||
+ ZVAL_STRINGL(&func, "register_shutdown_function", lenof("register_shutdown_function"), 0);
|
||
+
|
||
+ array_init(&arg);
|
||
+ add_next_index_stringl(&arg, "HttpResponse", lenof("HttpResponse"), 1);
|
||
+ add_next_index_stringl(&arg, "send", lenof("send"), 1);
|
||
+ argp[0] = &arg;
|
||
+ call_user_function(EG(function_table), NULL, &func, &retval, 1, argp TSRMLS_CC);
|
||
+ zval_dtor(&arg);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 && !WONKY */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_send_api.c
|
||
@@ -0,0 +1,607 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_send_api.c 300299 2010-06-09 06:23:16Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_ZLIB
|
||
+#define HTTP_WANT_MAGIC
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "php_streams.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_cache_api.h"
|
||
+#include "php_http_date_api.h"
|
||
+#include "php_http_encoding_api.h"
|
||
+#include "php_http_headers_api.h"
|
||
+#include "php_http_send_api.h"
|
||
+
|
||
+/* {{{ http_flush() */
|
||
+#define http_flush(d, l) _http_flush(NULL, (d), (l) TSRMLS_CC)
|
||
+static inline void _http_flush(void *nothing, const char *data, size_t data_len TSRMLS_DC)
|
||
+{
|
||
+ PHPWRITE(data, data_len);
|
||
+ /* we really only need to flush when throttling is enabled,
|
||
+ because we push the data as fast as possible anyway if not */
|
||
+ if (HTTP_G->send.throttle_delay >= HTTP_DIFFSEC) {
|
||
+ if (OG(ob_nesting_level)) {
|
||
+ php_end_ob_buffer(1, 1 TSRMLS_CC);
|
||
+ }
|
||
+ if (!OG(implicit_flush)) {
|
||
+ sapi_flush(TSRMLS_C);
|
||
+ }
|
||
+ http_sleep(HTTP_G->send.throttle_delay);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_send_response_start */
|
||
+#define http_send_response_start(b, cl) _http_send_response_start((b), (cl) TSRMLS_CC)
|
||
+static inline void _http_send_response_start(void **buffer, size_t content_length TSRMLS_DC)
|
||
+{
|
||
+ int encoding;
|
||
+
|
||
+ if ((encoding = http_encoding_response_start(content_length, 0))) {
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ *((http_encoding_stream **) buffer) = http_encoding_deflate_stream_init(NULL,
|
||
+ (encoding == HTTP_ENCODING_GZIP) ?
|
||
+ HTTP_DEFLATE_TYPE_GZIP : HTTP_DEFLATE_TYPE_ZLIB);
|
||
+#endif
|
||
+ }
|
||
+ /* flush headers */
|
||
+ sapi_flush(TSRMLS_C);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_send_response_data_plain */
|
||
+#define http_send_response_data_plain(b, d, dl) _http_send_response_data_plain((b), (d), (dl) TSRMLS_CC)
|
||
+static inline void _http_send_response_data_plain(void **buffer, const char *data, size_t data_len TSRMLS_DC)
|
||
+{
|
||
+ if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) {
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ char *encoded;
|
||
+ size_t encoded_len;
|
||
+ http_encoding_stream *s = *((http_encoding_stream **) buffer);
|
||
+
|
||
+ http_encoding_deflate_stream_update(s, data, data_len, &encoded, &encoded_len);
|
||
+ if (HTTP_G->send.buffer_size) {
|
||
+ phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC);
|
||
+ } else {
|
||
+ http_flush(encoded, encoded_len);
|
||
+ }
|
||
+ efree(encoded);
|
||
+#else
|
||
+ http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug");
|
||
+#endif
|
||
+ } else if (HTTP_G->send.buffer_size) {
|
||
+ phpstr_chunked_output((phpstr **) buffer, data, data_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC);
|
||
+ } else {
|
||
+ http_flush(data, data_len);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_send_response_data_fetch */
|
||
+#define http_send_response_data_fetch(b, d, l, m, s, e) _http_send_response_data_fetch((b), (d), (l), (m), (s), (e) TSRMLS_CC)
|
||
+static inline void _http_send_response_data_fetch(void **buffer, const void *data, size_t data_len, http_send_mode mode, size_t begin, size_t end TSRMLS_DC)
|
||
+{
|
||
+ long bsz, got, len = end - begin;
|
||
+
|
||
+ if (!(bsz = HTTP_G->send.buffer_size)) {
|
||
+ bsz = HTTP_SENDBUF_SIZE;
|
||
+ }
|
||
+
|
||
+ switch (mode) {
|
||
+ case SEND_RSRC: {
|
||
+ php_stream *s = (php_stream *) data;
|
||
+ if (SUCCESS == php_stream_seek(s, begin, SEEK_SET)) {
|
||
+ char *buf = emalloc(bsz);
|
||
+
|
||
+ while (len > 0) {
|
||
+ got = php_stream_read(s, buf, MIN(len, bsz));
|
||
+ http_send_response_data_plain(buffer, buf, got);
|
||
+ len -= got;
|
||
+ }
|
||
+
|
||
+ efree(buf);
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ case SEND_DATA: {
|
||
+ const char *buf = ((const char *) data) + begin;
|
||
+ while (len > 0) {
|
||
+ got = MIN(len, bsz);
|
||
+ http_send_response_data_plain(buffer, buf, got);
|
||
+ len -= got;
|
||
+ buf += got;
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ EMPTY_SWITCH_DEFAULT_CASE();
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_send_response_finish */
|
||
+#define http_send_response_finish(b) _http_send_response_finish((b) TSRMLS_CC)
|
||
+static inline void _http_send_response_finish(void **buffer TSRMLS_DC)
|
||
+{
|
||
+ if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) {
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ char *encoded = NULL;
|
||
+ size_t encoded_len = 0;
|
||
+ http_encoding_stream *s = *((http_encoding_stream **) buffer);
|
||
+
|
||
+ http_encoding_deflate_stream_finish(s, &encoded, &encoded_len);
|
||
+ if (HTTP_G->send.buffer_size) {
|
||
+ phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, 0, _http_flush, NULL TSRMLS_CC);
|
||
+ } else {
|
||
+ http_flush(encoded, encoded_len);
|
||
+ }
|
||
+ http_encoding_deflate_stream_free(&s);
|
||
+ STR_FREE(encoded);
|
||
+#else
|
||
+ http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug");
|
||
+#endif
|
||
+ } else if (HTTP_G->send.buffer_size) {
|
||
+ phpstr_chunked_output((phpstr **) buffer, NULL, 0, 0, _http_flush, NULL TSRMLS_CC);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ */
|
||
+PHP_MINIT_FUNCTION(http_send)
|
||
+{
|
||
+ HTTP_LONG_CONSTANT("HTTP_REDIRECT", HTTP_REDIRECT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_PERM", HTTP_REDIRECT_PERM);
|
||
+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_FOUND", HTTP_REDIRECT_FOUND);
|
||
+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_POST", HTTP_REDIRECT_POST);
|
||
+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_PROXY", HTTP_REDIRECT_PROXY);
|
||
+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_TEMP", HTTP_REDIRECT_TEMP);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_find_header */
|
||
+typedef struct {
|
||
+ const char *h;
|
||
+ size_t l;
|
||
+} http_response_header_t;
|
||
+
|
||
+static int http_find_header(void *data, void *arg)
|
||
+{
|
||
+ http_response_header_t *h = arg;
|
||
+ sapi_header_struct *s = data;
|
||
+
|
||
+ return (!strncasecmp(s->header, h->h, h->l)) && s->header[h->l] == ':';
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_hide_header(char *) */
|
||
+PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC)
|
||
+{
|
||
+ http_response_header_t h = {name, name_len};
|
||
+ zend_llist_del_element(&SG(sapi_headers).headers, (void *) &h, http_find_header);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ void http_send_header_zval(char*, zval **, zend_bool) */
|
||
+PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC)
|
||
+{
|
||
+ if (!val || !*val || Z_TYPE_PP(val) == IS_NULL || (Z_TYPE_PP(val) == IS_STRING && !Z_STRLEN_PP(val))) {
|
||
+ http_hide_header_ex(name, name_len);
|
||
+ } else if (Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT) {
|
||
+ zend_bool first = replace;
|
||
+ zval **data_ptr;
|
||
+ HashPosition pos;
|
||
+
|
||
+ FOREACH_HASH_VAL(pos, HASH_OF(*val), data_ptr) {
|
||
+ zval *data = http_zsep(IS_STRING, *data_ptr);
|
||
+
|
||
+ http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), first, NULL);
|
||
+ zval_ptr_dtor(&data);
|
||
+ first = 0;
|
||
+ }
|
||
+ } else {
|
||
+ zval *data = http_zsep(IS_STRING, *val);
|
||
+
|
||
+ http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), replace, NULL);
|
||
+ zval_ptr_dtor(&data);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send_header(char *, char *, zend_bool) */
|
||
+PHP_HTTP_API STATUS _http_send_header_ex(const char *name, size_t name_len, const char *value, size_t value_len, zend_bool replace, char **sent_header TSRMLS_DC)
|
||
+{
|
||
+ STATUS ret;
|
||
+
|
||
+ if (value && value_len) {
|
||
+ size_t header_len = sizeof(": ") + name_len + value_len + 1;
|
||
+ char *header = emalloc(header_len + 1);
|
||
+
|
||
+ header[header_len] = '\0';
|
||
+ header_len = snprintf(header, header_len, "%s: %s", name, value);
|
||
+ ret = http_send_header_string_ex(header, header_len, replace);
|
||
+ if (sent_header) {
|
||
+ *sent_header = header;
|
||
+ } else {
|
||
+ efree(header);
|
||
+ }
|
||
+ } else {
|
||
+ http_hide_header_ex(name, name_len);
|
||
+ ret = SUCCESS;
|
||
+ }
|
||
+ return ret;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send_status_header(int, char *) */
|
||
+PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC)
|
||
+{
|
||
+ STATUS ret;
|
||
+ sapi_header_line h = {(char *) header, header_len, status};
|
||
+ if (SUCCESS != (ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, &h TSRMLS_CC))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status);
|
||
+ }
|
||
+ return ret;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send_last_modified(int) */
|
||
+PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC)
|
||
+{
|
||
+ STATUS ret;
|
||
+ char *date = http_date(t);
|
||
+
|
||
+ if (!date) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ ret = http_send_header_ex("Last-Modified", lenof("Last-Modified"), date, strlen(date), 1, sent_header);
|
||
+ efree(date);
|
||
+
|
||
+ /* remember */
|
||
+ HTTP_G->send.last_modified = t;
|
||
+
|
||
+ return ret;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send_etag(char *, size_t) */
|
||
+PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC)
|
||
+{
|
||
+ STATUS status;
|
||
+ char *etag_header;
|
||
+ size_t etag_header_len;
|
||
+
|
||
+ if (!etag_len){
|
||
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G->send.unquoted_etag);
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ etag_header_len = spprintf(&etag_header, 0, "ETag: \"%s\"", etag);
|
||
+ status = http_send_header_string_ex(etag_header, etag_header_len, 1);
|
||
+
|
||
+ /* remember */
|
||
+ STR_SET(HTTP_G->send.unquoted_etag, estrndup(etag, etag_len));
|
||
+
|
||
+ if (sent_header) {
|
||
+ *sent_header = etag_header;
|
||
+ } else {
|
||
+ efree(etag_header);
|
||
+ }
|
||
+
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send_content_type(char *, size_t) */
|
||
+PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC)
|
||
+{
|
||
+ HTTP_CHECK_CONTENT_TYPE(content_type, return FAILURE);
|
||
+
|
||
+ /* remember for multiple ranges */
|
||
+ STR_FREE(HTTP_G->send.content_type);
|
||
+ HTTP_G->send.content_type = estrndup(content_type, ct_len);
|
||
+
|
||
+ return http_send_header_ex("Content-Type", lenof("Content-Type"), content_type, ct_len, 1, NULL);
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send_content_disposition(char *, size_t, zend_bool) */
|
||
+PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC)
|
||
+{
|
||
+ STATUS status;
|
||
+ char *cd_header;
|
||
+
|
||
+ if (send_inline) {
|
||
+ cd_header = ecalloc(1, sizeof("Content-Disposition: inline; filename=\"\"") + f_len);
|
||
+ sprintf(cd_header, "Content-Disposition: inline; filename=\"%s\"", filename);
|
||
+ } else {
|
||
+ cd_header = ecalloc(1, sizeof("Content-Disposition: attachment; filename=\"\"") + f_len);
|
||
+ sprintf(cd_header, "Content-Disposition: attachment; filename=\"%s\"", filename);
|
||
+ }
|
||
+
|
||
+ status = http_send_header_string(cd_header);
|
||
+ efree(cd_header);
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send(void *, size_t, http_send_mode) */
|
||
+PHP_HTTP_API STATUS _http_send_ex(const void *data_ptr, size_t data_size, http_send_mode data_mode, zend_bool no_cache TSRMLS_DC)
|
||
+{
|
||
+ void *s = NULL;
|
||
+ HashTable ranges;
|
||
+ http_range_status range_status;
|
||
+
|
||
+ if (!data_ptr) {
|
||
+ return FAILURE;
|
||
+ }
|
||
+ if (!data_size) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ /* enable partial dl and resume */
|
||
+ http_send_header_string("Accept-Ranges: bytes");
|
||
+
|
||
+ zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||
+ range_status = http_get_request_ranges(&ranges, data_size);
|
||
+
|
||
+ switch (range_status) {
|
||
+ case RANGE_ERR:
|
||
+ {
|
||
+ zend_hash_destroy(&ranges);
|
||
+ http_send_status(416);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ case RANGE_OK:
|
||
+ {
|
||
+ /* Range Request - only send ranges if entity hasn't changed */
|
||
+ if ( http_got_server_var("HTTP_IF_RANGE") &&
|
||
+ !http_match_etag("HTTP_IF_RANGE", HTTP_G->send.unquoted_etag) &&
|
||
+ !http_match_last_modified("HTTP_IF_RANGE", HTTP_G->send.last_modified)) {
|
||
+ /* fallthrough to send full entity with 200 Ok */
|
||
+ no_cache = 1;
|
||
+ } else if ( !http_match_etag_ex("HTTP_IF_MATCH", HTTP_G->send.unquoted_etag, 0) ||
|
||
+ !http_match_last_modified_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G->send.last_modified, 0) ||
|
||
+ !http_match_last_modified_ex("HTTP_UNLESS_MODIFIED_SINCE", HTTP_G->send.last_modified, 0)) {
|
||
+ /* 412 Precondition failed */
|
||
+ zend_hash_destroy(&ranges);
|
||
+ http_send_status(412);
|
||
+ return FAILURE;
|
||
+ } else if (zend_hash_num_elements(&ranges) == 1) {
|
||
+ /* single range */
|
||
+ zval **range, **begin, **end;
|
||
+
|
||
+ if ( SUCCESS != zend_hash_index_find(&ranges, 0, (void *) &range) ||
|
||
+ SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) ||
|
||
+ SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) {
|
||
+ /* this should never happen */
|
||
+ zend_hash_destroy(&ranges);
|
||
+ http_send_status(500);
|
||
+ return FAILURE;
|
||
+ } else {
|
||
+ phpstr header;
|
||
+
|
||
+ phpstr_init(&header);
|
||
+ phpstr_appendf(&header, "Content-Range: bytes %ld-%ld/%zu", Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size);
|
||
+ phpstr_fix(&header);
|
||
+ http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
|
||
+ phpstr_dtor(&header);
|
||
+ http_send_response_start(&s, Z_LVAL_PP(end)-Z_LVAL_PP(begin)+1);
|
||
+ http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1);
|
||
+ http_send_response_finish(&s);
|
||
+ zend_hash_destroy(&ranges);
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ } else {
|
||
+ /* multi range */
|
||
+ HashPosition pos;
|
||
+ zval **range, **begin, **end;
|
||
+ const char *content_type = HTTP_G->send.content_type;
|
||
+ char boundary_str[32];
|
||
+ size_t boundary_len;
|
||
+ phpstr header, preface;
|
||
+
|
||
+ boundary_len = http_boundary(boundary_str, sizeof(boundary_str));
|
||
+ phpstr_init(&header);
|
||
+ phpstr_appendf(&header, "Content-Type: multipart/byteranges; boundary=%s", boundary_str);
|
||
+ phpstr_fix(&header);
|
||
+ http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
|
||
+ phpstr_dtor(&header);
|
||
+ http_send_response_start(&s, 0);
|
||
+
|
||
+ if (!content_type) {
|
||
+ content_type = "application/x-octetstream";
|
||
+ }
|
||
+
|
||
+ phpstr_init(&preface);
|
||
+ FOREACH_HASH_VAL(pos, &ranges, range) {
|
||
+ if ( SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) &&
|
||
+ SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) {
|
||
+
|
||
+#define HTTP_RANGE_PREFACE \
|
||
+ HTTP_CRLF "--%s" \
|
||
+ HTTP_CRLF "Content-Type: %s" \
|
||
+ HTTP_CRLF "Content-Range: bytes %ld-%ld/%zu" \
|
||
+ HTTP_CRLF HTTP_CRLF
|
||
+
|
||
+ phpstr_appendf(&preface, HTTP_RANGE_PREFACE, boundary_str, content_type, Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size);
|
||
+ phpstr_fix(&preface);
|
||
+ http_send_response_data_plain(&s, PHPSTR_VAL(&preface), PHPSTR_LEN(&preface));
|
||
+ phpstr_reset(&preface);
|
||
+ http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1);
|
||
+ }
|
||
+ }
|
||
+ phpstr_dtor(&preface);
|
||
+
|
||
+ http_send_response_data_plain(&s, HTTP_CRLF "--", lenof(HTTP_CRLF "--"));
|
||
+ http_send_response_data_plain(&s, boundary_str, boundary_len);
|
||
+ http_send_response_data_plain(&s, "--", lenof("--"));
|
||
+
|
||
+ http_send_response_finish(&s);
|
||
+ zend_hash_destroy(&ranges);
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ }
|
||
+ case RANGE_NO:
|
||
+ {
|
||
+ zend_hash_destroy(&ranges);
|
||
+
|
||
+ /* send 304 Not Modified if etag matches - DON'T return on ETag generation failure */
|
||
+ if (!no_cache && (http_interrupt_ob_etaghandler() || (HTTP_G->send.unquoted_etag != NULL))) {
|
||
+ char *etag = NULL;
|
||
+
|
||
+ if (HTTP_G->send.unquoted_etag) {
|
||
+ etag = estrdup(HTTP_G->send.unquoted_etag);
|
||
+ }
|
||
+
|
||
+ if (etag || (etag = http_etag(data_ptr, data_size, data_mode))) {
|
||
+ char *sent_header = NULL;
|
||
+
|
||
+ http_send_etag_ex(etag, strlen(etag), &sent_header);
|
||
+ if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
|
||
+ return http_exit_ex(304, sent_header, NULL, 0);
|
||
+ } else {
|
||
+ STR_FREE(sent_header);
|
||
+ /* no caching for Last-Modified if ETags really don't match */
|
||
+ no_cache = http_got_server_var("HTTP_IF_NONE_MATCH");
|
||
+ }
|
||
+ efree(etag);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* send 304 Not Modified if last modified matches */
|
||
+ if (!no_cache && HTTP_G->send.last_modified && http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G->send.last_modified)) {
|
||
+ char *sent_header = NULL;
|
||
+ http_send_last_modified_ex(HTTP_G->send.last_modified, &sent_header);
|
||
+ return http_exit_ex(304, sent_header, NULL, 0);
|
||
+ }
|
||
+
|
||
+ /* send full response */
|
||
+ http_send_response_start(&s, data_size);
|
||
+ http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, 0, data_size);
|
||
+ http_send_response_finish(&s);
|
||
+ return SUCCESS;
|
||
+ }
|
||
+ }
|
||
+ return FAILURE;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_send_stream(php_stream *) */
|
||
+PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file, zend_bool close_stream, zend_bool no_cache TSRMLS_DC)
|
||
+{
|
||
+ STATUS status;
|
||
+ php_stream_statbuf ssb;
|
||
+ int orig_flags;
|
||
+
|
||
+ if ((!file) || php_stream_stat(file, &ssb)) {
|
||
+ char *defct = sapi_get_default_content_type(TSRMLS_C);
|
||
+
|
||
+ http_hide_header("Content-Disposition");
|
||
+ http_send_content_type(defct, strlen(defct));
|
||
+ http_error(HE_WARNING, HTTP_E_RESPONSE, "File not found; stat failed");
|
||
+ STR_FREE(defct);
|
||
+
|
||
+ if (HTTP_G->send.not_found_404) {
|
||
+ http_exit_ex(404, NULL, estrdup("File not found\n"), 0);
|
||
+ }
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ orig_flags = file->flags;
|
||
+ file->flags |= PHP_STREAM_FLAG_NO_BUFFER;
|
||
+ status = http_send_ex(file, ssb.sb.st_size, SEND_RSRC, no_cache);
|
||
+ file->flags = orig_flags;
|
||
+
|
||
+ if (close_stream) {
|
||
+ php_stream_close(file);
|
||
+ }
|
||
+
|
||
+ return status;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ char *http_guess_content_type(char *magic_file, long magic_mode, void *data, size_t size, http_send_mode mode) */
|
||
+PHP_HTTP_API char *_http_guess_content_type(const char *magicfile, long magicmode, void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC)
|
||
+{
|
||
+ char *ct = NULL;
|
||
+
|
||
+#ifdef HTTP_HAVE_MAGIC
|
||
+ struct magic_set *magic = NULL;
|
||
+
|
||
+ HTTP_CHECK_OPEN_BASEDIR(magicfile, return NULL);
|
||
+
|
||
+ if (!data_ptr) {
|
||
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Supplied payload is empty");
|
||
+ } else if (!(magic = magic_open(magicmode &~ MAGIC_MIME))) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid magic mode: %ld", magicmode);
|
||
+ } else if (-1 == magic_load(magic, magicfile)) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to load magic database '%s' (%s)", magicfile, magic_error(magic));
|
||
+ } else {
|
||
+ const char *ctype = NULL;
|
||
+
|
||
+ magic_setflags(magic, magicmode);
|
||
+
|
||
+ switch (data_mode) {
|
||
+ case SEND_RSRC:
|
||
+ {
|
||
+ char *buffer;
|
||
+ size_t b_len;
|
||
+
|
||
+ b_len = php_stream_copy_to_mem(data_ptr, &buffer, 65536, 0);
|
||
+ ctype = magic_buffer(magic, buffer, b_len);
|
||
+ efree(buffer);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ case SEND_DATA:
|
||
+ ctype = magic_buffer(magic, data_ptr, data_len);
|
||
+ break;
|
||
+
|
||
+ default:
|
||
+ HTTP_CHECK_OPEN_BASEDIR(data_ptr, magic_close(magic); return NULL);
|
||
+ ctype = magic_file(magic, data_ptr);
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ if (ctype) {
|
||
+ ct = estrdup(ctype);
|
||
+ } else {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to guess Content-Type: %s", magic_error(magic));
|
||
+ }
|
||
+ }
|
||
+ if (magic) {
|
||
+ magic_close(magic);
|
||
+ }
|
||
+#else
|
||
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
|
||
+#endif
|
||
+
|
||
+ return ct;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: sw=4 ts=4 fdm=marker
|
||
+ * vim<600: sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_url_api.c
|
||
@@ -0,0 +1,482 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_url_api.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#define HTTP_WANT_SAPI
|
||
+#define HTTP_WANT_NETDB
|
||
+#include "php_http.h"
|
||
+
|
||
+#include "zend_ini.h"
|
||
+#include "php_output.h"
|
||
+#include "ext/standard/php_string.h"
|
||
+
|
||
+#include "php_http_api.h"
|
||
+#include "php_http_querystring_api.h"
|
||
+#include "php_http_url_api.h"
|
||
+
|
||
+static inline char *localhostname(void)
|
||
+{
|
||
+ char hostname[1024] = {0};
|
||
+
|
||
+#ifdef PHP_WIN32
|
||
+ if (SUCCESS == gethostname(hostname, lenof(hostname))) {
|
||
+ return estrdup(hostname);
|
||
+ }
|
||
+#elif defined(HAVE_GETHOSTNAME)
|
||
+ if (SUCCESS == gethostname(hostname, lenof(hostname))) {
|
||
+# if defined(HAVE_GETDOMAINNAME)
|
||
+ size_t hlen = strlen(hostname);
|
||
+ if (hlen <= lenof(hostname) - lenof("(none)")) {
|
||
+ hostname[hlen++] = '.';
|
||
+ if (SUCCESS == getdomainname(&hostname[hlen], lenof(hostname) - hlen)) {
|
||
+ if (!strcmp(&hostname[hlen], "(none)")) {
|
||
+ hostname[hlen - 1] = '\0';
|
||
+ }
|
||
+ return estrdup(hostname);
|
||
+ }
|
||
+ }
|
||
+# endif
|
||
+ if (strcmp(hostname, "(none)")) {
|
||
+ return estrdup(hostname);
|
||
+ }
|
||
+ }
|
||
+#endif
|
||
+ return estrndup("localhost", lenof("localhost"));
|
||
+}
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_url)
|
||
+{
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_REPLACE", HTTP_URL_REPLACE);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_JOIN_PATH", HTTP_URL_JOIN_PATH);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_JOIN_QUERY", HTTP_URL_JOIN_QUERY);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_USER", HTTP_URL_STRIP_USER);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PASS", HTTP_URL_STRIP_PASS);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_AUTH", HTTP_URL_STRIP_AUTH);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PORT", HTTP_URL_STRIP_PORT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PATH", HTTP_URL_STRIP_PATH);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_QUERY", HTTP_URL_STRIP_QUERY);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_FRAGMENT", HTTP_URL_STRIP_FRAGMENT);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_ALL", HTTP_URL_STRIP_ALL);
|
||
+ HTTP_LONG_CONSTANT("HTTP_URL_FROM_ENV", HTTP_URL_FROM_ENV);
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC)
|
||
+{
|
||
+ char *abs = NULL;
|
||
+ php_url *purl = NULL;
|
||
+
|
||
+ if (url) {
|
||
+ purl = php_url_parse(abs = estrdup(url));
|
||
+ STR_SET(abs, NULL);
|
||
+ if (!purl) {
|
||
+ http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", url);
|
||
+ return NULL;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ http_build_url(flags, purl, NULL, NULL, &abs, NULL);
|
||
+
|
||
+ if (purl) {
|
||
+ php_url_free(purl);
|
||
+ }
|
||
+
|
||
+ return abs;
|
||
+}
|
||
+
|
||
+/* {{{ void http_build_url(int flags, const php_url *, const php_url *, php_url **, char **, size_t *) */
|
||
+PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_url *new_url, php_url **url_ptr, char **url_str, size_t *url_len TSRMLS_DC)
|
||
+{
|
||
+#if defined(HAVE_GETSERVBYPORT) || defined(HAVE_GETSERVBYNAME)
|
||
+ struct servent *se;
|
||
+#endif
|
||
+ php_url *url = ecalloc(1, sizeof(php_url));
|
||
+
|
||
+#define __URLSET(u,n) \
|
||
+ ((u)&&(u)->n)
|
||
+#define __URLCPY(n) \
|
||
+ url->n = __URLSET(new_url,n) ? estrdup(new_url->n) : (__URLSET(old_url,n) ? estrdup(old_url->n) : NULL)
|
||
+
|
||
+ if (!(flags & HTTP_URL_STRIP_PORT)) {
|
||
+ url->port = __URLSET(new_url, port) ? new_url->port : ((old_url) ? old_url->port : 0);
|
||
+ }
|
||
+ if (!(flags & HTTP_URL_STRIP_USER)) {
|
||
+ __URLCPY(user);
|
||
+ }
|
||
+ if (!(flags & HTTP_URL_STRIP_PASS)) {
|
||
+ __URLCPY(pass);
|
||
+ }
|
||
+
|
||
+ __URLCPY(scheme);
|
||
+ __URLCPY(host);
|
||
+
|
||
+ if (!(flags & HTTP_URL_STRIP_PATH)) {
|
||
+ if ((flags & HTTP_URL_JOIN_PATH) && __URLSET(old_url, path) && __URLSET(new_url, path) && *new_url->path != '/') {
|
||
+ size_t old_path_len = strlen(old_url->path), new_path_len = strlen(new_url->path);
|
||
+
|
||
+ url->path = ecalloc(1, old_path_len + new_path_len + 1 + 1);
|
||
+
|
||
+ strcat(url->path, old_url->path);
|
||
+ if (url->path[old_path_len - 1] != '/') {
|
||
+ php_dirname(url->path, old_path_len);
|
||
+ strcat(url->path, "/");
|
||
+ }
|
||
+ strcat(url->path, new_url->path);
|
||
+ } else {
|
||
+ __URLCPY(path);
|
||
+ }
|
||
+ }
|
||
+ if (!(flags & HTTP_URL_STRIP_QUERY)) {
|
||
+ if ((flags & HTTP_URL_JOIN_QUERY) && __URLSET(new_url, query) && __URLSET(old_url, query)) {
|
||
+ zval qarr, qstr;
|
||
+
|
||
+ INIT_PZVAL(&qstr);
|
||
+ INIT_PZVAL(&qarr);
|
||
+ array_init(&qarr);
|
||
+
|
||
+ ZVAL_STRING(&qstr, old_url->query, 0);
|
||
+ http_querystring_modify(&qarr, &qstr);
|
||
+ ZVAL_STRING(&qstr, new_url->query, 0);
|
||
+ http_querystring_modify(&qarr, &qstr);
|
||
+
|
||
+ ZVAL_NULL(&qstr);
|
||
+ http_querystring_update(&qarr, &qstr);
|
||
+ url->query = Z_STRVAL(qstr);
|
||
+ zval_dtor(&qarr);
|
||
+ } else {
|
||
+ __URLCPY(query);
|
||
+ }
|
||
+ }
|
||
+ if (!(flags & HTTP_URL_STRIP_FRAGMENT)) {
|
||
+ __URLCPY(fragment);
|
||
+ }
|
||
+
|
||
+ if (!url->scheme) {
|
||
+ if (flags & HTTP_URL_FROM_ENV) {
|
||
+ zval *https = http_get_server_var("HTTPS", 1);
|
||
+ if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) {
|
||
+ url->scheme = estrndup("https", lenof("https"));
|
||
+ } else switch (url->port) {
|
||
+ case 443:
|
||
+ url->scheme = estrndup("https", lenof("https"));
|
||
+ break;
|
||
+
|
||
+#ifndef HAVE_GETSERVBYPORT
|
||
+ default:
|
||
+#endif
|
||
+ case 80:
|
||
+ case 0:
|
||
+ url->scheme = estrndup("http", lenof("http"));
|
||
+ break;
|
||
+
|
||
+#ifdef HAVE_GETSERVBYPORT
|
||
+ default:
|
||
+ if ((se = getservbyport(htons(url->port), "tcp")) && se->s_name) {
|
||
+ url->scheme = estrdup(se->s_name);
|
||
+ } else {
|
||
+ url->scheme = estrndup("http", lenof("http"));
|
||
+ }
|
||
+ break;
|
||
+#endif
|
||
+ }
|
||
+ } else {
|
||
+ url->scheme = estrndup("http", lenof("http"));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!url->host) {
|
||
+ if (flags & HTTP_URL_FROM_ENV) {
|
||
+ zval *zhost;
|
||
+
|
||
+ if ((((zhost = http_get_server_var("HTTP_HOST", 1)) ||
|
||
+ (zhost = http_get_server_var("SERVER_NAME", 1)))) && Z_STRLEN_P(zhost)) {
|
||
+ url->host = estrndup(Z_STRVAL_P(zhost), Z_STRLEN_P(zhost));
|
||
+ } else {
|
||
+ url->host = localhostname();
|
||
+ }
|
||
+ } else {
|
||
+ url->host = estrndup("localhost", lenof("localhost"));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (!url->path) {
|
||
+ if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) {
|
||
+ const char *q = strchr(SG(request_info).request_uri, '?');
|
||
+
|
||
+ if (q) {
|
||
+ url->path = estrndup(SG(request_info).request_uri, q - SG(request_info).request_uri);
|
||
+ } else {
|
||
+ url->path = estrdup(SG(request_info).request_uri);
|
||
+ }
|
||
+ } else {
|
||
+ url->path = estrndup("/", 1);
|
||
+ }
|
||
+ } else if (url->path[0] != '/') {
|
||
+ if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) {
|
||
+ size_t ulen = strlen(SG(request_info).request_uri);
|
||
+ size_t plen = strlen(url->path);
|
||
+ char *path;
|
||
+
|
||
+ if (SG(request_info).request_uri[ulen-1] != '/') {
|
||
+ for (--ulen; ulen && SG(request_info).request_uri[ulen - 1] != '/'; --ulen);
|
||
+ }
|
||
+
|
||
+ path = emalloc(ulen + plen + 1);
|
||
+ memcpy(path, SG(request_info).request_uri, ulen);
|
||
+ memcpy(path + ulen, url->path, plen);
|
||
+ path[ulen + plen] = '\0';
|
||
+ STR_SET(url->path, path);
|
||
+ } else {
|
||
+ size_t plen = strlen(url->path);
|
||
+ char *path = emalloc(plen + 1 + 1);
|
||
+
|
||
+ path[0] = '/';
|
||
+ memcpy(&path[1], url->path, plen + 1);
|
||
+ STR_SET(url->path, path);
|
||
+ }
|
||
+ }
|
||
+ /* replace directory references if path is not a single slash */
|
||
+ if (url->path[0] && (url->path[0] != '/' || url->path[1])) {
|
||
+ char *ptr, *end = url->path + strlen(url->path) + 1;
|
||
+
|
||
+ for (ptr = strstr(url->path, "/."); ptr; ptr = strstr(ptr, "/.")) {
|
||
+ switch (ptr[2]) {
|
||
+ case '\0':
|
||
+ ptr[1] = '\0';
|
||
+ break;
|
||
+
|
||
+ case '/':
|
||
+ memmove(&ptr[1], &ptr[3], end - &ptr[3]);
|
||
+ break;
|
||
+
|
||
+ case '.':
|
||
+ if (ptr[3] == '/') {
|
||
+ char *pos = &ptr[4];
|
||
+ while (ptr != url->path) {
|
||
+ if (*--ptr == '/') {
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ memmove(&ptr[1], pos, end - pos);
|
||
+ break;
|
||
+ } else if (!ptr[3]) {
|
||
+ /* .. at the end */
|
||
+ ptr[1] = '\0';
|
||
+ }
|
||
+ /* fallthrough */
|
||
+
|
||
+ default:
|
||
+ /* something else */
|
||
+ ++ptr;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (url->port) {
|
||
+ if ( ((url->port == 80) && !strcmp(url->scheme, "http"))
|
||
+ || ((url->port ==443) && !strcmp(url->scheme, "https"))
|
||
+#ifdef HAVE_GETSERVBYNAME
|
||
+ || ((se = getservbyname(url->scheme, "tcp")) && se->s_port &&
|
||
+ (url->port == ntohs(se->s_port)))
|
||
+#endif
|
||
+ ) {
|
||
+ url->port = 0;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (url_str) {
|
||
+ size_t len;
|
||
+
|
||
+ *url_str = emalloc(HTTP_URL_MAXLEN + 1);
|
||
+
|
||
+ **url_str = '\0';
|
||
+ strlcat(*url_str, url->scheme, HTTP_URL_MAXLEN);
|
||
+ strlcat(*url_str, "://", HTTP_URL_MAXLEN);
|
||
+
|
||
+ if (url->user && *url->user) {
|
||
+ strlcat(*url_str, url->user, HTTP_URL_MAXLEN);
|
||
+ if (url->pass && *url->pass) {
|
||
+ strlcat(*url_str, ":", HTTP_URL_MAXLEN);
|
||
+ strlcat(*url_str, url->pass, HTTP_URL_MAXLEN);
|
||
+ }
|
||
+ strlcat(*url_str, "@", HTTP_URL_MAXLEN);
|
||
+ }
|
||
+
|
||
+ strlcat(*url_str, url->host, HTTP_URL_MAXLEN);
|
||
+
|
||
+ if (url->port) {
|
||
+ char port_str[8];
|
||
+
|
||
+ snprintf(port_str, sizeof(port_str), "%d", (int) url->port);
|
||
+ strlcat(*url_str, ":", HTTP_URL_MAXLEN);
|
||
+ strlcat(*url_str, port_str, HTTP_URL_MAXLEN);
|
||
+ }
|
||
+
|
||
+ strlcat(*url_str, url->path, HTTP_URL_MAXLEN);
|
||
+
|
||
+ if (url->query && *url->query) {
|
||
+ strlcat(*url_str, "?", HTTP_URL_MAXLEN);
|
||
+ strlcat(*url_str, url->query, HTTP_URL_MAXLEN);
|
||
+ }
|
||
+
|
||
+ if (url->fragment && *url->fragment) {
|
||
+ strlcat(*url_str, "#", HTTP_URL_MAXLEN);
|
||
+ strlcat(*url_str, url->fragment, HTTP_URL_MAXLEN);
|
||
+ }
|
||
+
|
||
+ if (HTTP_URL_MAXLEN == (len = strlen(*url_str))) {
|
||
+ http_error(HE_NOTICE, HTTP_E_URL, "Length of URL exceeds HTTP_URL_MAXLEN");
|
||
+ }
|
||
+ if (url_len) {
|
||
+ *url_len = len;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ if (url_ptr) {
|
||
+ *url_ptr = url;
|
||
+ } else {
|
||
+ php_url_free(url);
|
||
+ }
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
|
||
+PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep,
|
||
+ char *pre_encoded_data, size_t pre_encoded_len,
|
||
+ char **encoded_data, size_t *encoded_len TSRMLS_DC)
|
||
+{
|
||
+ char *arg_sep;
|
||
+ size_t arg_sep_len;
|
||
+ phpstr *qstr = phpstr_new();
|
||
+
|
||
+ if (override_argsep || !(arg_sep_len = strlen(arg_sep = INI_STR("arg_separator.output")))) {
|
||
+ arg_sep = HTTP_URL_ARGSEP;
|
||
+ arg_sep_len = lenof(HTTP_URL_ARGSEP);
|
||
+ }
|
||
+
|
||
+ if (pre_encoded_len && pre_encoded_data) {
|
||
+ phpstr_append(qstr, pre_encoded_data, pre_encoded_len);
|
||
+ }
|
||
+
|
||
+ if (SUCCESS != http_urlencode_hash_recursive(hash, qstr, arg_sep, arg_sep_len, NULL, 0)) {
|
||
+ phpstr_free(&qstr);
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ phpstr_data(qstr, encoded_data, encoded_len);
|
||
+ phpstr_free(&qstr);
|
||
+
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/* {{{ http_urlencode_hash_recursive */
|
||
+PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC)
|
||
+{
|
||
+ HashKey key = initHashKey(0);
|
||
+ zval **data = NULL;
|
||
+ HashPosition pos;
|
||
+
|
||
+ if (!ht || !str) {
|
||
+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters");
|
||
+ return FAILURE;
|
||
+ }
|
||
+ if (ht->nApplyCount > 0) {
|
||
+ return SUCCESS;
|
||
+ }
|
||
+
|
||
+ FOREACH_HASH_KEYVAL(pos, ht, key, data) {
|
||
+ char *encoded_key;
|
||
+ int encoded_len;
|
||
+ phpstr new_prefix;
|
||
+
|
||
+ if (!data || !*data) {
|
||
+ phpstr_dtor(str);
|
||
+ return FAILURE;
|
||
+ }
|
||
+
|
||
+ if (key.type == HASH_KEY_IS_STRING) {
|
||
+ if (!*key.str) {
|
||
+ /* only public properties */
|
||
+ continue;
|
||
+ }
|
||
+ if (key.len && key.str[key.len - 1] == '\0') {
|
||
+ --key.len;
|
||
+ }
|
||
+ encoded_key = php_url_encode(key.str, key.len, &encoded_len);
|
||
+ } else {
|
||
+ encoded_len = spprintf(&encoded_key, 0, "%ld", key.num);
|
||
+ }
|
||
+
|
||
+ {
|
||
+ phpstr_init(&new_prefix);
|
||
+ if (prefix && prefix_len) {
|
||
+ phpstr_append(&new_prefix, prefix, prefix_len);
|
||
+ phpstr_appends(&new_prefix, "%5B");
|
||
+ }
|
||
+
|
||
+ phpstr_append(&new_prefix, encoded_key, encoded_len);
|
||
+ efree(encoded_key);
|
||
+
|
||
+ if (prefix && prefix_len) {
|
||
+ phpstr_appends(&new_prefix, "%5D");
|
||
+ }
|
||
+ phpstr_fix(&new_prefix);
|
||
+ }
|
||
+
|
||
+ if (Z_TYPE_PP(data) == IS_ARRAY || Z_TYPE_PP(data) == IS_OBJECT) {
|
||
+ STATUS status;
|
||
+ ++ht->nApplyCount;
|
||
+ status = http_urlencode_hash_recursive(HASH_OF(*data), str, arg_sep, arg_sep_len, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
|
||
+ --ht->nApplyCount;
|
||
+ if (SUCCESS != status) {
|
||
+ phpstr_dtor(&new_prefix);
|
||
+ phpstr_dtor(str);
|
||
+ return FAILURE;
|
||
+ }
|
||
+ } else {
|
||
+ zval *val = http_zsep(IS_STRING, *data);
|
||
+
|
||
+ if (PHPSTR_LEN(str)) {
|
||
+ phpstr_append(str, arg_sep, arg_sep_len);
|
||
+ }
|
||
+ phpstr_append(str, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
|
||
+ phpstr_appends(str, "=");
|
||
+
|
||
+ if (Z_STRLEN_P(val) && Z_STRVAL_P(val)) {
|
||
+ char *encoded_val;
|
||
+ int encoded_len;
|
||
+
|
||
+ encoded_val = php_url_encode(Z_STRVAL_P(val), Z_STRLEN_P(val), &encoded_len);
|
||
+ phpstr_append(str, encoded_val, encoded_len);
|
||
+ efree(encoded_val);
|
||
+ }
|
||
+
|
||
+ zval_ptr_dtor(&val);
|
||
+ }
|
||
+ phpstr_dtor(&new_prefix);
|
||
+ }
|
||
+ return SUCCESS;
|
||
+}
|
||
+/* }}} */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/http_util_object.c
|
||
@@ -0,0 +1,158 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: http_util_object.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#include "php_http.h"
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#include "ext/standard/php_http.h"
|
||
+
|
||
+#include "php_http_util_object.h"
|
||
+
|
||
+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpUtil, method, 0, req_args)
|
||
+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpUtil, method, 0)
|
||
+
|
||
+#define HTTP_UTIL_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpUtil, method))
|
||
+
|
||
+HTTP_BEGIN_ARGS(date, 0)
|
||
+ HTTP_ARG_VAL(timestamp, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(buildStr, 1)
|
||
+ HTTP_ARG_VAL(query, 0)
|
||
+ HTTP_ARG_VAL(prefix, 0)
|
||
+ HTTP_ARG_VAL(arg_sep, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(buildUrl, 1)
|
||
+ HTTP_ARG_VAL(url, 0)
|
||
+ HTTP_ARG_VAL(parts, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+ HTTP_ARG_VAL(composed, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(negotiateLanguage, 1)
|
||
+ HTTP_ARG_VAL(supported, 0)
|
||
+ HTTP_ARG_VAL(result, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(negotiateCharset, 1)
|
||
+ HTTP_ARG_VAL(supported, 0)
|
||
+ HTTP_ARG_VAL(result, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(negotiateContentType, 1)
|
||
+ HTTP_ARG_VAL(supported, 0)
|
||
+ HTTP_ARG_VAL(result, 1)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(matchModified, 1)
|
||
+ HTTP_ARG_VAL(last_modified, 0)
|
||
+ HTTP_ARG_VAL(for_range, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(matchEtag, 1)
|
||
+ HTTP_ARG_VAL(plain_etag, 0)
|
||
+ HTTP_ARG_VAL(for_range, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(matchRequestHeader, 2)
|
||
+ HTTP_ARG_VAL(header_name, 0)
|
||
+ HTTP_ARG_VAL(header_value, 0)
|
||
+ HTTP_ARG_VAL(case_sensitive, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(parseMessage, 1)
|
||
+ HTTP_ARG_VAL(message_string, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(parseHeaders, 1)
|
||
+ HTTP_ARG_VAL(headers_string, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(parseCookie, 1)
|
||
+ HTTP_ARG_VAL(cookie_string, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(buildCookie, 1)
|
||
+ HTTP_ARG_VAL(cookie_array, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(parseParams, 1)
|
||
+ HTTP_ARG_VAL(param_string, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(chunkedDecode, 1)
|
||
+ HTTP_ARG_VAL(encoded_string, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+HTTP_BEGIN_ARGS(deflate, 1)
|
||
+ HTTP_ARG_VAL(plain, 0)
|
||
+ HTTP_ARG_VAL(flags, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+HTTP_BEGIN_ARGS(inflate, 1)
|
||
+ HTTP_ARG_VAL(encoded, 0)
|
||
+HTTP_END_ARGS;
|
||
+#endif
|
||
+
|
||
+HTTP_BEGIN_ARGS(support, 0)
|
||
+ HTTP_ARG_VAL(feature, 0)
|
||
+HTTP_END_ARGS;
|
||
+
|
||
+zend_class_entry *http_util_object_ce;
|
||
+zend_function_entry http_util_object_fe[] = {
|
||
+ HTTP_UTIL_ALIAS(date, http_date)
|
||
+ HTTP_UTIL_ALIAS(buildUrl, http_build_url)
|
||
+ HTTP_UTIL_ALIAS(buildStr, http_build_str)
|
||
+ HTTP_UTIL_ALIAS(negotiateLanguage, http_negotiate_language)
|
||
+ HTTP_UTIL_ALIAS(negotiateCharset, http_negotiate_charset)
|
||
+ HTTP_UTIL_ALIAS(negotiateContentType, http_negotiate_content_type)
|
||
+ HTTP_UTIL_ALIAS(matchModified, http_match_modified)
|
||
+ HTTP_UTIL_ALIAS(matchEtag, http_match_etag)
|
||
+ HTTP_UTIL_ALIAS(matchRequestHeader, http_match_request_header)
|
||
+ HTTP_UTIL_ALIAS(parseMessage, http_parse_message)
|
||
+ HTTP_UTIL_ALIAS(parseHeaders, http_parse_headers)
|
||
+ HTTP_UTIL_ALIAS(parseCookie, http_parse_cookie)
|
||
+ HTTP_UTIL_ALIAS(buildCookie, http_build_cookie)
|
||
+ HTTP_UTIL_ALIAS(parseParams, http_parse_params)
|
||
+ HTTP_UTIL_ALIAS(chunkedDecode, http_chunked_decode)
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+ HTTP_UTIL_ALIAS(deflate, http_deflate)
|
||
+ HTTP_UTIL_ALIAS(inflate, http_inflate)
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+ HTTP_UTIL_ALIAS(support, http_support)
|
||
+
|
||
+ EMPTY_FUNCTION_ENTRY
|
||
+};
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_util_object)
|
||
+{
|
||
+ HTTP_REGISTER_CLASS(HttpUtil, http_util_object, NULL, 0);
|
||
+ return SUCCESS;
|
||
+}
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/lib/BigGet.php
|
||
@@ -0,0 +1,213 @@
|
||
+<?php
|
||
+
|
||
+/**
|
||
+ * BigGet - download big files efficiently
|
||
+ * $Id: BigGet.php 220502 2006-09-25 08:27:32Z mike $
|
||
+ *
|
||
+ * @copyright Michael Wallner, <mike@iworks.at>
|
||
+ * @license BSD, revised
|
||
+ * @version $Revision: 220502 $
|
||
+ */
|
||
+class BigGet extends HttpRequestPool
|
||
+{
|
||
+ /**
|
||
+ * File split size
|
||
+ */
|
||
+ const SIZE = 1048576;
|
||
+
|
||
+ /**
|
||
+ * Parallel Request count
|
||
+ */
|
||
+ const RMAX = 5;
|
||
+
|
||
+ /**
|
||
+ * Whether to output debug messages
|
||
+ *
|
||
+ * @var bool
|
||
+ */
|
||
+ public $dbg = false;
|
||
+
|
||
+ /**
|
||
+ * URL
|
||
+ *
|
||
+ * @var string
|
||
+ */
|
||
+ private $url;
|
||
+
|
||
+ /**
|
||
+ * Temp file prefix
|
||
+ *
|
||
+ * @var string
|
||
+ */
|
||
+ private $tmp;
|
||
+
|
||
+ /**
|
||
+ * Size of requested resource
|
||
+ *
|
||
+ * @var int
|
||
+ */
|
||
+ private $size;
|
||
+
|
||
+ /**
|
||
+ * Whether the requests have been sent
|
||
+ *
|
||
+ * @var bool
|
||
+ */
|
||
+ private $sent = false;
|
||
+
|
||
+ /**
|
||
+ * Request counter
|
||
+ *
|
||
+ * @var int
|
||
+ */
|
||
+ private $count = 0;
|
||
+
|
||
+ /**
|
||
+ * Static constructor
|
||
+ *
|
||
+ * @param string $url
|
||
+ * @param string $tmp
|
||
+ * @return BigGet
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public static function url($url, $tmp = '/tmp')
|
||
+ {
|
||
+ $head = new HttpRequest($url, HttpRequest::METH_HEAD);
|
||
+ $headers = $head->send()->getHeaders();
|
||
+
|
||
+ if (200 != $head->getResponseCode()) {
|
||
+ throw new HttpException("Did not receive '200 Ok' from HEAD $url");
|
||
+ }
|
||
+ if (!isset($headers['Accept-Ranges'])) {
|
||
+ throw new HttpException("Did not receive an Accept-Ranges header from HEAD $url");
|
||
+ }
|
||
+ if (!isset($headers['Content-Length'])) {
|
||
+ throw new HttpException("Did not receive a Content-Length header from HEAD $url");
|
||
+ }
|
||
+
|
||
+ $bigget = new BigGet;
|
||
+ $bigget->url = $url;
|
||
+ $bigget->tmp = tempnam($tmp, 'BigGet.');
|
||
+ $bigget->size = $headers['Content-Length'];
|
||
+ return $bigget;
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Save the resource to a file
|
||
+ *
|
||
+ * @param string $file
|
||
+ * @return bool
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public function saveTo($file)
|
||
+ {
|
||
+ $this->sent or $this->send();
|
||
+
|
||
+ if ($w = fopen($this->tmp, 'wb')) {
|
||
+
|
||
+ $this->dbg && print "\nCopying temp files to $file ...\n";
|
||
+
|
||
+ foreach (glob($this->tmp .".????") as $tmp) {
|
||
+
|
||
+ $this->dbg && print "\t$tmp\n";
|
||
+
|
||
+ if ($r = fopen($tmp, 'rb')) {
|
||
+ stream_copy_to_stream($r, $w);
|
||
+ fclose($r);
|
||
+ }
|
||
+ unlink($tmp);
|
||
+ }
|
||
+ fclose($w);
|
||
+ rename($this->tmp, $file);
|
||
+
|
||
+ $this->dbg && print "\nDone.\n";
|
||
+
|
||
+ return true;
|
||
+ }
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Overrides HttpRequestPool::send()
|
||
+ *
|
||
+ * @return void
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public function send()
|
||
+ {
|
||
+ $this->sent = true;
|
||
+
|
||
+ // use max RMAX simultanous requests with a req size of SIZE
|
||
+ while ($this->count < self::RMAX && -1 != $offset = $this->getRangeOffset()) {
|
||
+ $this->attachNew($offset);
|
||
+ }
|
||
+
|
||
+ while ($this->socketPerform()) {
|
||
+ if (!$this->socketSelect()) {
|
||
+ throw new HttpSocketException;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Overrides HttpRequestPool::socketPerform()
|
||
+ *
|
||
+ * @return bool
|
||
+ */
|
||
+ protected function socketPerform()
|
||
+ {
|
||
+ $rs = parent::socketPerform();
|
||
+
|
||
+ foreach ($this->getFinishedRequests() as $r) {
|
||
+ $this->detach($r);
|
||
+
|
||
+ if (206 != $rc = $r->getResponseCode()) {
|
||
+ throw new HttpException("Unexpected response code: $rc");
|
||
+ }
|
||
+
|
||
+ file_put_contents(sprintf("%s.%04d", $this->tmp, $r->id), $r->getResponseBody());
|
||
+
|
||
+ if (-1 != $offset = $this->getRangeOffset()) {
|
||
+ $this->attachNew($offset);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return $rs;
|
||
+ }
|
||
+
|
||
+ private function attachNew($offset)
|
||
+ {
|
||
+ $stop = min($this->count * self::SIZE + self::SIZE, $this->size) - 1;
|
||
+
|
||
+ $this->dbg && print "Attaching new request to get range: $offset-$stop\n";
|
||
+
|
||
+ $req = new BigGetRequest(
|
||
+ $this->url,
|
||
+ HttpRequest::METH_GET,
|
||
+ array(
|
||
+ 'headers' => array(
|
||
+ 'Range' => "bytes=$offset-$stop"
|
||
+ )
|
||
+ )
|
||
+ );
|
||
+ $this->attach($req);
|
||
+ $req->id = $this->count++;
|
||
+ }
|
||
+
|
||
+ private function getRangeOffset()
|
||
+ {
|
||
+ return ($this->size >= $start = $this->count * self::SIZE) ? $start : -1;
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+/**
|
||
+ * BigGet request
|
||
+ * @ignore
|
||
+ */
|
||
+class BigGetRequest extends HttpRequest
|
||
+{
|
||
+ public $id;
|
||
+}
|
||
+
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/lib/FeedAggregator.php
|
||
@@ -0,0 +1,187 @@
|
||
+<?php
|
||
+
|
||
+/**
|
||
+ * Simple Feed Aggregator
|
||
+ * $Id: FeedAggregator.php 208774 2006-03-06 16:07:19Z mike $
|
||
+ *
|
||
+ * @copyright Michael Wallner, <mike@iworks.at>
|
||
+ * @license BSD, revised
|
||
+ * @package pecl/http
|
||
+ * @version $Revision: 208774 $
|
||
+ */
|
||
+class FeedAggregator
|
||
+{
|
||
+ /**
|
||
+ * Cache directory
|
||
+ *
|
||
+ * @var string
|
||
+ */
|
||
+ public $directory;
|
||
+
|
||
+ /**
|
||
+ * Feeds
|
||
+ *
|
||
+ * @var array
|
||
+ */
|
||
+ protected $feeds = array();
|
||
+
|
||
+ /**
|
||
+ * Constructor
|
||
+ *
|
||
+ * @param string $directory
|
||
+ */
|
||
+ public function __construct($directory = 'feeds')
|
||
+ {
|
||
+ $this->setDirectory($directory);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Set cache directory
|
||
+ *
|
||
+ * @param string $directory
|
||
+ */
|
||
+ public function setDirectory($directory)
|
||
+ {
|
||
+ $this->directory = $directory;
|
||
+ foreach (glob($this->directory .'/*.xml') as $feed) {
|
||
+ $this->feeds[basename($feed, '.xml')] = filemtime($feed);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Strips all special chars
|
||
+ *
|
||
+ * @param string $url
|
||
+ * @return string
|
||
+ */
|
||
+ public function url2name($url)
|
||
+ {
|
||
+ return preg_replace('/[^\w\.-]+/', '_', $url);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Checks if $url is a known feed
|
||
+ *
|
||
+ * @param string $url
|
||
+ * @return bool
|
||
+ */
|
||
+ public function hasFeed($url)
|
||
+ {
|
||
+ return isset($this->feeds[$this->url2name($url)]);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Add an URL as feed
|
||
+ *
|
||
+ * @param string $url
|
||
+ * @return void
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public function addFeed($url)
|
||
+ {
|
||
+ $r = $this->setupRequest($url);
|
||
+ $r->send();
|
||
+ $this->handleResponse($r);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Add several URLs as feeds
|
||
+ *
|
||
+ * @param array $urls
|
||
+ * @return void
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public function addFeeds(array $urls)
|
||
+ {
|
||
+ $pool = new HttpRequestPool;
|
||
+ foreach ($urls as $url) {
|
||
+ $pool->attach($r = $this->setupRequest($url));
|
||
+ }
|
||
+ $pool->send();
|
||
+
|
||
+ foreach ($pool as $request) {
|
||
+ $this->handleResponse($request);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Load a feed (from cache)
|
||
+ *
|
||
+ * @param string $url
|
||
+ * @return string
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public function getFeed($url)
|
||
+ {
|
||
+ $this->addFeed($url);
|
||
+ return $this->loadFeed($this->url2name($url));
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Load several feeds (from cache)
|
||
+ *
|
||
+ * @param array $urls
|
||
+ * @return array
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public function getFeeds(array $urls)
|
||
+ {
|
||
+ $feeds = array();
|
||
+ $this->addFeeds($urls);
|
||
+ foreach ($urls as $url) {
|
||
+ $feeds[] = $this->loadFeed($this->url2name($url));
|
||
+ }
|
||
+ return $feeds;
|
||
+ }
|
||
+
|
||
+ protected function saveFeed($file, $contents)
|
||
+ {
|
||
+ if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) {
|
||
+ $this->feeds[$file] = time();
|
||
+ } else {
|
||
+ throw new Exception("Could not save feed contents to $file.xml");
|
||
+ }
|
||
+ }
|
||
+
|
||
+ protected function loadFeed($file)
|
||
+ {
|
||
+ if (isset($this->feeds[$file])) {
|
||
+ if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) {
|
||
+ return $data;
|
||
+ } else {
|
||
+ throw new Exception("Could not load feed contents from $file.xml");
|
||
+ }
|
||
+ } else {
|
||
+ throw new Exception("Unknown feed/file $file.xml");
|
||
+ }
|
||
+ }
|
||
+
|
||
+ protected function setupRequest($url, $escape = true)
|
||
+ {
|
||
+ $r = new HttpRequest($url);
|
||
+ $r->setOptions(array('redirect' => true));
|
||
+
|
||
+ $file = $escape ? $this->url2name($url) : $url;
|
||
+
|
||
+ if (isset($this->feeds[$file])) {
|
||
+ $r->setOptions(array('lastmodified' => $this->feeds[$file]));
|
||
+ }
|
||
+
|
||
+ return $r;
|
||
+ }
|
||
+
|
||
+ protected function handleResponse(HttpRequest $r)
|
||
+ {
|
||
+ if ($r->getResponseCode() != 304) {
|
||
+ if ($r->getResponseCode() != 200) {
|
||
+ throw new Exception("Unexpected response code ". $r->getResponseCode());
|
||
+ }
|
||
+ if (!strlen($body = $r->getResponseBody())) {
|
||
+ throw new Exception("Received empty feed from ". $r->getUrl());
|
||
+ }
|
||
+ $this->saveFeed($this->url2name($r->getUrl()), $body);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/lib/PgLobStream.php
|
||
@@ -0,0 +1,100 @@
|
||
+<?php
|
||
+
|
||
+/**
|
||
+ * PostgreSQL LOB stream
|
||
+ * $Id: PgLobStream.php 210232 2006-03-27 17:41:25Z mike $
|
||
+ *
|
||
+ * Usage:
|
||
+ * <code>
|
||
+ * // GET /image.php?image=1234
|
||
+ * if (PgLobStream::$loId = (int) $_GET['image']) {
|
||
+ * if ($lob = fopen('pglob://dbname=database user=mike', 'r')) {
|
||
+ * HttpResponse::setContentType('image/jpeg');
|
||
+ * HttpResponse::setStream($lob);
|
||
+ * HttpResponse::send();
|
||
+ * }
|
||
+ * }
|
||
+ * </code>
|
||
+ *
|
||
+ * @copyright Michael Wallner, <mike@iworks.at>
|
||
+ * @license BSD, revised
|
||
+ * @package pecl/http
|
||
+ * @version $Revision: 210232 $
|
||
+ */
|
||
+class PgLobStream
|
||
+{
|
||
+ private $dbh;
|
||
+ private $loh;
|
||
+ private $lon;
|
||
+ private $size = 0;
|
||
+
|
||
+ public static $loId;
|
||
+
|
||
+ function stream_open($path, $mode)
|
||
+ {
|
||
+ $path = trim(parse_url($path, PHP_URL_HOST));
|
||
+
|
||
+ if ($path) {
|
||
+ if ($this->dbh = pg_connect($path)) {
|
||
+ if (pg_query($this->dbh, 'BEGIN')) {
|
||
+ if (is_resource($this->loh = pg_lo_open($this->dbh, $this->lon = self::$loId, $mode))) {
|
||
+ pg_lo_seek($this->loh, 0, PGSQL_SEEK_END);
|
||
+ $this->size = (int) pg_lo_tell($this->loh);
|
||
+ pg_lo_seek($this->loh, 0, PGSQL_SEEK_SET);
|
||
+ return true;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+ function stream_read($length)
|
||
+ {
|
||
+ return pg_lo_read($this->loh, $length);
|
||
+ }
|
||
+
|
||
+ function stream_seek($offset, $whence = PGSQL_SEEK_SET)
|
||
+ {
|
||
+ return pg_lo_seek($this->loh, $offset, $whence);
|
||
+ }
|
||
+
|
||
+ function stream_tell()
|
||
+ {
|
||
+ return pg_lo_tell($this->loh);
|
||
+ }
|
||
+
|
||
+ function stream_eof()
|
||
+ {
|
||
+ return pg_lo_tell($this->loh) >= $this->size;
|
||
+ }
|
||
+
|
||
+ function stream_flush()
|
||
+ {
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ function stream_stat()
|
||
+ {
|
||
+ return array('size' => $this->size, 'ino' => $this->lon);
|
||
+ }
|
||
+
|
||
+ function stream_write($data)
|
||
+ {
|
||
+ return pg_lo_write($this->loh, $data);
|
||
+ }
|
||
+
|
||
+ function stream_close()
|
||
+ {
|
||
+ if (pg_lo_close($this->loh)) {
|
||
+ return pg_query($this->dbh, 'COMMIT');
|
||
+ } else {
|
||
+ pg_query($this->dbh, 'ROLLBACK');
|
||
+ return false;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+stream_register_wrapper('pglob', 'PgLobStream');
|
||
+
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/lib/XmlRpcClient.php
|
||
@@ -0,0 +1,119 @@
|
||
+<?php
|
||
+
|
||
+/**
|
||
+ * XMLRPC Client, very KISS
|
||
+ * $Id: XmlRpcClient.php 227268 2007-01-15 08:01:35Z mike $
|
||
+ *
|
||
+ * NOTE: requires ext/xmlrpc
|
||
+ *
|
||
+ * Usage:
|
||
+ * <code>
|
||
+ * <?php
|
||
+ * $rpc = new XmlRpcClient('http://mike:secret@example.com/cgi-bin/vpop-xmlrpc');
|
||
+ * $rpc->__request->setOptions(array('compress' => true));
|
||
+ * try {
|
||
+ * print_r($rpc->vpop->listdomain(array('domain' => 'example.com')));
|
||
+ * } catch (Exception $ex) {
|
||
+ * echo $ex;
|
||
+ * }
|
||
+ * ?>
|
||
+ * </code>
|
||
+ *
|
||
+ * @copyright Michael Wallner, <mike@iworks.at>
|
||
+ * @license BSD, revised
|
||
+ * @package pecl/http
|
||
+ * @version $Revision: 227268 $
|
||
+ */
|
||
+class XmlRpcClient
|
||
+{
|
||
+ /**
|
||
+ * RPC namespace
|
||
+ *
|
||
+ * @var string
|
||
+ */
|
||
+ public $__namespace;
|
||
+
|
||
+ /**
|
||
+ * HttpRequest instance
|
||
+ *
|
||
+ * @var HttpRequest
|
||
+ */
|
||
+ public $__request;
|
||
+
|
||
+ /**
|
||
+ * Client charset
|
||
+ *
|
||
+ * @var string
|
||
+ */
|
||
+ public $__encoding = "iso-8859-1";
|
||
+
|
||
+ /**
|
||
+ * RPC options
|
||
+ *
|
||
+ * @var array
|
||
+ */
|
||
+ public $__options;
|
||
+
|
||
+ /**
|
||
+ * Constructor
|
||
+ *
|
||
+ * @param string $url RPC endpoint
|
||
+ * @param string $namespace RPC namespace
|
||
+ * @param array $options HttpRequest options
|
||
+ */
|
||
+ public function __construct($url, $namespace = '', array $options = null)
|
||
+ {
|
||
+ $this->__request = new HttpRequest($url, HttpRequest::METH_POST, (array) $options);
|
||
+ $this->__namespace = $namespace;
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * RPC method proxy
|
||
+ *
|
||
+ * @param string $method RPC method name
|
||
+ * @param array $params RPC method arguments
|
||
+ * @return mixed decoded RPC response
|
||
+ * @throws Exception
|
||
+ */
|
||
+ public function __call($method, array $params)
|
||
+ {
|
||
+ if (strlen($this->__namespace)) {
|
||
+ $method = $this->__namespace .'.'. $method;
|
||
+ }
|
||
+ $this->__request->setContentType("text/xml");
|
||
+ $this->__request->setRawPostData(
|
||
+ xmlrpc_encode_request($method, $params,
|
||
+ array("encoding" => $this->__encoding) + (array) $this->__options));
|
||
+ $response = $this->__request->send();
|
||
+ if ($response->getResponseCode() != 200) {
|
||
+ throw new Exception(
|
||
+ $response->getResponseStatus(),
|
||
+ $response->getResponseCode()
|
||
+ );
|
||
+ }
|
||
+
|
||
+ $data = xmlrpc_decode($response->getBody(), $this->__encoding);
|
||
+ if (xmlrpc_is_fault($data)) {
|
||
+ throw new Exception(
|
||
+ (string) $data['faultString'],
|
||
+ (int) $data['faultCode']
|
||
+ );
|
||
+ }
|
||
+
|
||
+ return $data;
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Returns self, where namespace is set to variable name
|
||
+ *
|
||
+ * @param string $ns
|
||
+ * @return XmlRpcRequest
|
||
+ */
|
||
+ public function __get($ns)
|
||
+ {
|
||
+ $this->__namespace = $ns;
|
||
+ return $this;
|
||
+ }
|
||
+}
|
||
+
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/lib/XmlRpcServer.php
|
||
@@ -0,0 +1,254 @@
|
||
+<?php
|
||
+
|
||
+XmlRpcServer::setContentType("text/xml");
|
||
+XmlRpcServer::capture();
|
||
+
|
||
+/**
|
||
+ * XMLRPC Server, very KISS
|
||
+ * $Id: XmlRpcServer.php 227268 2007-01-15 08:01:35Z mike $
|
||
+ *
|
||
+ * NOTE: requires ext/xmlrpc
|
||
+ *
|
||
+ * Usage:
|
||
+ * <code>
|
||
+ * <?php
|
||
+ * class Handler extends XmlRpcRequestHandlerStub {
|
||
+ * public function xmlrpcPing(array $values) {
|
||
+ * return true;
|
||
+ * }
|
||
+ * }
|
||
+ * try {
|
||
+ * XmlRpcServer::factory("namespace")->registerHandler(new Handler);
|
||
+ * XmlRpcServer::run();
|
||
+ * } catch (Exception $ex) {
|
||
+ * XmlRpcServer::error($ex->getCode(), $ex->getMessage());
|
||
+ * }
|
||
+ * </code>
|
||
+ *
|
||
+ * @copyright Michael Wallner, <mike@iworks.at>
|
||
+ * @license BSD, revised
|
||
+ * @package pecl/http
|
||
+ * @version $Revision: 227268 $
|
||
+ */
|
||
+
|
||
+class XmlRpcServer extends HttpResponse
|
||
+{
|
||
+ /**
|
||
+ * Server charset
|
||
+ *
|
||
+ * @var string
|
||
+ */
|
||
+ public static $encoding = "iso-8859-1";
|
||
+
|
||
+ /**
|
||
+ * RPC namespace
|
||
+ *
|
||
+ * @var string
|
||
+ */
|
||
+ public $namespace;
|
||
+
|
||
+ /**
|
||
+ * RPC handler attached to this server instance
|
||
+ *
|
||
+ * @var XmlRpcRequestHandler
|
||
+ */
|
||
+ protected $handler;
|
||
+
|
||
+ private static $xmlreq;
|
||
+ private static $xmlrpc;
|
||
+ private static $refcnt = 0;
|
||
+ private static $handle = array();
|
||
+
|
||
+ /**
|
||
+ * Create a new XmlRpcServer instance
|
||
+ *
|
||
+ * @param string $namespace
|
||
+ * @param string $encoding
|
||
+ */
|
||
+ public function __construct($namespace)
|
||
+ {
|
||
+ $this->namespace = $namespace;
|
||
+ self::initialize();
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Destructor
|
||
+ */
|
||
+ public function __destruct()
|
||
+ {
|
||
+ if (self::$refcnt && !--self::$refcnt) {
|
||
+ xmlrpc_server_destroy(self::$xmlrpc);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Static factory
|
||
+ *
|
||
+ * @param string $namespace
|
||
+ * @return XmlRpcServer
|
||
+ */
|
||
+ public static function factory($namespace)
|
||
+ {
|
||
+ return new XmlRpcServer($namespace);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Run all servers and send response
|
||
+ *
|
||
+ * @param array $options
|
||
+ */
|
||
+ public static function run(array $options = null)
|
||
+ {
|
||
+ self::initialize(false, true);
|
||
+ self::setContentType("text/xml; charset=". self::$encoding);
|
||
+ echo xmlrpc_server_call_method(self::$xmlrpc, self::$xmlreq, null,
|
||
+ array("encoding" => self::$encoding) + (array) $options);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Test hook; call instead of XmlRpcServer::run()
|
||
+ *
|
||
+ * @param string $method
|
||
+ * @param array $params
|
||
+ * @param array $request_options
|
||
+ * @param array $response_options
|
||
+ */
|
||
+ public static function test($method, array $params, array $request_options = null, array $response_options = null)
|
||
+ {
|
||
+ self::$xmlreq = xmlrpc_encode_request($method, $params, $request_options);
|
||
+ self::run($response_options);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Optional XMLRPC error handler
|
||
+ *
|
||
+ * @param int $code
|
||
+ * @param string $msg
|
||
+ */
|
||
+ public static function error($code, $msg, array $options = null)
|
||
+ {
|
||
+ echo xmlrpc_encode(array("faultCode" => $code, "faultString" => $msg),
|
||
+ array("encoding" => self::$encoding) + (array) $options);
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Register a single method
|
||
+ *
|
||
+ * @param string $name
|
||
+ * @param mixed $callback
|
||
+ * @param mixed $dispatch
|
||
+ * @param array $spec
|
||
+ */
|
||
+ public function registerMethod($name, $callback, $dispatch = null, array $spec = null)
|
||
+ {
|
||
+ if (!is_callable($callback, false, $cb_name)) {
|
||
+ throw new Exception("$cb_name is not a valid callback");
|
||
+ }
|
||
+ if (isset($dispatch)) {
|
||
+ if (!is_callable($dispatch, false, $cb_name)) {
|
||
+ throw new Exception("$cb_name is not a valid callback");
|
||
+ }
|
||
+ xmlrpc_server_register_method(self::$xmlrpc, $name, $dispatch);
|
||
+ self::$handle[$name] = $callback;
|
||
+ } else {
|
||
+ xmlrpc_server_register_method(self::$xmlrpc, $name, $callback);
|
||
+ }
|
||
+
|
||
+ if (isset($spec)) {
|
||
+ xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /**
|
||
+ * Register an XmlRpcRequestHandler for this server instance
|
||
+ *
|
||
+ * @param XmlRpcRequestHandler $handler
|
||
+ */
|
||
+ public function registerHandler(XmlRpcRequestHandler $handler)
|
||
+ {
|
||
+ $this->handler = $handler;
|
||
+
|
||
+ foreach (get_class_methods($handler) as $method) {
|
||
+ if (!strncmp($method, "xmlrpc", 6)) {
|
||
+ $this->registerMethod(
|
||
+ $this->method($method, $handler->getNamespace()),
|
||
+ array($handler, $method), array($this, "dispatch"));
|
||
+ }
|
||
+ }
|
||
+
|
||
+ $handler->getIntrospectionData($spec);
|
||
+ if (is_array($spec)) {
|
||
+ xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ private function method($method, $namespace = null)
|
||
+ {
|
||
+ if (!strlen($namespace)) {
|
||
+ $namespace = strlen($this->namespace) ? $this->namespace : "xmlrpc";
|
||
+ }
|
||
+ return $namespace .".". strtolower($method[6]) . substr($method, 7);
|
||
+ }
|
||
+
|
||
+ private function dispatch($method, array $params = null)
|
||
+ {
|
||
+ if (array_key_exists($method, self::$handle)) {
|
||
+ return call_user_func(self::$handle[$method], $params);
|
||
+ }
|
||
+ throw new Exception("Unknown XMLRPC method: $method");
|
||
+ }
|
||
+
|
||
+ private static function initialize($server = true, $data = false)
|
||
+ {
|
||
+ if ($data) {
|
||
+ if (!self::$xmlreq && !(self::$xmlreq = http_get_request_body())) {
|
||
+ throw new Exception("Failed to fetch XMLRPC request body");
|
||
+ }
|
||
+ }
|
||
+ if ($server) {
|
||
+ if (!self::$xmlrpc && !(self::$xmlrpc = xmlrpc_server_create())) {
|
||
+ throw new Exception("Failed to initialize XMLRPC server");
|
||
+ }
|
||
+ ++self::$refcnt;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+/**
|
||
+ * XmlRpcRequestHandler
|
||
+ *
|
||
+ * Define XMLRPC methods with an "xmlrpc" prefix, eg:
|
||
+ * <code>
|
||
+ * class IntOp implements XmlRpcRequestHandler {
|
||
+ * public function getNamespace() {
|
||
+ * return "int";
|
||
+ * }
|
||
+ * public function getInstrospectionData(array &$spec = null) {
|
||
+ * }
|
||
+ * // XMLRPC method name: int.sumValues
|
||
+ * public function xmlrpcSumValues(array $values) {
|
||
+ * return array_sum($values);
|
||
+ * }
|
||
+ * }
|
||
+ * </code>
|
||
+ */
|
||
+interface XmlRpcRequestHandler
|
||
+{
|
||
+ public function getNamespace();
|
||
+ public function getIntrospectionData(array &$spec = null);
|
||
+}
|
||
+
|
||
+/**
|
||
+ * XmlRpcRequestHandlerStub
|
||
+ */
|
||
+abstract class XmlRpcRequestHandlerStub implements XmlRpcRequestHandler
|
||
+{
|
||
+ public function getNamespace()
|
||
+ {
|
||
+ }
|
||
+ public function getIntrospectionData(array &$spec = null)
|
||
+ {
|
||
+ }
|
||
+}
|
||
+
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/missing.c
|
||
@@ -0,0 +1,74 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: missing.c 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifdef HAVE_CONFIG_H
|
||
+# include "config.h"
|
||
+#endif
|
||
+
|
||
+#include "php.h"
|
||
+#include "missing.h"
|
||
+
|
||
+#ifdef WONKY
|
||
+int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC)
|
||
+{
|
||
+ zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS);
|
||
+ INIT_PZVAL(property);
|
||
+ ZVAL_DOUBLE(property, value);
|
||
+ return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
|
||
+}
|
||
+
|
||
+void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC)
|
||
+{
|
||
+ zval *tmp = ecalloc(1, sizeof(zval));
|
||
+ ZVAL_DOUBLE(tmp, value);
|
||
+ zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
|
||
+}
|
||
+
|
||
+int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC)
|
||
+{
|
||
+ zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS);
|
||
+ INIT_PZVAL(property);
|
||
+ ZVAL_BOOL(property, value);
|
||
+ return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
|
||
+}
|
||
+
|
||
+void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC)
|
||
+{
|
||
+ zval *tmp = ecalloc(1, sizeof(zval));
|
||
+ ZVAL_BOOL(tmp, value);
|
||
+ zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
|
||
+}
|
||
+
|
||
+void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC)
|
||
+{
|
||
+ zval *tmp;
|
||
+
|
||
+ ALLOC_ZVAL(tmp);
|
||
+ tmp->is_ref = 0;
|
||
+ tmp->refcount = 0;
|
||
+ ZVAL_STRINGL(tmp, value, value_len, 1);
|
||
+ zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
|
||
+}
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/missing.h
|
||
@@ -0,0 +1,180 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: missing.h 298892 2010-05-03 08:29:31Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_MISSING
|
||
+#define PHP_HTTP_MISSING
|
||
+
|
||
+#include "php_version.h"
|
||
+
|
||
+#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50399)
|
||
+# define ZEND_LITERAL_KEY_DC , const zend_literal *_zend_literal_key
|
||
+# define ZEND_LITERAL_KEY_CC , _zend_literal_key
|
||
+# define ZEND_LITERAL_NIL_CC , NULL
|
||
+# define HTTP_CHECK_OPEN_BASEDIR(file, act) \
|
||
+ if ((PG(open_basedir) && *PG(open_basedir))) \
|
||
+ { \
|
||
+ const char *tmp = file; \
|
||
+ \
|
||
+ if (!strncasecmp(tmp, "file:", lenof("file:"))) { \
|
||
+ tmp += lenof("file:"); \
|
||
+ while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \
|
||
+ } \
|
||
+ \
|
||
+ if ( (tmp != file || !strstr(file, "://")) && \
|
||
+ (!*tmp || php_check_open_basedir(tmp TSRMLS_CC))) { \
|
||
+ act; \
|
||
+ } \
|
||
+ }
|
||
+
|
||
+#else
|
||
+# define ZEND_LITERAL_KEY_DC
|
||
+# define ZEND_LITERAL_KEY_CC
|
||
+# define ZEND_LITERAL_NIL_CC
|
||
+# define HTTP_CHECK_OPEN_BASEDIR(file, act) \
|
||
+ if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) \
|
||
+ { \
|
||
+ const char *tmp = file; \
|
||
+ \
|
||
+ if (!strncasecmp(tmp, "file:", lenof("file:"))) { \
|
||
+ tmp += lenof("file:"); \
|
||
+ while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \
|
||
+ } \
|
||
+ \
|
||
+ if ( (tmp != file || !strstr(file, "://")) && \
|
||
+ (!*tmp || php_check_open_basedir(tmp TSRMLS_CC) || \
|
||
+ (PG(safe_mode) && !php_checkuid(tmp, "rb+", CHECKUID_CHECK_MODE_PARAM)))) { \
|
||
+ act; \
|
||
+ } \
|
||
+ }
|
||
+
|
||
+#endif
|
||
+
|
||
+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)
|
||
+# define HTTP_ZAPI_HASH_TSRMLS_CC TSRMLS_CC
|
||
+# define HTTP_ZAPI_HASH_TSRMLS_DC TSRMLS_DC
|
||
+# define HTTP_ZAPI_CONST_CAST(t) (const t)
|
||
+# define GLOBAL_ERROR_HANDLING EG(error_handling)
|
||
+# define GLOBAL_EXCEPTION_CLASS EG(exception_class)
|
||
+# define IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp) TSRMLS_CC)
|
||
+# define HTTP_STATIC_ARG_INFO
|
||
+#else
|
||
+# define HTTP_ZAPI_HASH_TSRMLS_CC
|
||
+# define HTTP_ZAPI_HASH_TSRMLS_DC
|
||
+# define HTTP_ZAPI_CONST_CAST(t) (t)
|
||
+# define GLOBAL_ERROR_HANDLING PG(error_handling)
|
||
+# define GLOBAL_EXCEPTION_CLASS PG(exception_class)
|
||
+# define IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp))
|
||
+# define HTTP_STATIC_ARG_INFO static
|
||
+#endif
|
||
+
|
||
+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION == 0)
|
||
+# define WONKY
|
||
+#endif
|
||
+
|
||
+#ifndef pemalloc_rel
|
||
+# define pemalloc_rel(size, persistent) ((persistent)?malloc(size):emalloc_rel(size))
|
||
+#endif
|
||
+
|
||
+#ifndef ZEND_ACC_DEPRECATED
|
||
+# define ZEND_ACC_DEPRECATED 0
|
||
+#endif
|
||
+
|
||
+#if PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10
|
||
+# define php_url_parse_ex(u, l) php_url_parse(u)
|
||
+#endif
|
||
+
|
||
+#ifndef TSRMLS_FETCH_FROM_CTX
|
||
+# ifdef ZTS
|
||
+# define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
|
||
+# else
|
||
+# define TSRMLS_FETCH_FROM_CTX(ctx)
|
||
+# endif
|
||
+#endif
|
||
+
|
||
+#ifndef TSRMLS_SET_CTX
|
||
+# ifdef ZTS
|
||
+# define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
|
||
+# else
|
||
+# define TSRMLS_SET_CTX(ctx)
|
||
+# endif
|
||
+#endif
|
||
+
|
||
+#ifndef ZVAL_ADDREF
|
||
+# define ZVAL_ADDREF Z_ADDREF_P
|
||
+#endif
|
||
+
|
||
+#ifndef SEPARATE_ARG_IF_REF
|
||
+#define SEPARATE_ARG_IF_REF(zv) \
|
||
+ if (PZVAL_IS_REF(zv)) { \
|
||
+ zval *ov = zv; \
|
||
+ ALLOC_INIT_ZVAL(zv); \
|
||
+ Z_TYPE_P(zv) = Z_TYPE_P(ov); \
|
||
+ zv->value = ov->value; \
|
||
+ zval_copy_ctor(zv); \
|
||
+ } else { \
|
||
+ ZVAL_ADDREF(zv); \
|
||
+ }
|
||
+#endif
|
||
+
|
||
+#ifndef ZVAL_ZVAL
|
||
+#define ZVAL_ZVAL(z, zv, copy, dtor) { \
|
||
+ int is_ref, refcount; \
|
||
+ is_ref = (z)->is_ref; \
|
||
+ refcount = (z)->refcount; \
|
||
+ *(z) = *(zv); \
|
||
+ if (copy) { \
|
||
+ zval_copy_ctor(z); \
|
||
+ } \
|
||
+ if (dtor) { \
|
||
+ if (!copy) { \
|
||
+ ZVAL_NULL(zv); \
|
||
+ } \
|
||
+ zval_ptr_dtor(&zv); \
|
||
+ } \
|
||
+ (z)->is_ref = is_ref; \
|
||
+ (z)->refcount = refcount; \
|
||
+ }
|
||
+#endif
|
||
+#ifndef RETVAL_ZVAL
|
||
+# define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
|
||
+#endif
|
||
+#ifndef RETURN_ZVAL
|
||
+# define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
|
||
+#endif
|
||
+
|
||
+#ifndef ZEND_MN
|
||
+# define ZEND_MN(name) ZEND_FN(name)
|
||
+#endif
|
||
+
|
||
+#ifdef WONKY
|
||
+extern int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC);
|
||
+extern void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC);
|
||
+
|
||
+extern int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);
|
||
+extern void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC);
|
||
+
|
||
+extern void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC);
|
||
+#endif
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http.h
|
||
@@ -0,0 +1,262 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http.h 310776 2011-05-05 06:35:46Z mike $ */
|
||
+
|
||
+#ifndef PHP_EXT_HTTP_H
|
||
+#define PHP_EXT_HTTP_H
|
||
+
|
||
+#define PHP_HTTP_VERSION "1.7.1"
|
||
+
|
||
+#ifdef HAVE_CONFIG_H
|
||
+# include "config.h"
|
||
+#else
|
||
+# ifndef PHP_WIN32
|
||
+# include "php_config.h"
|
||
+# endif
|
||
+#endif
|
||
+
|
||
+#include "php.h"
|
||
+#include "missing.h"
|
||
+#include "php_http_std_defs.h"
|
||
+#include "phpstr/phpstr.h"
|
||
+
|
||
+#ifdef HTTP_WANT_SAPI
|
||
+# if PHP_API_VERSION > 20041225
|
||
+# define HTTP_HAVE_SAPI_RTIME
|
||
+# endif
|
||
+# include "SAPI.h"
|
||
+#endif
|
||
+
|
||
+#ifdef HTTP_WANT_NETDB
|
||
+# ifdef PHP_WIN32
|
||
+# define HTTP_HAVE_NETDB
|
||
+# include <winsock2.h>
|
||
+# elif defined(HAVE_NETDB_H)
|
||
+# define HTTP_HAVE_NETDB
|
||
+# include <netdb.h>
|
||
+# ifdef HAVE_UNISTD_H
|
||
+# include <unistd.h>
|
||
+# endif
|
||
+# endif
|
||
+#endif
|
||
+
|
||
+#if defined(HTTP_WANT_CURL) && defined(HTTP_HAVE_CURL)
|
||
+# ifdef PHP_WIN32
|
||
+# include <winsock2.h>
|
||
+# define CURL_STATICLIB
|
||
+# endif
|
||
+# include <curl/curl.h>
|
||
+# define HTTP_CURL_VERSION(x, y, z) (LIBCURL_VERSION_NUM >= (((x)<<16) + ((y)<<8) + (z)))
|
||
+#
|
||
+# if defined(HTTP_WANT_EVENT) && defined(HTTP_HAVE_EVENT)
|
||
+# include <event.h>
|
||
+# endif
|
||
+#endif
|
||
+
|
||
+#if defined(HTTP_WANT_MAGIC) && defined(HTTP_HAVE_MAGIC)
|
||
+# if defined(PHP_WIN32) && !defined(USE_MAGIC_DLL) && !defined(USE_MAGIC_STATIC)
|
||
+# define USE_MAGIC_STATIC
|
||
+# endif
|
||
+# include <magic.h>
|
||
+#endif
|
||
+
|
||
+#if defined(HTTP_WANT_ZLIB) && defined(HTTP_HAVE_ZLIB)
|
||
+# include <zlib.h>
|
||
+#endif
|
||
+
|
||
+#include <ctype.h>
|
||
+#define HTTP_IS_CTYPE(type, c) is##type((int) (unsigned char) (c))
|
||
+#define HTTP_TO_CTYPE(type, c) to##type((int) (unsigned char) (c))
|
||
+
|
||
+extern zend_module_entry http_module_entry;
|
||
+#define phpext_http_ptr &http_module_entry
|
||
+
|
||
+extern int http_module_number;
|
||
+
|
||
+ZEND_BEGIN_MODULE_GLOBALS(http)
|
||
+
|
||
+ struct _http_globals_etag {
|
||
+ char *mode;
|
||
+ void *ctx;
|
||
+ zend_bool started;
|
||
+ } etag;
|
||
+
|
||
+ struct _http_globals_log {
|
||
+ char *cache;
|
||
+ char *redirect;
|
||
+ char *not_found;
|
||
+ char *allowed_methods;
|
||
+ char *composite;
|
||
+ } log;
|
||
+
|
||
+ struct _http_globals_send {
|
||
+ double throttle_delay;
|
||
+ size_t buffer_size;
|
||
+ char *content_type;
|
||
+ char *unquoted_etag;
|
||
+ time_t last_modified;
|
||
+ struct _http_globals_send_deflate {
|
||
+ zend_bool response;
|
||
+ zend_bool start_auto;
|
||
+ long start_flags;
|
||
+ int encoding;
|
||
+ void *stream;
|
||
+ } deflate;
|
||
+ struct _http_globals_send_inflate {
|
||
+ zend_bool start_auto;
|
||
+ long start_flags;
|
||
+ void *stream;
|
||
+ } inflate;
|
||
+ zend_bool not_found_404;
|
||
+ } send;
|
||
+
|
||
+ struct _http_globals_request {
|
||
+ time_t time;
|
||
+ HashTable *headers;
|
||
+ struct _http_globals_request_methods {
|
||
+ HashTable registered;
|
||
+ char *allowed;
|
||
+ char *custom;
|
||
+ } methods;
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
|
||
+ struct _http_globals_request_datashare {
|
||
+ zend_llist handles;
|
||
+ zend_bool cookie;
|
||
+ zend_bool dns;
|
||
+ zend_bool ssl;
|
||
+ zend_bool connect;
|
||
+ } datashare;
|
||
+#endif
|
||
+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_EVENT)
|
||
+ struct _http_globals_request_pool {
|
||
+ struct _http_globals_request_pool_event {
|
||
+ void *base;
|
||
+ } event;
|
||
+ } pool;
|
||
+#endif
|
||
+ } request;
|
||
+
|
||
+ struct _http_globals_persistent {
|
||
+ struct _http_globals_persistent_handles {
|
||
+ ulong limit;
|
||
+ struct _http_globals_persistent_handles_ident {
|
||
+ ulong h;
|
||
+ char *s;
|
||
+ size_t l;
|
||
+ } ident;
|
||
+ } handles;
|
||
+ } persistent;
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+ zend_bool only_exceptions;
|
||
+#endif
|
||
+
|
||
+ zend_bool force_exit;
|
||
+ zend_bool read_post_data;
|
||
+ zval *server_var;
|
||
+
|
||
+ZEND_END_MODULE_GLOBALS(http)
|
||
+
|
||
+ZEND_EXTERN_MODULE_GLOBALS(http);
|
||
+
|
||
+#ifdef ZTS
|
||
+# include "TSRM.h"
|
||
+# define HTTP_G ((zend_http_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(http_globals_id)])
|
||
+#else
|
||
+# define HTTP_G (&http_globals)
|
||
+#endif
|
||
+
|
||
+#if defined(HAVE_ICONV) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_ICONV))
|
||
+# define HTTP_HAVE_ICONV
|
||
+#endif
|
||
+
|
||
+#if defined(HAVE_PHP_SESSION) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_SESSION))
|
||
+# define HTTP_HAVE_SESSION
|
||
+#endif
|
||
+
|
||
+#if defined(HAVE_HASH_EXT) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_HASH)) && defined(HTTP_HAVE_PHP_HASH_H)
|
||
+# define HTTP_HAVE_HASH
|
||
+#endif
|
||
+
|
||
+#if defined(HAVE_SPL)
|
||
+# define HTTP_HAVE_SPL
|
||
+#endif
|
||
+
|
||
+PHP_FUNCTION(http_date);
|
||
+PHP_FUNCTION(http_build_url);
|
||
+PHP_FUNCTION(http_build_str);
|
||
+PHP_FUNCTION(http_negotiate_language);
|
||
+PHP_FUNCTION(http_negotiate_charset);
|
||
+PHP_FUNCTION(http_negotiate_content_type);
|
||
+PHP_FUNCTION(http_negotiate);
|
||
+PHP_FUNCTION(http_redirect);
|
||
+PHP_FUNCTION(http_throttle);
|
||
+PHP_FUNCTION(http_send_status);
|
||
+PHP_FUNCTION(http_send_last_modified);
|
||
+PHP_FUNCTION(http_send_content_type);
|
||
+PHP_FUNCTION(http_send_content_disposition);
|
||
+PHP_FUNCTION(http_match_modified);
|
||
+PHP_FUNCTION(http_match_etag);
|
||
+PHP_FUNCTION(http_cache_last_modified);
|
||
+PHP_FUNCTION(http_cache_etag);
|
||
+PHP_FUNCTION(http_send_data);
|
||
+PHP_FUNCTION(http_send_file);
|
||
+PHP_FUNCTION(http_send_stream);
|
||
+PHP_FUNCTION(http_chunked_decode);
|
||
+PHP_FUNCTION(http_parse_message);
|
||
+PHP_FUNCTION(http_parse_headers);
|
||
+PHP_FUNCTION(http_parse_cookie);
|
||
+PHP_FUNCTION(http_build_cookie);
|
||
+PHP_FUNCTION(http_parse_params);
|
||
+PHP_FUNCTION(http_get_request_headers);
|
||
+PHP_FUNCTION(http_get_request_body);
|
||
+PHP_FUNCTION(http_get_request_body_stream);
|
||
+PHP_FUNCTION(http_match_request_header);
|
||
+PHP_FUNCTION(http_persistent_handles_count);
|
||
+PHP_FUNCTION(http_persistent_handles_clean);
|
||
+PHP_FUNCTION(http_persistent_handles_ident);
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+PHP_FUNCTION(http_get);
|
||
+PHP_FUNCTION(http_head);
|
||
+PHP_FUNCTION(http_post_data);
|
||
+PHP_FUNCTION(http_post_fields);
|
||
+PHP_FUNCTION(http_put_data);
|
||
+PHP_FUNCTION(http_put_file);
|
||
+PHP_FUNCTION(http_put_stream);
|
||
+PHP_FUNCTION(http_request);
|
||
+PHP_FUNCTION(http_request_body_encode);
|
||
+#endif /* HTTP_HAVE_CURL */
|
||
+PHP_FUNCTION(http_request_method_register);
|
||
+PHP_FUNCTION(http_request_method_unregister);
|
||
+PHP_FUNCTION(http_request_method_exists);
|
||
+PHP_FUNCTION(http_request_method_name);
|
||
+PHP_FUNCTION(ob_etaghandler);
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+PHP_FUNCTION(http_deflate);
|
||
+PHP_FUNCTION(http_inflate);
|
||
+PHP_FUNCTION(ob_deflatehandler);
|
||
+PHP_FUNCTION(ob_inflatehandler);
|
||
+#endif
|
||
+PHP_FUNCTION(http_support);
|
||
+
|
||
+#endif /* PHP_HTTP_H */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_api.h
|
||
@@ -0,0 +1,318 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_api.h 298891 2010-05-03 08:26:38Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_API_H
|
||
+#define PHP_HTTP_API_H
|
||
+
|
||
+#define HTTP_SUPPORT 0x01L
|
||
+#define HTTP_SUPPORT_REQUESTS 0x02L
|
||
+#define HTTP_SUPPORT_MAGICMIME 0x04L
|
||
+#define HTTP_SUPPORT_ENCODINGS 0x08L
|
||
+#define HTTP_SUPPORT_SSLREQUESTS 0x20L
|
||
+#define HTTP_SUPPORT_PERSISTENCE 0x40L
|
||
+#define HTTP_SUPPORT_EVENTS 0x80L
|
||
+
|
||
+#define HTTP_PARAMS_ALLOW_COMMA 0x01
|
||
+#define HTTP_PARAMS_ALLOW_FAILURE 0x02
|
||
+#define HTTP_PARAMS_RAISE_ERROR 0x04
|
||
+#define HTTP_PARAMS_DEFAULT (HTTP_PARAMS_ALLOW_COMMA|HTTP_PARAMS_ALLOW_FAILURE|HTTP_PARAMS_RAISE_ERROR)
|
||
+#define HTTP_PARAMS_COLON_SEPARATOR 0x10
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_support);
|
||
+
|
||
+#define http_support(f) _http_support(f)
|
||
+PHP_HTTP_API long _http_support(long feature);
|
||
+
|
||
+#define pretty_key(key, key_len, uctitle, xhyphen) _http_pretty_key(key, key_len, uctitle, xhyphen)
|
||
+extern char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen);
|
||
+
|
||
+#define http_boundary(b, l) _http_boundary((b), (l) TSRMLS_CC)
|
||
+extern size_t _http_boundary(char *buf, size_t len TSRMLS_DC);
|
||
+
|
||
+#define http_error(type, code, string) _http_error_ex(type, code, "%s", string)
|
||
+#define http_error_ex _http_error_ex
|
||
+extern void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...);
|
||
+
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+#define http_exception_wrap(o, n, ce) _http_exception_wrap((o), (n), (ce) TSRMLS_CC)
|
||
+extern zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC);
|
||
+
|
||
+#define http_try \
|
||
+{ \
|
||
+ zval *old_exception = EG(exception); \
|
||
+ EG(exception) = NULL;
|
||
+#define http_catch(ex_ce) \
|
||
+ if (EG(exception) && old_exception) { \
|
||
+ EG(exception) = http_exception_wrap(old_exception, EG(exception), ex_ce); \
|
||
+ } \
|
||
+}
|
||
+#define http_final(ex_ce) \
|
||
+ if (EG(exception)) { \
|
||
+ EG(exception) = http_exception_wrap(EG(exception), NULL, ex_ce); \
|
||
+ }
|
||
+
|
||
+typedef zend_object_value (*http_object_new_t)(zend_class_entry *ce, void *, void ** TSRMLS_DC);
|
||
+
|
||
+#define http_object_new(ov, cn, cl, co, ce, i, pp) _http_object_new((ov), (cn), (cl), (http_object_new_t) (co), (ce), (i), (void *) (pp) TSRMLS_CC)
|
||
+extern STATUS _http_object_new(zend_object_value *ov, const char *cname_str, uint cname_len, http_object_new_t create, zend_class_entry *parent_ce, void *intern_ptr, void **obj_ptr TSRMLS_DC);
|
||
+#endif /* ZEND_ENGINE_2 */
|
||
+
|
||
+
|
||
+#define HTTP_CHECK_CURL_INIT(ch, init, action) \
|
||
+ if ((!(ch)) && (!((ch) = init))) { \
|
||
+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initialize curl"); \
|
||
+ action; \
|
||
+ }
|
||
+#define HTTP_CHECK_CONTENT_TYPE(ct, action) \
|
||
+ if (!strchr((ct), '/')) { \
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, \
|
||
+ "Content type \"%s\" does not seem to contain a primary and a secondary part", (ct)); \
|
||
+ action; \
|
||
+ }
|
||
+#define HTTP_CHECK_MESSAGE_TYPE_RESPONSE(msg, action) \
|
||
+ if (!HTTP_MSG_TYPE(RESPONSE, (msg))) { \
|
||
+ http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_RESPONSE"); \
|
||
+ action; \
|
||
+ }
|
||
+#define HTTP_CHECK_MESSAGE_TYPE_REQUEST(msg, action) \
|
||
+ if (!HTTP_MSG_TYPE(REQUEST, (msg))) { \
|
||
+ http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST"); \
|
||
+ action; \
|
||
+ }
|
||
+#define HTTP_CHECK_GZIP_LEVEL(level, action) \
|
||
+ if (level < -1 || level > 9) { \
|
||
+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid compression level (-1 to 9): %d", level); \
|
||
+ action; \
|
||
+ }
|
||
+
|
||
+#define HTTP_CHECK_HEADERS_SENT(action) \
|
||
+ if (SG(headers_sent) && !SG(request_info).no_headers) { \
|
||
+ char *output_start_filename = php_get_output_start_filename(TSRMLS_C); \
|
||
+ int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); \
|
||
+ \
|
||
+ if (output_start_filename) { \
|
||
+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent by (output started at %s:%d)", \
|
||
+ output_start_filename, output_start_lineno); \
|
||
+ } else { \
|
||
+ http_error(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent"); \
|
||
+ } \
|
||
+ action; \
|
||
+ }
|
||
+
|
||
+#define http_log(f, i, m) _http_log_ex((f), (i), (m) TSRMLS_CC)
|
||
+extern void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC);
|
||
+
|
||
+#define http_exit(s, h) http_exit_ex((s), (h), NULL, 1)
|
||
+#define http_exit_ex(s, h, b, e) _http_exit_ex((s), (h), (b), (e) TSRMLS_CC)
|
||
+extern STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC);
|
||
+
|
||
+#define http_check_method(m) http_check_method_ex((m), HTTP_KNOWN_METHODS)
|
||
+#define http_check_method_ex(m, a) _http_check_method_ex((m), (a))
|
||
+extern STATUS _http_check_method_ex(const char *method, const char *methods);
|
||
+
|
||
+#define http_got_server_var(v) (NULL != http_get_server_var_ex((v), strlen(v), 1))
|
||
+#define http_get_server_var(v, c) http_get_server_var_ex((v), strlen(v), (c))
|
||
+#define http_get_server_var_ex(v, l, c) _http_get_server_var_ex((v), (l), (c) TSRMLS_CC)
|
||
+PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC);
|
||
+
|
||
+#define http_get_request_body(b, l) _http_get_request_body_ex((b), (l), 1 TSRMLS_CC)
|
||
+#define http_get_request_body_ex(b, l, d) _http_get_request_body_ex((b), (l), (d) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC);
|
||
+
|
||
+#define http_get_request_body_stream() _http_get_request_body_stream(TSRMLS_C)
|
||
+PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D);
|
||
+
|
||
+
|
||
+typedef void (*http_parse_params_callback)(void *cb_arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC);
|
||
+
|
||
+#define http_parse_params_default_callback _http_parse_params_default_callback
|
||
+PHP_HTTP_API void _http_parse_params_default_callback(void *ht, const char *key, int keylen, const char *val, int vallen TSRMLS_DC);
|
||
+
|
||
+#define http_parse_params(s, f, ht) _http_parse_params_ex((s), (f), _http_parse_params_default_callback, (ht) TSRMLS_CC)
|
||
+#define http_parse_params_ex(s, f, cb, a) _http_parse_params_ex((s), (f), (cb), (a) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_parse_params_ex(const char *params, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC);
|
||
+
|
||
+
|
||
+#define http_sleep(s) _http_sleep(s)
|
||
+static inline void _http_sleep(double s)
|
||
+{
|
||
+#define HTTP_DIFFSEC (0.001)
|
||
+#define HTTP_MLLISEC (1000)
|
||
+#define HTTP_MCROSEC (1000 * 1000)
|
||
+#define HTTP_NANOSEC (1000 * 1000 * 1000)
|
||
+#define HTTP_MSEC(s) ((long)(s * HTTP_MLLISEC))
|
||
+#define HTTP_USEC(s) ((long)(s * HTTP_MCROSEC))
|
||
+#define HTTP_NSEC(s) ((long)(s * HTTP_NANOSEC))
|
||
+
|
||
+#if defined(PHP_WIN32)
|
||
+ Sleep((DWORD) HTTP_MSEC(s));
|
||
+#elif defined(HAVE_USLEEP)
|
||
+ usleep(HTTP_USEC(s));
|
||
+#elif defined(HAVE_NANOSLEEP)
|
||
+ struct timespec req, rem;
|
||
+
|
||
+ req.tv_sec = (time_t) s;
|
||
+ req.tv_nsec = HTTP_NSEC(s) % HTTP_NANOSEC;
|
||
+
|
||
+ while (nanosleep(&req, &rem) && (errno == EINTR) && (HTTP_NSEC(rem.tv_sec) + rem.tv_nsec) > HTTP_NSEC(HTTP_DIFFSEC))) {
|
||
+ req.tv_sec = rem.tv_sec;
|
||
+ req.tv_nsec = rem.tv_nsec;
|
||
+ }
|
||
+#else
|
||
+ struct timeval timeout;
|
||
+
|
||
+ timeout.tv.sec = (time_t) s;
|
||
+ timeout.tv_usec = HTTP_USEC(s) % HTTP_MCROSEC;
|
||
+
|
||
+ select(0, NULL, NULL, NULL, &timeout);
|
||
+#endif
|
||
+}
|
||
+
|
||
+#define http_locate_str _http_locate_str
|
||
+static inline const char *_http_locate_str(const char *h, size_t h_len, const char *n, size_t n_len)
|
||
+{
|
||
+ const char *p, *e;
|
||
+
|
||
+ if (n_len && h_len) {
|
||
+ e = h + h_len;
|
||
+ do {
|
||
+ if (*h == *n) {
|
||
+ for (p = n; *p == h[p-n]; ++p) {
|
||
+ if (p == n+n_len-1) {
|
||
+ return h;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ } while (h++ != e);
|
||
+ }
|
||
+
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+#define http_locate_body _http_locate_body
|
||
+static inline const char *_http_locate_body(const char *message)
|
||
+{
|
||
+ const char *body = NULL, *msg = message;
|
||
+
|
||
+ while (*msg) {
|
||
+ if (*msg == '\n') {
|
||
+ if (*(msg+1) == '\n') {
|
||
+ body = msg + 2;
|
||
+ break;
|
||
+ } else if (*(msg+1) == '\r' && *(msg+2) == '\n') {
|
||
+ body = msg + 3;
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ ++msg;
|
||
+ }
|
||
+ return body;
|
||
+}
|
||
+
|
||
+#define http_locate_eol _http_locate_eol
|
||
+static inline const char *_http_locate_eol(const char *line, int *eol_len)
|
||
+{
|
||
+ const char *eol = strpbrk(line, "\r\n");
|
||
+
|
||
+ if (eol_len) {
|
||
+ *eol_len = eol ? ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1) : 0;
|
||
+ }
|
||
+ return eol;
|
||
+}
|
||
+
|
||
+#define http_zset(t, z) _http_zset((t), (z))
|
||
+static inline zval *_http_zset(int type, zval *z)
|
||
+{
|
||
+ if (Z_TYPE_P(z) != type) {
|
||
+ switch (type) {
|
||
+ case IS_NULL: convert_to_null(z); break;
|
||
+ case IS_BOOL: convert_to_boolean(z); break;
|
||
+ case IS_LONG: convert_to_long(z); break;
|
||
+ case IS_DOUBLE: convert_to_double(z); break;
|
||
+ case IS_STRING: convert_to_string(z); break;
|
||
+ case IS_ARRAY: convert_to_array(z); break;
|
||
+ case IS_OBJECT: convert_to_object(z); break;
|
||
+ }
|
||
+ }
|
||
+ return z;
|
||
+}
|
||
+#define http_zsep(t, z) _http_zsep_ex((t), (z), NULL)
|
||
+#define http_zsep_ex(t, z, p) _http_zsep_ex((t), (z), (p))
|
||
+static inline zval *_http_zsep_ex(int type, zval *z, zval **p) {
|
||
+ 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;
|
||
+ }
|
||
+ }
|
||
+ if (p) {
|
||
+ *p = z;
|
||
+ }
|
||
+ return z;
|
||
+}
|
||
+
|
||
+typedef struct _HashKey {
|
||
+ char *str;
|
||
+ uint len;
|
||
+ ulong num;
|
||
+ uint dup:1;
|
||
+ uint type:31;
|
||
+} HashKey;
|
||
+#define initHashKey(dup) {NULL, 0, 0, (dup), 0}
|
||
+
|
||
+#define FOREACH_VAL(pos, array, val) FOREACH_HASH_VAL(pos, Z_ARRVAL_P(array), val)
|
||
+#define FOREACH_HASH_VAL(pos, hash, val) \
|
||
+ for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
|
||
+ zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
|
||
+ zend_hash_move_forward_ex(hash, &pos))
|
||
+
|
||
+#define FOREACH_KEY(pos, array, key) FOREACH_HASH_KEY(pos, Z_ARRVAL_P(array), key)
|
||
+#define FOREACH_HASH_KEY(pos, hash, _key) \
|
||
+ for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
|
||
+ ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT; \
|
||
+ zend_hash_move_forward_ex(hash, &pos)) \
|
||
+
|
||
+#define FOREACH_KEYVAL(pos, array, key, val) FOREACH_HASH_KEYVAL(pos, Z_ARRVAL_P(array), key, val)
|
||
+#define FOREACH_HASH_KEYVAL(pos, hash, _key, val) \
|
||
+ for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
|
||
+ ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT && \
|
||
+ zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
|
||
+ 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_join(src, dst, append, flags) zend_hash_apply_with_arguments(src HTTP_ZAPI_HASH_TSRMLS_CC, (append)?apply_array_append_func:apply_array_merge_func, 2, dst, (int)flags)
|
||
+
|
||
+extern int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
|
||
+extern int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_cache_api.h
|
||
@@ -0,0 +1,162 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_cache_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_CACHE_API_H
|
||
+#define PHP_HTTP_CACHE_API_H
|
||
+
|
||
+#include "php_http_send_api.h"
|
||
+
|
||
+#include "ext/standard/crc32.h"
|
||
+#include "ext/standard/sha1.h"
|
||
+#include "ext/standard/md5.h"
|
||
+
|
||
+#ifdef HTTP_HAVE_HASH
|
||
+# include "php_hash.h"
|
||
+#endif
|
||
+
|
||
+#define http_etag_digest(d, l) _http_etag_digest((d), (l))
|
||
+static inline char *_http_etag_digest(const unsigned char *digest, int len)
|
||
+{
|
||
+ static const char hexdigits[17] = "0123456789abcdef";
|
||
+ int i;
|
||
+ char *hex = emalloc(len * 2 + 1);
|
||
+ char *ptr = hex;
|
||
+
|
||
+ for (i = 0; i < len; ++i) {
|
||
+ *ptr++ = hexdigits[digest[i] >> 4];
|
||
+ *ptr++ = hexdigits[digest[i] & 0xF];
|
||
+ }
|
||
+ *ptr = '\0';
|
||
+
|
||
+ return hex;
|
||
+}
|
||
+
|
||
+#define http_etag_init() _http_etag_init(TSRMLS_C)
|
||
+static inline void *_http_etag_init(TSRMLS_D)
|
||
+{
|
||
+ void *ctx = NULL;
|
||
+ char *mode = HTTP_G->etag.mode;
|
||
+
|
||
+#ifdef HTTP_HAVE_HASH
|
||
+ const php_hash_ops *eho = NULL;
|
||
+
|
||
+ if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
|
||
+ ctx = emalloc(eho->context_size);
|
||
+ eho->hash_init(ctx);
|
||
+ } else
|
||
+#endif
|
||
+ if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
|
||
+ ctx = emalloc(sizeof(uint));
|
||
+ *((uint *) ctx) = ~0;
|
||
+ } else if (mode && !strcasecmp(mode, "sha1")) {
|
||
+ PHP_SHA1Init(ctx = emalloc(sizeof(PHP_SHA1_CTX)));
|
||
+ } else {
|
||
+ PHP_MD5Init(ctx = emalloc(sizeof(PHP_MD5_CTX)));
|
||
+ }
|
||
+
|
||
+ return ctx;
|
||
+}
|
||
+
|
||
+#define http_etag_finish(c) _http_etag_finish((c) TSRMLS_CC)
|
||
+static inline char *_http_etag_finish(void *ctx TSRMLS_DC)
|
||
+{
|
||
+ unsigned char digest[128] = {0};
|
||
+ char *etag = NULL, *mode = HTTP_G->etag.mode;
|
||
+
|
||
+#ifdef HTTP_HAVE_HASH
|
||
+ const php_hash_ops *eho = NULL;
|
||
+
|
||
+ if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
|
||
+ eho->hash_final(digest, ctx);
|
||
+ etag = http_etag_digest(digest, eho->digest_size);
|
||
+ } else
|
||
+#endif
|
||
+ if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
|
||
+ *((uint *) ctx) = ~*((uint *) ctx);
|
||
+ etag = http_etag_digest((const unsigned char *) ctx, sizeof(uint));
|
||
+ } else if (mode && (!strcasecmp(mode, "sha1"))) {
|
||
+ PHP_SHA1Final(digest, ctx);
|
||
+ etag = http_etag_digest(digest, 20);
|
||
+ } else {
|
||
+ PHP_MD5Final(digest, ctx);
|
||
+ etag = http_etag_digest(digest, 16);
|
||
+ }
|
||
+ efree(ctx);
|
||
+
|
||
+ return etag;
|
||
+}
|
||
+
|
||
+#define http_etag_update(c, d, l) _http_etag_update((c), (d), (l) TSRMLS_CC)
|
||
+static inline void _http_etag_update(void *ctx, const char *data_ptr, size_t data_len TSRMLS_DC)
|
||
+{
|
||
+ char *mode = HTTP_G->etag.mode;
|
||
+#ifdef HTTP_HAVE_HASH
|
||
+ const php_hash_ops *eho = NULL;
|
||
+
|
||
+ if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
|
||
+ eho->hash_update(ctx, (const unsigned char *) data_ptr, data_len);
|
||
+ } else
|
||
+#endif
|
||
+ if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
|
||
+ uint i, c = *((uint *) ctx);
|
||
+ for (i = 0; i < data_len; ++i) {
|
||
+ CRC32(c, data_ptr[i]);
|
||
+ }
|
||
+ *((uint *)ctx) = c;
|
||
+ } else if (mode && (!strcasecmp(mode, "sha1"))) {
|
||
+ PHP_SHA1Update(ctx, (const unsigned char *) data_ptr, data_len);
|
||
+ } else {
|
||
+ PHP_MD5Update(ctx, (const unsigned char *) data_ptr, data_len);
|
||
+ }
|
||
+}
|
||
+
|
||
+#define http_ob_etaghandler(o, l, ho, hl, m) _http_ob_etaghandler((o), (l), (ho), (hl), (m) TSRMLS_CC)
|
||
+extern void _http_ob_etaghandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC);
|
||
+
|
||
+#define http_etag(p, l, m) _http_etag((p), (l), (m) TSRMLS_CC)
|
||
+PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC);
|
||
+
|
||
+#define http_last_modified(p, m) _http_last_modified((p), (m) TSRMLS_CC)
|
||
+PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC);
|
||
+
|
||
+#define http_match_last_modified(entry, modified) _http_match_last_modified_ex((entry), (modified), 1 TSRMLS_CC)
|
||
+#define http_match_last_modified_ex(entry, modified, ep) _http_match_last_modified_ex((entry), (modified), (ep) TSRMLS_CC)
|
||
+PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC);
|
||
+
|
||
+#define http_match_etag(entry, etag) _http_match_etag_ex((entry), (etag), 1 TSRMLS_CC)
|
||
+#define http_match_etag_ex(entry, etag, ep) _http_match_etag_ex((entry), (etag), (ep) TSRMLS_CC)
|
||
+PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC);
|
||
+
|
||
+#define http_cache_last_modified(l, s, cc, ccl) _http_cache_last_modified((l), (s), (cc), (ccl) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_cache_last_modified(time_t last_modified, time_t send_modified, const char *cache_control, size_t cc_len TSRMLS_DC);
|
||
+
|
||
+#define http_cache_etag(e, el, cc, ccl) _http_cache_etag((e), (el), (cc), (ccl) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len, const char *cache_control, size_t cc_len TSRMLS_DC);
|
||
+
|
||
+#define http_start_ob_etaghandler() _http_start_ob_etaghandler(TSRMLS_C)
|
||
+PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D);
|
||
+#define http_interrupt_ob_etaghandler() _http_interrupt_ob_etaghandler(TSRMLS_C)
|
||
+PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_cookie_api.h
|
||
@@ -0,0 +1,86 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_cookie_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_COOKIE_API_H
|
||
+#define PHP_HTTP_COOKIE_API_H
|
||
+
|
||
+#define HTTP_COOKIE_SECURE 0x10L
|
||
+#define HTTP_COOKIE_HTTPONLY 0x20L
|
||
+
|
||
+#define HTTP_COOKIE_PARSE_RAW 0x01L
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_cookie);
|
||
+
|
||
+/*
|
||
+ generally a netscape cookie compliant struct, recognizing httpOnly attribute, too;
|
||
+ cookie params like those from rfc2109 and rfc2965 are just put into extras, if
|
||
+ one specifies them in allowed extras, else they're treated like cookies themself
|
||
+*/
|
||
+typedef struct _http_cookie_list_t {
|
||
+ HashTable cookies;
|
||
+ HashTable extras;
|
||
+ long flags;
|
||
+ char *path;
|
||
+ char *domain;
|
||
+ time_t expires;
|
||
+} http_cookie_list;
|
||
+
|
||
+#define http_cookie_list_new() _http_cookie_list_init(NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+#define http_cookie_list_init(l) _http_cookie_list_init((l) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API http_cookie_list *_http_cookie_list_init(http_cookie_list *list ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_dtor(l) _http_cookie_list_dtor((l) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_free(l) _http_cookie_list_free((l) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_has_cookie(list, name, name_len) zend_hash_exists(&(list)->cookies, (name), (name_len)+1)
|
||
+#define http_cookie_list_has_extra(list, name, name_len) zend_hash_exists(&(list)->extras, (name), (name_len)+1)
|
||
+
|
||
+#define http_cookie_list_add_cookie(l, n, nl, v, vl) _http_cookie_list_add_cookie((l), (n), (nl), (v), (vl) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_cookie_list_add_cookie(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_add_extra(l, n , nl, v, vl) _http_cookie_list_add_extra((l), (n), (nl), (v), (vl) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_cookie_list_add_extra(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_get_cookie(l, n, nl) _http_cookie_list_get_cookie((l), (n), (nl) TSRMLS_CC)
|
||
+PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_get_extra(l, n, nl) _http_cookie_list_get_extra((l), (n), (nl) TSRMLS_CC)
|
||
+PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC);
|
||
+
|
||
+#define http_parse_cookie(s) _http_parse_cookie_ex(NULL, (s), 0, NULL TSRMLS_CC)
|
||
+#define http_parse_cookie_ex(l, s, f, a) _http_parse_cookie_ex((l), (s), (f), (a) TSRMLS_CC)
|
||
+PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list * list, const char *string, long flags, char **allowed_extras TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_tostruct(l, s) _http_cookie_list_tostruct((l), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_fromstruct(l, s) _http_cookie_list_fromstruct((l), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC);
|
||
+
|
||
+#define http_cookie_list_tostring(l, str, len) _http_cookie_list_tostring((l), (str), (len) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_date_api.h
|
||
@@ -0,0 +1,35 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_date_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_DATE_API_H
|
||
+#define PHP_HTTP_DATE_API_H
|
||
+
|
||
+#define http_date(t) _http_date((t) TSRMLS_CC)
|
||
+PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC);
|
||
+
|
||
+#define http_parse_date(d) _http_parse_date_ex((d), 0 TSRMLS_CC)
|
||
+#define http_parse_date_ex(d, s) _http_parse_date_ex((d), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_deflatestream_object.h
|
||
@@ -0,0 +1,57 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_deflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_DEFLATESTREAM_OBJECT_H
|
||
+#define PHP_HTTP_DEFLATESTREAM_OBJECT_H
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+typedef struct _http_deflatestream_object_t {
|
||
+ zend_object zo;
|
||
+ http_encoding_stream *stream;
|
||
+} http_deflatestream_object;
|
||
+
|
||
+extern zend_class_entry *http_deflatestream_object_ce;
|
||
+extern zend_function_entry http_deflatestream_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_deflatestream_object);
|
||
+
|
||
+#define http_deflatestream_object_new(ce) _http_deflatestream_object_new((ce) TSRMLS_CC)
|
||
+extern zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC);
|
||
+#define http_deflatestream_object_new_ex(ce, s, ptr) _http_deflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
|
||
+extern zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC);
|
||
+#define http_deflatestream_object_clone(zobj) _http_deflatestream_object_clone_obj(zobj TSRMLS_CC)
|
||
+extern zend_object_value _http_deflatestream_object_clone_obj(zval *object TSRMLS_DC);
|
||
+#define http_deflatestream_object_free(o) _http_deflatestream_object_free((o) TSRMLS_CC)
|
||
+extern void _http_deflatestream_object_free(zend_object *object TSRMLS_DC);
|
||
+
|
||
+PHP_METHOD(HttpDeflateStream, __construct);
|
||
+PHP_METHOD(HttpDeflateStream, factory);
|
||
+PHP_METHOD(HttpDeflateStream, update);
|
||
+PHP_METHOD(HttpDeflateStream, flush);
|
||
+PHP_METHOD(HttpDeflateStream, finish);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_encoding_api.h
|
||
@@ -0,0 +1,192 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_encoding_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_ENCODING_API_H
|
||
+#define PHP_HTTP_ENCODING_API_H
|
||
+
|
||
+#define http_encoding_dechunk(e, el, d, dl) _http_encoding_dechunk((e), (el), (d), (dl) TSRMLS_CC)
|
||
+PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC);
|
||
+
|
||
+#define http_encoding_response_start(cl, i) _http_encoding_response_start((cl), (i) TSRMLS_CC)
|
||
+PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC);
|
||
+
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_encoding);
|
||
+extern PHP_RINIT_FUNCTION(http_encoding);
|
||
+extern PHP_RSHUTDOWN_FUNCTION(http_encoding);
|
||
+
|
||
+typedef enum _http_encoding_type_t {
|
||
+ HTTP_ENCODING_NONE,
|
||
+ HTTP_ENCODING_GZIP,
|
||
+ HTTP_ENCODING_DEFLATE,
|
||
+} http_encoding_type;
|
||
+
|
||
+#define HTTP_INFLATE_ROUNDS 100
|
||
+
|
||
+#define HTTP_DEFLATE_BUFFER_SIZE_GUESS(S) \
|
||
+ (((size_t) ((double) S * (double) 1.015)) + 10 + 8 + 4 + 1)
|
||
+#define HTTP_INFLATE_BUFFER_SIZE_GUESS(S) \
|
||
+ (((S) + 1) << 3)
|
||
+#define HTTP_INFLATE_BUFFER_SIZE_ALIGN(S) \
|
||
+ ((S) += (S) >> (3))
|
||
+
|
||
+#define HTTP_DEFLATE_BUFFER_SIZE 0x8000
|
||
+#define HTTP_INFLATE_BUFFER_SIZE 0x1000
|
||
+
|
||
+#define HTTP_DEFLATE_LEVEL_DEF 0x00000000
|
||
+#define HTTP_DEFLATE_LEVEL_MIN 0x00000001
|
||
+#define HTTP_DEFLATE_LEVEL_MAX 0x00000009
|
||
+#define HTTP_DEFLATE_TYPE_ZLIB 0x00000000
|
||
+#define HTTP_DEFLATE_TYPE_GZIP 0x00000010
|
||
+#define HTTP_DEFLATE_TYPE_RAW 0x00000020
|
||
+#define HTTP_DEFLATE_STRATEGY_DEF 0x00000000
|
||
+#define HTTP_DEFLATE_STRATEGY_FILT 0x00000100
|
||
+#define HTTP_DEFLATE_STRATEGY_HUFF 0x00000200
|
||
+#define HTTP_DEFLATE_STRATEGY_RLE 0x00000300
|
||
+#define HTTP_DEFLATE_STRATEGY_FIXED 0x00000400
|
||
+
|
||
+#define HTTP_DEFLATE_LEVEL_SET(flags, level) \
|
||
+ switch (flags & 0xf) \
|
||
+ { \
|
||
+ default: \
|
||
+ if ((flags & 0xf) < 10) { \
|
||
+ level = flags & 0xf; \
|
||
+ break; \
|
||
+ } \
|
||
+ case HTTP_DEFLATE_LEVEL_DEF: \
|
||
+ level = Z_DEFAULT_COMPRESSION; \
|
||
+ break; \
|
||
+ }
|
||
+
|
||
+#define HTTP_DEFLATE_WBITS_SET(flags, wbits) \
|
||
+ switch (flags & 0xf0) \
|
||
+ { \
|
||
+ case HTTP_DEFLATE_TYPE_GZIP: \
|
||
+ wbits = HTTP_WINDOW_BITS_GZIP; \
|
||
+ break; \
|
||
+ case HTTP_DEFLATE_TYPE_RAW: \
|
||
+ wbits = HTTP_WINDOW_BITS_RAW; \
|
||
+ break; \
|
||
+ default: \
|
||
+ wbits = HTTP_WINDOW_BITS_ZLIB; \
|
||
+ break; \
|
||
+ }
|
||
+
|
||
+#define HTTP_INFLATE_WBITS_SET(flags, wbits) \
|
||
+ if (flags & HTTP_INFLATE_TYPE_RAW) { \
|
||
+ wbits = HTTP_WINDOW_BITS_RAW; \
|
||
+} else { \
|
||
+ wbits = HTTP_WINDOW_BITS_ANY; \
|
||
+}
|
||
+
|
||
+#define HTTP_DEFLATE_STRATEGY_SET(flags, strategy) \
|
||
+ switch (flags & 0xf00) \
|
||
+ { \
|
||
+ case HTTP_DEFLATE_STRATEGY_FILT: \
|
||
+ strategy = Z_FILTERED; \
|
||
+ break; \
|
||
+ case HTTP_DEFLATE_STRATEGY_HUFF: \
|
||
+ strategy = Z_HUFFMAN_ONLY; \
|
||
+ break; \
|
||
+ case HTTP_DEFLATE_STRATEGY_RLE: \
|
||
+ strategy = Z_RLE; \
|
||
+ break; \
|
||
+ case HTTP_DEFLATE_STRATEGY_FIXED: \
|
||
+ strategy = Z_FIXED; \
|
||
+ break; \
|
||
+ default: \
|
||
+ strategy = Z_DEFAULT_STRATEGY; \
|
||
+ break; \
|
||
+ }
|
||
+
|
||
+#define HTTP_WINDOW_BITS_ZLIB 0x0000000f
|
||
+#define HTTP_WINDOW_BITS_GZIP 0x0000001f
|
||
+#define HTTP_WINDOW_BITS_ANY 0x0000002f
|
||
+#define HTTP_WINDOW_BITS_RAW -0x000000f
|
||
+
|
||
+#ifndef Z_FIXED
|
||
+/* Z_FIXED does not exist prior 1.2.2.2 */
|
||
+# define Z_FIXED 0
|
||
+#endif
|
||
+
|
||
+#define HTTP_INFLATE_TYPE_ZLIB 0x00000000
|
||
+#define HTTP_INFLATE_TYPE_GZIP 0x00000000
|
||
+#define HTTP_INFLATE_TYPE_RAW 0x00000001
|
||
+
|
||
+#define HTTP_ENCODING_STREAM_FLUSH_NONE 0x00000000
|
||
+#define HTTP_ENCODING_STREAM_FLUSH_SYNC 0x00100000
|
||
+#define HTTP_ENCODING_STREAM_FLUSH_FULL 0x00200000
|
||
+
|
||
+#define HTTP_ENCODING_STREAM_FLUSH_FLAG(f) \
|
||
+ (((f) & HTTP_ENCODING_STREAM_FLUSH_FULL) ? Z_FULL_FLUSH : \
|
||
+ (((f) & HTTP_ENCODING_STREAM_FLUSH_SYNC) ? Z_SYNC_FLUSH : Z_NO_FLUSH))
|
||
+
|
||
+#define HTTP_ENCODING_STREAM_PERSISTENT 0x01000000
|
||
+
|
||
+typedef struct _http_encoding_stream_t {
|
||
+ z_stream stream;
|
||
+ int flags;
|
||
+ void *storage;
|
||
+} http_encoding_stream;
|
||
+
|
||
+#define http_encoding_deflate(f, d, dl, r, rl) _http_encoding_deflate((f), (d), (dl), (r), (rl) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_inflate(d, dl, r, rl) _http_encoding_inflate((d), (dl), (r), (rl) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+
|
||
+#define http_encoding_deflate_stream_init(s, f) _http_encoding_deflate_stream_init((s), (f) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_deflate_stream_update(s, d, dl, e, el) _http_encoding_deflate_stream_update((s), (d), (dl), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_deflate_stream_flush(s, e, el) _http_encoding_deflate_stream_flush((s), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_flush(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_deflate_stream_finish(s, e, el) _http_encoding_deflate_stream_finish((s), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_deflate_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_deflate_stream_dtor(s) _http_encoding_deflate_stream_dtor((s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
|
||
+#define http_encoding_deflate_stream_free(s) _http_encoding_deflate_stream_free((s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC);
|
||
+
|
||
+#define http_encoding_inflate_stream_init(s, f) _http_encoding_inflate_stream_init((s), (f) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API http_encoding_stream *_http_encoding_inflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_inflate_stream_update(s, d, dl, e, el) _http_encoding_inflate_stream_update((s), (d), (dl), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_inflate_stream_flush(s, d, dl) _http_encoding_inflate_stream_flush((s), (d), (dl) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_flush(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_inflate_stream_finish(s, e, el) _http_encoding_inflate_stream_finish((s), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_encoding_inflate_stream_finish(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+#define http_encoding_inflate_stream_dtor(s) _http_encoding_inflate_stream_dtor((s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
|
||
+#define http_encoding_inflate_stream_free(s) _http_encoding_inflate_stream_free((s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC);
|
||
+
|
||
+#define http_ob_deflatehandler(o, ol, h, hl, m) _http_ob_deflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC)
|
||
+extern void _http_ob_deflatehandler(char *, uint, char **, uint *, int TSRMLS_DC);
|
||
+
|
||
+#define http_ob_inflatehandler(o, ol, h, hl, m) _http_ob_inflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC)
|
||
+extern void _http_ob_inflatehandler(char *, uint, char **, uint *, int TSRMLS_DC);
|
||
+
|
||
+#endif /* HTTP_HAVE_ZLIB */
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_exception_object.h
|
||
@@ -0,0 +1,60 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_exception_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_EXCEPTION_OBJECT_H
|
||
+#define PHP_HTTP_EXCEPTION_OBJECT_H
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#include "zend_exceptions.h"
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_exception_object);
|
||
+
|
||
+#define HTTP_EX_DEF_CE http_exception_object_ce
|
||
+#define HTTP_EX_CE(name) http_ ##name## _exception_object_ce
|
||
+
|
||
+extern zend_class_entry *http_exception_object_ce;
|
||
+extern zend_class_entry *HTTP_EX_CE(runtime);
|
||
+extern zend_class_entry *HTTP_EX_CE(header);
|
||
+extern zend_class_entry *HTTP_EX_CE(malformed_headers);
|
||
+extern zend_class_entry *HTTP_EX_CE(request_method);
|
||
+extern zend_class_entry *HTTP_EX_CE(message_type);
|
||
+extern zend_class_entry *HTTP_EX_CE(invalid_param);
|
||
+extern zend_class_entry *HTTP_EX_CE(encoding);
|
||
+extern zend_class_entry *HTTP_EX_CE(request);
|
||
+extern zend_class_entry *HTTP_EX_CE(request_pool);
|
||
+extern zend_class_entry *HTTP_EX_CE(socket);
|
||
+extern zend_class_entry *HTTP_EX_CE(response);
|
||
+extern zend_class_entry *HTTP_EX_CE(url);
|
||
+extern zend_function_entry http_exception_object_fe[];
|
||
+
|
||
+#define http_exception_get_default _http_exception_get_default
|
||
+extern zend_class_entry *_http_exception_get_default();
|
||
+
|
||
+#define http_exception_get_for_code(c) _http_exception_get_for_code(c)
|
||
+extern zend_class_entry *_http_exception_get_for_code(long code);
|
||
+
|
||
+PHP_METHOD(HttpException, __toString);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_filter_api.h
|
||
@@ -0,0 +1,33 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_filter_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_FILTER_API_H
|
||
+#define PHP_HTTP_FILTER_API_H
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+extern php_stream_filter_factory http_filter_factory;
|
||
+PHP_MINIT_FUNCTION(http_filter);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_headers_api.h
|
||
@@ -0,0 +1,77 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_headers_api.h 300300 2010-06-09 07:29:35Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_HEADERS_API_H
|
||
+#define PHP_HTTP_HEADERS_API_H
|
||
+
|
||
+#include "php_http_info_api.h"
|
||
+
|
||
+typedef enum http_range_status_t {
|
||
+ RANGE_OK,
|
||
+ RANGE_NO,
|
||
+ RANGE_ERR
|
||
+} http_range_status;
|
||
+
|
||
+#define http_parse_headers(h, a) _http_parse_headers_ex((h), Z_ARRVAL_P(a), 1, http_info_default_callback, NULL TSRMLS_CC)
|
||
+#define http_parse_headers_ex(h, ht, p) _http_parse_headers_ex((h), (ht), (p), http_info_default_callback, NULL TSRMLS_CC)
|
||
+#define http_parse_headers_cb(h, ht, p, f, d) _http_parse_headers_ex((h), (ht), (p), (f), (d) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *headers, zend_bool prettify, http_info_callback callback_func, void **callback_data TSRMLS_DC);
|
||
+
|
||
+typedef char *(*negotiate_func_t)(const char *test, double *quality, HashTable *supported TSRMLS_DC);
|
||
+
|
||
+#define http_negotiate_language_func _http_negotiate_language_func
|
||
+extern char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
|
||
+#define http_negotiate_content_type_func _http_negotiate_default_func
|
||
+#define http_negotiate_encoding_func _http_negotiate_default_func
|
||
+#define http_negotiate_charset_func _http_negotiate_default_func
|
||
+#define http_negotiate_default_func _http_negotiate_default_func
|
||
+extern char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
|
||
+
|
||
+#define http_negotiate_language(zsupported) http_negotiate_language_ex(Z_ARRVAL_P(zsupported))
|
||
+#define http_negotiate_language_ex(supported) http_negotiate_q("HTTP_ACCEPT_LANGUAGE", (supported), http_negotiate_language_func)
|
||
+#define http_negotiate_charset(zsupported) http_negotiate_charset_ex(Z_ARRVAL_P(zsupported))
|
||
+#define http_negotiate_charset_ex(supported) http_negotiate_q("HTTP_ACCEPT_CHARSET", (supported), http_negotiate_charset_func)
|
||
+#define http_negotiate_encoding(zsupported) http_negotiate_encoding_ex(Z_ARRVAL_P(zsupported))
|
||
+#define http_negotiate_encoding_ex(supported) http_negotiate_q("HTTP_ACCEPT_ENCODING", (supported), http_negotiate_encoding_func)
|
||
+#define http_negotiate_content_type(zsupported) http_negotiate_content_type_ex(Z_ARRVAL_P(zsupported))
|
||
+#define http_negotiate_content_type_ex(supported) http_negotiate_q("HTTP_ACCEPT", (supported), http_negotiate_content_type_func)
|
||
+#define http_negotiate_q(e, s, n) _http_negotiate_q((e), (s), (n) TSRMLS_CC)
|
||
+PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC);
|
||
+#define http_negotiate_z(z, s, n) _http_negotiate_z((z), (s), (n) TSRMLS_CC)
|
||
+PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC);
|
||
+
|
||
+#define http_get_request_ranges(r, l) _http_get_request_ranges((r), (l) TSRMLS_CC)
|
||
+PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC);
|
||
+
|
||
+#define http_get_request_headers(h) _http_get_request_headers((h) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC);
|
||
+
|
||
+#define http_get_response_headers(h) _http_get_response_headers((h) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC);
|
||
+
|
||
+#define http_match_request_header(h, v) http_match_request_header_ex((h), (v), 0)
|
||
+#define http_match_request_header_ex(h, v, c) _http_match_request_header_ex((h), (v), (c) TSRMLS_CC)
|
||
+PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_inflatestream_object.h
|
||
@@ -0,0 +1,57 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_inflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_INFLATESTREAM_OBJECT_H
|
||
+#define PHP_HTTP_INFLATESTREAM_OBJECT_H
|
||
+#ifdef HTTP_HAVE_ZLIB
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+typedef struct _http_inflatestream_object_t {
|
||
+ zend_object zo;
|
||
+ http_encoding_stream *stream;
|
||
+} http_inflatestream_object;
|
||
+
|
||
+extern zend_class_entry *http_inflatestream_object_ce;
|
||
+extern zend_function_entry http_inflatestream_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_inflatestream_object);
|
||
+
|
||
+#define http_inflatestream_object_new(ce) _http_inflatestream_object_new((ce) TSRMLS_CC)
|
||
+extern zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC);
|
||
+#define http_inflatestream_object_new_ex(ce, s, ptr) _http_inflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
|
||
+extern zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC);
|
||
+#define http_inflatestream_object_clone(zobj) _http_inflatestream_object_clone_obj(zobj TSRMLS_CC)
|
||
+extern zend_object_value _http_inflatestream_object_clone_obj(zval *object TSRMLS_DC);
|
||
+#define http_inflatestream_object_free(o) _http_inflatestream_object_free((o) TSRMLS_CC)
|
||
+extern void _http_inflatestream_object_free(zend_object *object TSRMLS_DC);
|
||
+
|
||
+PHP_METHOD(HttpInflateStream, __construct);
|
||
+PHP_METHOD(HttpInflateStream, factory);
|
||
+PHP_METHOD(HttpInflateStream, update);
|
||
+PHP_METHOD(HttpInflateStream, flush);
|
||
+PHP_METHOD(HttpInflateStream, finish);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_info_api.h
|
||
@@ -0,0 +1,79 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_info_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_INFO_API_H
|
||
+#define PHP_HTTP_INFO_API_H
|
||
+
|
||
+#define IS_HTTP_REQUEST 1
|
||
+#define IS_HTTP_RESPONSE 2
|
||
+
|
||
+#define HTTP_INFO(ptr) (ptr)->http.info
|
||
+
|
||
+#define HTTP_INFO_REQUEST_FMT_ARGS(_http_ptr, _EOL) "%s %s HTTP/%1.1f" _EOL, \
|
||
+ (_http_ptr)->info.request.method?(_http_ptr)->info.request.method:"UNKNOWN", \
|
||
+ (_http_ptr)->info.request.url?(_http_ptr)->info.request.url:"/", \
|
||
+ (_http_ptr)->version>0.0?(_http_ptr)->version:1.1
|
||
+
|
||
+#define HTTP_INFO_RESPONSE_FMT_ARGS(_http_ptr, _EOL) "HTTP/%1.1f %d%s%s" _EOL, \
|
||
+ (_http_ptr)->version>0.0?(_http_ptr)->version:1.1, \
|
||
+ (_http_ptr)->info.response.code?(_http_ptr)->info.response.code:200, \
|
||
+ (_http_ptr)->info.response.status&&*(_http_ptr)->info.response.status ? " ":"", \
|
||
+ STR_PTR((_http_ptr)->info.response.status)
|
||
+
|
||
+typedef struct _http_request_info_t {
|
||
+ char *method;
|
||
+ char *url;
|
||
+} http_request_info;
|
||
+
|
||
+typedef struct _http_response_info_t {
|
||
+ int code;
|
||
+ char *status;
|
||
+} http_response_info;
|
||
+
|
||
+typedef union _http_info_union_t {
|
||
+ http_request_info request;
|
||
+ http_response_info response;
|
||
+} http_info_union;
|
||
+
|
||
+struct http_info {
|
||
+ http_info_union info;
|
||
+ double version;
|
||
+};
|
||
+
|
||
+typedef struct _http_info_t {
|
||
+ struct http_info http;
|
||
+ int type;
|
||
+} http_info;
|
||
+
|
||
+typedef void (*http_info_callback)(void **callback_data, HashTable **headers, http_info *info TSRMLS_DC);
|
||
+
|
||
+#define http_info_default_callback _http_info_default_callback
|
||
+PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC);
|
||
+#define http_info_dtor _http_info_dtor
|
||
+PHP_HTTP_API void _http_info_dtor(http_info *info);
|
||
+#define http_info_parse(p, i) _http_info_parse_ex((p), (i), 1 TSRMLS_CC)
|
||
+#define http_info_parse_ex(p, i, s) _http_info_parse_ex((p), (i), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info , zend_bool silent TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_message_api.h
|
||
@@ -0,0 +1,131 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_message_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_MESSAGE_API_H
|
||
+#define PHP_HTTP_MESSAGE_API_H
|
||
+
|
||
+#include "php_http_info_api.h"
|
||
+
|
||
+typedef enum _http_message_type_t {
|
||
+ HTTP_MSG_NONE = 0,
|
||
+ HTTP_MSG_REQUEST = IS_HTTP_REQUEST,
|
||
+ HTTP_MSG_RESPONSE = IS_HTTP_RESPONSE,
|
||
+} http_message_type;
|
||
+
|
||
+typedef struct _http_message_t http_message;
|
||
+
|
||
+struct _http_message_t {
|
||
+ phpstr body;
|
||
+ HashTable hdrs;
|
||
+ http_message_type type;
|
||
+ struct http_info http;
|
||
+ http_message *parent;
|
||
+};
|
||
+
|
||
+/* required minimum length of an HTTP message "HTTP/1.1" */
|
||
+#define HTTP_MSG_MIN_SIZE 8
|
||
+
|
||
+/* shorthand for type checks */
|
||
+#define HTTP_MSG_TYPE(TYPE, msg) ((msg) && ((msg)->type == HTTP_MSG_ ##TYPE))
|
||
+
|
||
+#define http_message_new() http_message_init_ex(NULL, 0)
|
||
+#define http_message_init(m) http_message_init_ex((m), 0)
|
||
+#define http_message_init_ex(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
|
||
+#define http_message_init_rel(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
|
||
+PHP_HTTP_API http_message *_http_message_init_ex(http_message *m, http_message_type t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
|
||
+#define http_message_init_env(m, t) _http_message_init_env((m), (t) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
|
||
+PHP_HTTP_API http_message *_http_message_init_env(http_message *m, http_message_type t TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
|
||
+
|
||
+#define http_message_set_type(m, t) _http_message_set_type((m), (t))
|
||
+PHP_HTTP_API void _http_message_set_type(http_message *m, http_message_type t);
|
||
+
|
||
+#define http_message_set_info(m, i) _http_message_set_info((m), (i))
|
||
+PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info);
|
||
+
|
||
+#define http_message_header(m, h) _http_message_header_ex((m), (h), sizeof(h), 1)
|
||
+#define http_message_header_ex _http_message_header_ex
|
||
+static inline zval *_http_message_header_ex(http_message *msg, char *key_str, size_t key_len, int join)
|
||
+{
|
||
+ zval **header;
|
||
+ if (SUCCESS == zend_hash_find(&msg->hdrs, key_str, key_len, (void *) &header)) {
|
||
+ if (join && Z_TYPE_PP(header) == IS_ARRAY) {
|
||
+ zval *header_str, **val;
|
||
+ HashPosition pos;
|
||
+ phpstr str;
|
||
+
|
||
+ phpstr_init(&str);
|
||
+ MAKE_STD_ZVAL(header_str);
|
||
+ FOREACH_VAL(pos, *header, val) {
|
||
+ phpstr_appendf(&str, PHPSTR_LEN(&str) ? ", %s":"%s", Z_STRVAL_PP(val));
|
||
+ }
|
||
+ phpstr_fix(&str);
|
||
+ ZVAL_STRINGL(header_str, PHPSTR_VAL(&str), PHPSTR_LEN(&str), 0);
|
||
+ return header_str;
|
||
+ } else {
|
||
+ ZVAL_ADDREF(*header);
|
||
+ return *header;
|
||
+ }
|
||
+ }
|
||
+ return NULL;
|
||
+}
|
||
+
|
||
+#define http_message_count(c, m) \
|
||
+{ \
|
||
+ http_message *__tmp_msg = (m); \
|
||
+ for (c = 0; __tmp_msg; __tmp_msg = __tmp_msg->parent, ++(c)); \
|
||
+}
|
||
+
|
||
+#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l))
|
||
+#define http_message_parse_ex(h, m, l) _http_message_parse_ex((h), (m), (l) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+#define http_message_parse_rel(h, m, l) _http_message_parse_ex((h), (m), (l) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+
|
||
+#define http_message_tostring(m, s, l) _http_message_tostring((m), (s), (l))
|
||
+PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length);
|
||
+
|
||
+#define http_message_serialize(m, s, l) _http_message_serialize((m), (s), (l))
|
||
+PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length);
|
||
+
|
||
+#define http_message_reverse(m) _http_message_reverse(m)
|
||
+PHP_HTTP_API http_message *_http_message_reverse(http_message *msg);
|
||
+
|
||
+#define http_message_interconnect(m1, m2) _http_message_interconnect((m1), (m2))
|
||
+PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2);
|
||
+
|
||
+#define http_message_tostruct_recursive(m, s) _http_message_tostruct_recursive((m), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *strct TSRMLS_DC);
|
||
+
|
||
+#define http_message_send(m) _http_message_send((m) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC);
|
||
+
|
||
+#define http_message_dup(m) _http_message_dup((m) TSRMLS_CC)
|
||
+PHP_HTTP_API http_message *_http_message_dup(http_message *msg TSRMLS_DC);
|
||
+
|
||
+#define http_message_dtor(m) _http_message_dtor((m))
|
||
+PHP_HTTP_API void _http_message_dtor(http_message *message);
|
||
+
|
||
+#define http_message_free(m) _http_message_free((m))
|
||
+PHP_HTTP_API void _http_message_free(http_message **message);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_message_object.h
|
||
@@ -0,0 +1,115 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_message_object.h 298590 2010-04-26 11:46:35Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_MESSAGE_OBJECT_H
|
||
+#define PHP_HTTP_MESSAGE_OBJECT_H
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+typedef struct _http_message_object_t {
|
||
+ zend_object zo;
|
||
+ http_message *message;
|
||
+ zend_object_value parent;
|
||
+ zval *iterator;
|
||
+} http_message_object;
|
||
+
|
||
+extern zend_class_entry *http_message_object_ce;
|
||
+extern zend_function_entry http_message_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_message_object);
|
||
+extern PHP_MSHUTDOWN_FUNCTION(http_message_object);
|
||
+
|
||
+#define http_message_object_prepend(o, p) http_message_object_prepend_ex((o), (p), 1)
|
||
+#define http_message_object_prepend_ex(o, p, t) _http_message_object_prepend_ex((o), (p), (t) TSRMLS_CC)
|
||
+extern void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC);
|
||
+
|
||
+#define http_message_object_reverse(t, r) _http_message_object_reverse((t), (r) TSRMLS_CC)
|
||
+extern void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC);
|
||
+
|
||
+#define http_message_object_new(ce) _http_message_object_new((ce) TSRMLS_CC)
|
||
+extern zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC);
|
||
+#define http_message_object_new_ex(ce, msg, ptr) _http_message_object_new_ex((ce), (msg), (ptr) TSRMLS_CC)
|
||
+extern zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC);
|
||
+#define http_message_object_clone(zobj) _http_message_object_clone_obj(zobj TSRMLS_CC)
|
||
+extern zend_object_value _http_message_object_clone_obj(zval *object TSRMLS_DC);
|
||
+#define http_message_object_free(o) _http_message_object_free((o) TSRMLS_CC)
|
||
+extern void _http_message_object_free(zend_object *object TSRMLS_DC);
|
||
+
|
||
+#define HTTP_MSG_CHECK_OBJ(obj, dofail) \
|
||
+ if (!(obj)->message) { \
|
||
+ http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is empty"); \
|
||
+ dofail; \
|
||
+ }
|
||
+#define HTTP_MSG_CHECK_STD() HTTP_MSG_CHECK_OBJ(obj, RETURN_FALSE)
|
||
+
|
||
+#define HTTP_MSG_INIT_OBJ(obj) \
|
||
+ if (!(obj)->message) { \
|
||
+ (obj)->message = http_message_new(); \
|
||
+ }
|
||
+#define HTTP_MSG_INIT_STD() HTTP_MSG_INIT_OBJ(obj)
|
||
+
|
||
+PHP_METHOD(HttpMessage, __construct);
|
||
+PHP_METHOD(HttpMessage, getBody);
|
||
+PHP_METHOD(HttpMessage, setBody);
|
||
+PHP_METHOD(HttpMessage, getHeader);
|
||
+PHP_METHOD(HttpMessage, getHeaders);
|
||
+PHP_METHOD(HttpMessage, setHeaders);
|
||
+PHP_METHOD(HttpMessage, addHeaders);
|
||
+PHP_METHOD(HttpMessage, getType);
|
||
+PHP_METHOD(HttpMessage, setType);
|
||
+PHP_METHOD(HttpMessage, getInfo);
|
||
+PHP_METHOD(HttpMessage, setInfo);
|
||
+PHP_METHOD(HttpMessage, getResponseCode);
|
||
+PHP_METHOD(HttpMessage, setResponseCode);
|
||
+PHP_METHOD(HttpMessage, getResponseStatus);
|
||
+PHP_METHOD(HttpMessage, setResponseStatus);
|
||
+PHP_METHOD(HttpMessage, getRequestMethod);
|
||
+PHP_METHOD(HttpMessage, setRequestMethod);
|
||
+PHP_METHOD(HttpMessage, getRequestUrl);
|
||
+PHP_METHOD(HttpMessage, setRequestUrl);
|
||
+PHP_METHOD(HttpMessage, getHttpVersion);
|
||
+PHP_METHOD(HttpMessage, setHttpVersion);
|
||
+PHP_METHOD(HttpMessage, guessContentType);
|
||
+PHP_METHOD(HttpMessage, getParentMessage);
|
||
+PHP_METHOD(HttpMessage, send);
|
||
+PHP_METHOD(HttpMessage, toString);
|
||
+PHP_METHOD(HttpMessage, toMessageTypeObject);
|
||
+
|
||
+PHP_METHOD(HttpMessage, count);
|
||
+PHP_METHOD(HttpMessage, serialize);
|
||
+PHP_METHOD(HttpMessage, unserialize);
|
||
+PHP_METHOD(HttpMessage, rewind);
|
||
+PHP_METHOD(HttpMessage, valid);
|
||
+PHP_METHOD(HttpMessage, current);
|
||
+PHP_METHOD(HttpMessage, key);
|
||
+PHP_METHOD(HttpMessage, next);
|
||
+
|
||
+PHP_METHOD(HttpMessage, factory);
|
||
+PHP_METHOD(HttpMessage, fromEnv);
|
||
+
|
||
+PHP_METHOD(HttpMessage, detach);
|
||
+PHP_METHOD(HttpMessage, prepend);
|
||
+PHP_METHOD(HttpMessage, reverse);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_persistent_handle_api.h
|
||
@@ -0,0 +1,58 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_persistent_handle_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef HTTP_PERSISTENT_HANDLE_H
|
||
+#define HTTP_PERSISTENT_HANDLE_H
|
||
+
|
||
+typedef void *(*http_persistent_handle_ctor)(void);
|
||
+typedef void (*http_persistent_handle_dtor)(void *handle);
|
||
+typedef void *(*http_persistent_handle_copy)(void *handle);
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_persistent_handle);
|
||
+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle);
|
||
+
|
||
+#define http_persistent_handle_provide(n, c, d, cc) _http_persistent_handle_provide_ex((n), strlen(n), (c), (d), (cc))
|
||
+#define http_persistent_handle_provide_ex(n, l, c, d, cc) _http_persistent_handle_provide_ex((n), (l), (c), (d), (cc))
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor, http_persistent_handle_copy copy);
|
||
+
|
||
+#define http_persistent_handle_cleanup(n, c) _http_persistent_handle_cleanup_ex((n), strlen(n), (c) TSRMLS_CC)
|
||
+#define http_persistent_handle_cleanup_ex(n, l,c ) _http_persistent_handle_cleanup_ex((n), (l), (c) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC);
|
||
+
|
||
+#define http_persistent_handle_statall() _http_persistent_handle_statall_ex(NULL TSRMLS_CC)
|
||
+#define http_persistent_handle_statall_ex(ht) _http_persistent_handle_statall_ex((ht) TSRMLS_CC)
|
||
+PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC);
|
||
+
|
||
+#define http_persistent_handle_acquire(n, h) _http_persistent_handle_acquire_ex((n), strlen(n), (h) TSRMLS_CC)
|
||
+#define http_persistent_handle_acquire_ex(n, l, h) _http_persistent_handle_acquire_ex((n), (l), (h) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
|
||
+
|
||
+#define http_persistent_handle_release(n, h) _http_persistent_handle_release_ex((n), strlen(n), (h) TSRMLS_CC)
|
||
+#define http_persistent_handle_release_ex(n, l, h) _http_persistent_handle_release_ex((n), (l), (h) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
|
||
+
|
||
+#define http_persistent_handle_accrete(n, oh, nh) _http_persistent_handle_accrete_ex((n), strlen(n), (oh), (nh) TSRMLS_CC)
|
||
+#define http_persistent_handle_accrete_ex(n, l, oh, nh) _http_persistent_handle_accrete_ex((n), (l), (oh), (nh) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_persistent_handle_accrete_ex(const char *name_str, size_t name_len, void *old_handle, void **new_handle TSRMLS_DC);
|
||
+
|
||
+#endif /* HTTP_PERSISTENT_HANDLE_H */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_querystring_api.h
|
||
@@ -0,0 +1,38 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_querystring_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_QUERYSTRING_API_H
|
||
+#define PHP_HTTP_QUERYSTRING_API_H
|
||
+
|
||
+#ifdef HTTP_HAVE_ICONV
|
||
+#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC)
|
||
+PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC);
|
||
+#endif
|
||
+
|
||
+#define http_querystring_update(qa, qs) _http_querystring_update((qa), (qs) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC);
|
||
+
|
||
+#define http_querystring_modify(q, p) _http_querystring_modify((q), (p) TSRMLS_CC)
|
||
+PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_querystring_object.h
|
||
@@ -0,0 +1,78 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_querystring_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_QUERYSTRING_OBJECT_H
|
||
+#define PHP_HTTP_QUERYSTRING_OBJECT_H
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+typedef struct _http_querystring_object_t {
|
||
+ zend_object zo;
|
||
+} http_querystring_object;
|
||
+
|
||
+#define HTTP_QUERYSTRING_TYPE_BOOL IS_BOOL
|
||
+#define HTTP_QUERYSTRING_TYPE_INT IS_LONG
|
||
+#define HTTP_QUERYSTRING_TYPE_FLOAT IS_DOUBLE
|
||
+#define HTTP_QUERYSTRING_TYPE_STRING IS_STRING
|
||
+#define HTTP_QUERYSTRING_TYPE_ARRAY IS_ARRAY
|
||
+#define HTTP_QUERYSTRING_TYPE_OBJECT IS_OBJECT
|
||
+
|
||
+extern zend_class_entry *http_querystring_object_ce;
|
||
+extern zend_function_entry http_querystring_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_querystring_object);
|
||
+
|
||
+#define http_querystring_object_new(ce) _http_querystring_object_new((ce) TSRMLS_CC)
|
||
+extern zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC);
|
||
+#define http_querystring_object_new_ex(ce, n, ptr) _http_querystring_object_new_ex((ce), (n), (ptr) TSRMLS_CC)
|
||
+extern zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC);
|
||
+#define http_querystring_object_free(o) _http_querystring_object_free((o) TSRMLS_CC)
|
||
+extern void _http_querystring_object_free(zend_object *object TSRMLS_DC);
|
||
+
|
||
+PHP_METHOD(HttpQueryString, __construct);
|
||
+PHP_METHOD(HttpQueryString, toString);
|
||
+PHP_METHOD(HttpQueryString, toArray);
|
||
+PHP_METHOD(HttpQueryString, get);
|
||
+PHP_METHOD(HttpQueryString, set);
|
||
+PHP_METHOD(HttpQueryString, mod);
|
||
+PHP_METHOD(HttpQueryString, getBool);
|
||
+PHP_METHOD(HttpQueryString, getInt);
|
||
+PHP_METHOD(HttpQueryString, getFloat);
|
||
+PHP_METHOD(HttpQueryString, getString);
|
||
+PHP_METHOD(HttpQueryString, getArray);
|
||
+PHP_METHOD(HttpQueryString, getObject);
|
||
+#ifdef HTTP_HAVE_ICONV
|
||
+PHP_METHOD(HttpQueryString, xlate);
|
||
+#endif
|
||
+PHP_METHOD(HttpQueryString, factory);
|
||
+#ifndef WONKY
|
||
+PHP_METHOD(HttpQueryString, singleton);
|
||
+#endif
|
||
+PHP_METHOD(HttpQueryString, serialize);
|
||
+PHP_METHOD(HttpQueryString, unserialize);
|
||
+PHP_METHOD(HttpQueryString, offsetGet);
|
||
+PHP_METHOD(HttpQueryString, offsetSet);
|
||
+PHP_METHOD(HttpQueryString, offsetExists);
|
||
+PHP_METHOD(HttpQueryString, offsetUnset);
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_request_api.h
|
||
@@ -0,0 +1,144 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_request_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUEST_API_H
|
||
+#define PHP_HTTP_REQUEST_API_H
|
||
+
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+
|
||
+#include "php_http_request_body_api.h"
|
||
+#include "php_http_request_method_api.h"
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_request);
|
||
+extern PHP_MSHUTDOWN_FUNCTION(http_request);
|
||
+
|
||
+typedef struct _http_request_t {
|
||
+ CURL *ch;
|
||
+ char *url;
|
||
+ http_request_method meth;
|
||
+ http_request_body *body;
|
||
+
|
||
+ struct {
|
||
+ curl_infotype last_type;
|
||
+ phpstr request;
|
||
+ phpstr response;
|
||
+ } conv;
|
||
+
|
||
+ struct {
|
||
+ phpstr cookies;
|
||
+ HashTable options;
|
||
+ struct curl_slist *headers;
|
||
+ } _cache;
|
||
+
|
||
+ struct {
|
||
+ uint count;
|
||
+ double delay;
|
||
+ } _retry;
|
||
+
|
||
+ char _error[CURL_ERROR_SIZE+1];
|
||
+ zval *_progress_callback;
|
||
+
|
||
+#ifdef ZTS
|
||
+ void ***tsrm_ls;
|
||
+#endif
|
||
+
|
||
+ uint _in_progress_cb:1;
|
||
+
|
||
+} http_request;
|
||
+
|
||
+#ifndef pestrndup
|
||
+# define pestrndup(s,l,p) _pestrndup((s),(l),(p))
|
||
+static inline void *_pestrndup(const void *s, size_t l, int p)
|
||
+{
|
||
+ void *d = pemalloc(l+1, p);
|
||
+ memcpy(d, s, l);
|
||
+ ((char *) d)[l] = '\0';
|
||
+ return d;
|
||
+}
|
||
+#endif
|
||
+
|
||
+/* CURLOPT_PRIVATE storage living as long as a CURL handle */
|
||
+typedef struct _http_request_storage_t {
|
||
+ char *url;
|
||
+ char *cookiestore;
|
||
+ char errorbuffer[CURL_ERROR_SIZE];
|
||
+} http_request_storage;
|
||
+
|
||
+static inline http_request_storage *http_request_storage_get(CURL *ch)
|
||
+{
|
||
+ http_request_storage *st = NULL;
|
||
+ curl_easy_getinfo(ch, CURLINFO_PRIVATE, &st);
|
||
+ return st;
|
||
+}
|
||
+
|
||
+#define http_curl_init(r) http_curl_init_ex(NULL, (r))
|
||
+#define http_curl_init_ex(c, r) _http_curl_init_ex((c), (r) TSRMLS_CC)
|
||
+PHP_HTTP_API CURL *_http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC);
|
||
+
|
||
+#define http_curl_free(c) _http_curl_free((c) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC);
|
||
+
|
||
+#define http_curl_copy(c) _http_curl_copy((c) TSRMLS_CC)
|
||
+PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC);
|
||
+
|
||
+#define http_request_new() _http_request_init_ex(NULL, NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+#define http_request_init(r) _http_request_init_ex((r), NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+#define http_request_init_ex(r, c, m, u) _http_request_init_ex((r), (c), (m), (u) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API http_request *_http_request_init_ex(http_request *request, CURL *ch, http_request_method meth, const char *url ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+
|
||
+#define http_request_dtor(r) _http_request_dtor((r))
|
||
+PHP_HTTP_API void _http_request_dtor(http_request *request);
|
||
+
|
||
+#define http_request_free(r) _http_request_free((r))
|
||
+PHP_HTTP_API void _http_request_free(http_request **request);
|
||
+
|
||
+#define http_request_reset(r) _http_request_reset(r)
|
||
+PHP_HTTP_API void _http_request_reset(http_request *r);
|
||
+
|
||
+#define http_request_enable_cookies(r) _http_request_enable_cookies(r)
|
||
+PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request);
|
||
+
|
||
+#define http_request_reset_cookies(r, s) _http_request_reset_cookies((r), (s))
|
||
+PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only);
|
||
+
|
||
+#define http_request_flush_cookies(r) _http_request_flush_cookies(r)
|
||
+PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request);
|
||
+
|
||
+#define http_request_defaults(r) _http_request_defaults(r)
|
||
+PHP_HTTP_API void _http_request_defaults(http_request *request);
|
||
+
|
||
+#define http_request_prepare(r, o) _http_request_prepare((r), (o))
|
||
+PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options);
|
||
+
|
||
+#define http_request_exec(r) _http_request_exec((r))
|
||
+PHP_HTTP_API void _http_request_exec(http_request *request);
|
||
+
|
||
+#define http_request_info(r, i) _http_request_info((r), (i))
|
||
+PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info);
|
||
+
|
||
+#define http_request_set_progress_callback(r, cb) _http_request_set_progress_callback((r), (cb))
|
||
+PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_request_body_api.h
|
||
@@ -0,0 +1,62 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_request_body_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUEST_BODY_API_H
|
||
+#define PHP_HTTP_REQUEST_BODY_API_H
|
||
+
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+
|
||
+#define HTTP_REQUEST_BODY_EMPTY 0
|
||
+#define HTTP_REQUEST_BODY_CSTRING 1
|
||
+#define HTTP_REQUEST_BODY_CURLPOST 2
|
||
+#define HTTP_REQUEST_BODY_UPLOADFILE 3
|
||
+typedef struct _http_request_body_t {
|
||
+ void *data;
|
||
+ size_t size;
|
||
+ uint type:3;
|
||
+ uint free:1;
|
||
+ uint priv:28;
|
||
+} http_request_body;
|
||
+
|
||
+
|
||
+#define http_request_body_new() http_request_body_init(NULL)
|
||
+#define http_request_body_init(b) http_request_body_init_ex((b), 0, NULL, 0, 0)
|
||
+#define http_request_body_init_ex(b, t, d, l, f) _http_request_body_init_ex((b), (t), (d), (l), (f) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+#define http_request_body_init_rel(b, t, d, l, f) _http_request_body_init_ex((b), (t), (d), (l), (f) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API http_request_body *_http_request_body_init_ex(http_request_body *body, int type, void *data, size_t len, zend_bool free ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+
|
||
+#define http_request_body_fill(b, fields, files) _http_request_body_fill((b), (fields), (files) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
|
||
+PHP_HTTP_API http_request_body *_http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC);
|
||
+
|
||
+#define http_request_body_encode(b, s, l) _http_request_body_encode((b), (s), (l) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC);
|
||
+
|
||
+#define http_request_body_dtor(b) _http_request_body_dtor((b) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC);
|
||
+
|
||
+#define http_request_body_free(b) _http_request_body_free((b) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_request_datashare_api.h
|
||
@@ -0,0 +1,88 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_request_datashare_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUEST_DATASHARE_API_H
|
||
+#define PHP_HTTP_REQUEST_DATASHARE_API_H
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#ifdef ZTS
|
||
+typedef struct _http_request_datashare_lock_t {
|
||
+ CURL *ch;
|
||
+ MUTEX_T mx;
|
||
+} http_request_datashare_lock;
|
||
+
|
||
+typedef union _http_request_datashare_handle_t {
|
||
+ zend_llist *list;
|
||
+ http_request_datashare_lock *locks;
|
||
+} http_request_datashare_handle;
|
||
+#else
|
||
+typedef struct _http_request_datashare_handle_t {
|
||
+ zend_llist *list;
|
||
+} http_request_datashare_handle;
|
||
+#endif
|
||
+
|
||
+typedef struct _http_request_datashare_t {
|
||
+ CURLSH *ch;
|
||
+ zend_bool persistent;
|
||
+ http_request_datashare_handle handle;
|
||
+} http_request_datashare;
|
||
+
|
||
+#define HTTP_RSHARE_HANDLES(s) ((s)->persistent ? &HTTP_G->request.datashare.handles : (s)->handle.list)
|
||
+
|
||
+#define http_request_datashare_global_get _http_request_datashare_global_get
|
||
+extern http_request_datashare *_http_request_datashare_global_get(void);
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_request_datashare);
|
||
+extern PHP_MSHUTDOWN_FUNCTION(http_request_datashare);
|
||
+extern PHP_RINIT_FUNCTION(http_request_datashare);
|
||
+extern PHP_RSHUTDOWN_FUNCTION(http_request_datashare);
|
||
+
|
||
+#define http_request_datashare_new() _http_request_datashare_init_ex(NULL, 0 TSRMLS_CC)
|
||
+#define http_request_datashare_init(s) _http_request_datashare_init_ex((s), 0 TSRMLS_CC)
|
||
+#define http_request_datashare_init_ex(s, p) _http_request_datashare_init_ex((s), (p) TSRMLS_CC)
|
||
+PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC);
|
||
+
|
||
+#define http_request_datashare_attach(s, r) _http_request_datashare_attach((s), (r) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC);
|
||
+
|
||
+#define http_request_datashare_detach(s, r) _http_request_datashare_detach((s), (r) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC);
|
||
+
|
||
+#define http_request_datashare_detach_all(s) _http_request_datashare_detach_all((s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC);
|
||
+
|
||
+#define http_request_datashare_dtor(s) _http_request_datashare_dtor((s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC);
|
||
+
|
||
+#define http_request_datashare_free(s) _http_request_datashare_free((s) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC);
|
||
+
|
||
+#define http_request_datashare_set(s, o, l, e) _http_request_datashare_set((s), (o), (l), (e) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC);
|
||
+
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_request_int.h
|
||
@@ -0,0 +1,72 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_request_int.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#if defined(ZTS) && defined(HTTP_HAVE_SSL)
|
||
+# ifdef PHP_WIN32
|
||
+# define HTTP_NEED_OPENSSL_TSL
|
||
+# include <openssl/crypto.h>
|
||
+# else /* !PHP_WIN32 */
|
||
+# if defined(HTTP_HAVE_OPENSSL)
|
||
+# define HTTP_NEED_OPENSSL_TSL
|
||
+# include <openssl/crypto.h>
|
||
+# elif defined(HTTP_HAVE_GNUTLS)
|
||
+# define 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 /* HTTP_HAVE_OPENSSL || HTTP_HAVE_GNUTLS */
|
||
+# endif /* PHP_WIN32 */
|
||
+#endif /* ZTS && HTTP_HAVE_SSL */
|
||
+
|
||
+#define HTTP_CURL_OPT(OPTION, p) curl_easy_setopt((request->ch), OPTION, (p))
|
||
+
|
||
+#define HTTP_CURL_OPT_STRING(OPTION, ldiff, obdc) \
|
||
+ { \
|
||
+ char *K = #OPTION; \
|
||
+ HTTP_CURL_OPT_STRING_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION, obdc); \
|
||
+ }
|
||
+#define HTTP_CURL_OPT_STRING_EX(keyname, optname, obdc) \
|
||
+ if (!strcasecmp(key.str, keyname)) { \
|
||
+ zval *copy = http_request_option_cache_ex(request, keyname, strlen(keyname)+1, 0, http_zsep(IS_STRING, *param)); \
|
||
+ if (obdc) { \
|
||
+ HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(copy), return FAILURE); \
|
||
+ } \
|
||
+ HTTP_CURL_OPT(optname, Z_STRVAL_P(copy)); \
|
||
+ zval_ptr_dtor(©); \
|
||
+ continue; \
|
||
+ }
|
||
+#define HTTP_CURL_OPT_LONG(OPTION, ldiff) \
|
||
+ { \
|
||
+ char *K = #OPTION; \
|
||
+ HTTP_CURL_OPT_LONG_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION); \
|
||
+ }
|
||
+#define HTTP_CURL_OPT_LONG_EX(keyname, optname) \
|
||
+ if (!strcasecmp(key.str, keyname)) { \
|
||
+ zval *copy = http_zsep(IS_LONG, *param); \
|
||
+ HTTP_CURL_OPT(optname, Z_LVAL_P(copy)); \
|
||
+ zval_ptr_dtor(©); \
|
||
+ continue; \
|
||
+ }
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_request_method_api.h
|
||
@@ -0,0 +1,85 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_request_method_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUEST_METHOD_API_H
|
||
+#define PHP_HTTP_REQUEST_METHOD_API_H
|
||
+
|
||
+typedef enum _http_request_method_t {
|
||
+ /* force the enum to be signed */
|
||
+ HTTP_NEG_REQUEST_METHOD =-1,
|
||
+ HTTP_NO_REQUEST_METHOD = 0,
|
||
+ /* HTTP/1.1 */
|
||
+ HTTP_GET = 1,
|
||
+ HTTP_HEAD = 2,
|
||
+ HTTP_POST = 3,
|
||
+ HTTP_PUT = 4,
|
||
+ HTTP_DELETE = 5,
|
||
+ HTTP_OPTIONS = 6,
|
||
+ HTTP_TRACE = 7,
|
||
+ HTTP_CONNECT = 8,
|
||
+ /* WebDAV - RFC 2518 */
|
||
+ HTTP_PROPFIND = 9,
|
||
+ HTTP_PROPPATCH = 10,
|
||
+ HTTP_MKCOL = 11,
|
||
+ HTTP_COPY = 12,
|
||
+ HTTP_MOVE = 13,
|
||
+ HTTP_LOCK = 14,
|
||
+ HTTP_UNLOCK = 15,
|
||
+ /* WebDAV Versioning - RFC 3253 */
|
||
+ HTTP_VERSION_CONTROL = 16,
|
||
+ HTTP_REPORT = 17,
|
||
+ HTTP_CHECKOUT = 18,
|
||
+ HTTP_CHECKIN = 19,
|
||
+ HTTP_UNCHECKOUT = 20,
|
||
+ HTTP_MKWORKSPACE = 21,
|
||
+ HTTP_UPDATE = 22,
|
||
+ HTTP_LABEL = 23,
|
||
+ HTTP_MERGE = 24,
|
||
+ HTTP_BASELINE_CONTROL = 25,
|
||
+ HTTP_MKACTIVITY = 26,
|
||
+ /* WebDAV Access Control - RFC 3744 */
|
||
+ HTTP_ACL = 27,
|
||
+ HTTP_MAX_REQUEST_METHOD = 28
|
||
+} http_request_method;
|
||
+
|
||
+#define HTTP_MIN_REQUEST_METHOD (HTTP_NO_REQUEST_METHOD + 1)
|
||
+#define HTTP_STD_REQUEST_METHOD(m) ((m > HTTP_NO_REQUEST_METHOD) && (m < HTTP_MAX_REQUEST_METHOD))
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_request_method);
|
||
+extern PHP_RINIT_FUNCTION(http_request_method);
|
||
+extern PHP_RSHUTDOWN_FUNCTION(http_request_method);
|
||
+
|
||
+#define http_request_method_name(m) _http_request_method_name((m) TSRMLS_CC)
|
||
+PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC);
|
||
+
|
||
+#define http_request_method_exists(u, l, c) _http_request_method_exists((u), (l), (c) TSRMLS_CC)
|
||
+PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id, const char *name TSRMLS_DC);
|
||
+
|
||
+#define http_request_method_register(m, l) _http_request_method_register((m), (l) TSRMLS_CC)
|
||
+PHP_HTTP_API int _http_request_method_register(const char *method, int method_name_len TSRMLS_DC);
|
||
+
|
||
+#define http_request_method_unregister(mn) _http_request_method_unregister((mn) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_request_object.h
|
||
@@ -0,0 +1,118 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_request_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUEST_OBJECT_H
|
||
+#define PHP_HTTP_REQUEST_OBJECT_H
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+#include "php_http_request_api.h"
|
||
+#include "php_http_request_pool_api.h"
|
||
+#include "php_http_request_datashare_api.h"
|
||
+
|
||
+typedef struct _http_request_object_t {
|
||
+ zend_object zo;
|
||
+ http_request *request;
|
||
+ http_request_pool *pool;
|
||
+ http_request_datashare *share;
|
||
+} http_request_object;
|
||
+
|
||
+extern zend_class_entry *http_request_object_ce;
|
||
+extern zend_function_entry http_request_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_request_object);
|
||
+
|
||
+#define http_request_object_new(ce) _http_request_object_new((ce) TSRMLS_CC)
|
||
+extern zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC);
|
||
+#define http_request_object_new_ex(ce, ch, ptr) _http_request_object_new_ex((ce), (ch), (ptr) TSRMLS_CC)
|
||
+extern zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC);
|
||
+#define http_request_object_clone(zv) _http_request_object_clone_obj((zv) TSRMLS_CC)
|
||
+extern zend_object_value _http_request_object_clone_obj(zval *zobject TSRMLS_DC);
|
||
+#define http_request_object_free(o) _http_request_object_free((o) TSRMLS_CC)
|
||
+extern void _http_request_object_free(zend_object *object TSRMLS_DC);
|
||
+
|
||
+#define http_request_object_requesthandler(req, this) _http_request_object_requesthandler((req), (this) TSRMLS_CC)
|
||
+extern STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC);
|
||
+#define http_request_object_responsehandler(req, this) _http_request_object_responsehandler((req), (this) TSRMLS_CC)
|
||
+extern STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC);
|
||
+
|
||
+PHP_METHOD(HttpRequest, __construct);
|
||
+PHP_METHOD(HttpRequest, setOptions);
|
||
+PHP_METHOD(HttpRequest, getOptions);
|
||
+PHP_METHOD(HttpRequest, addSslOptions);
|
||
+PHP_METHOD(HttpRequest, setSslOptions);
|
||
+PHP_METHOD(HttpRequest, getSslOptions);
|
||
+PHP_METHOD(HttpRequest, addHeaders);
|
||
+PHP_METHOD(HttpRequest, getHeaders);
|
||
+PHP_METHOD(HttpRequest, setHeaders);
|
||
+PHP_METHOD(HttpRequest, addCookies);
|
||
+PHP_METHOD(HttpRequest, getCookies);
|
||
+PHP_METHOD(HttpRequest, setCookies);
|
||
+PHP_METHOD(HttpRequest, enableCookies);
|
||
+PHP_METHOD(HttpRequest, resetCookies);
|
||
+PHP_METHOD(HttpRequest, flushCookies);
|
||
+PHP_METHOD(HttpRequest, setMethod);
|
||
+PHP_METHOD(HttpRequest, getMethod);
|
||
+PHP_METHOD(HttpRequest, setUrl);
|
||
+PHP_METHOD(HttpRequest, getUrl);
|
||
+PHP_METHOD(HttpRequest, setContentType);
|
||
+PHP_METHOD(HttpRequest, getContentType);
|
||
+PHP_METHOD(HttpRequest, setQueryData);
|
||
+PHP_METHOD(HttpRequest, getQueryData);
|
||
+PHP_METHOD(HttpRequest, addQueryData);
|
||
+PHP_METHOD(HttpRequest, setPostFields);
|
||
+PHP_METHOD(HttpRequest, getPostFields);
|
||
+PHP_METHOD(HttpRequest, addPostFields);
|
||
+PHP_METHOD(HttpRequest, getBody);
|
||
+PHP_METHOD(HttpRequest, setBody);
|
||
+PHP_METHOD(HttpRequest, addBody);
|
||
+PHP_METHOD(HttpRequest, addPostFile);
|
||
+PHP_METHOD(HttpRequest, setPostFiles);
|
||
+PHP_METHOD(HttpRequest, getPostFiles);
|
||
+PHP_METHOD(HttpRequest, setPutFile);
|
||
+PHP_METHOD(HttpRequest, getPutFile);
|
||
+PHP_METHOD(HttpRequest, getPutData);
|
||
+PHP_METHOD(HttpRequest, setPutData);
|
||
+PHP_METHOD(HttpRequest, addPutData);
|
||
+PHP_METHOD(HttpRequest, send);
|
||
+PHP_METHOD(HttpRequest, getResponseData);
|
||
+PHP_METHOD(HttpRequest, getResponseHeader);
|
||
+PHP_METHOD(HttpRequest, getResponseCookies);
|
||
+PHP_METHOD(HttpRequest, getResponseCode);
|
||
+PHP_METHOD(HttpRequest, getResponseStatus);
|
||
+PHP_METHOD(HttpRequest, getResponseBody);
|
||
+PHP_METHOD(HttpRequest, getResponseInfo);
|
||
+PHP_METHOD(HttpRequest, getResponseMessage);
|
||
+PHP_METHOD(HttpRequest, getRawResponseMessage);
|
||
+PHP_METHOD(HttpRequest, getRequestMessage);
|
||
+PHP_METHOD(HttpRequest, getRawRequestMessage);
|
||
+PHP_METHOD(HttpRequest, getHistory);
|
||
+PHP_METHOD(HttpRequest, clearHistory);
|
||
+PHP_METHOD(HttpRequest, getMessageClass);
|
||
+PHP_METHOD(HttpRequest, setMessageClass);
|
||
+PHP_METHOD(HttpRequest, factory);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_request_pool_api.h
|
||
@@ -0,0 +1,97 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_request_pool_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUEST_POOL_API_H
|
||
+#define PHP_HTTP_REQUEST_POOL_API_H
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+typedef struct _http_request_pool_t {
|
||
+ CURLM *ch;
|
||
+ zend_llist finished;
|
||
+ zend_llist handles;
|
||
+ int unfinished;
|
||
+#ifdef ZTS
|
||
+ void ***tsrm_ls;
|
||
+#endif
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+ struct event *timeout;
|
||
+ unsigned useevents:1;
|
||
+ unsigned runsocket:1;
|
||
+#endif
|
||
+} http_request_pool;
|
||
+
|
||
+typedef int (*http_request_pool_apply_func)(http_request_pool *pool, zval *request);
|
||
+typedef int (*http_request_pool_apply_with_arg_func)(http_request_pool *pool, zval *request, void *arg);
|
||
+
|
||
+PHP_MINIT_FUNCTION(http_request_pool);
|
||
+#ifdef HTTP_HAVE_EVENT
|
||
+PHP_RINIT_FUNCTION(http_request_pool);
|
||
+#endif
|
||
+
|
||
+#define http_request_pool_timeout _http_request_pool_timeout
|
||
+extern struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout);
|
||
+
|
||
+#define http_request_pool_responsehandler _http_request_pool_responsehandler
|
||
+extern void _http_request_pool_responsehandler(http_request_pool *pool);
|
||
+
|
||
+#define http_request_pool_apply_responsehandler _http_request_pool_responsehandler
|
||
+extern int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch);
|
||
+
|
||
+#define http_request_pool_init(p) _http_request_pool_init((p) TSRMLS_CC)
|
||
+PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC);
|
||
+
|
||
+#define http_request_pool_attach(p, r) _http_request_pool_attach((p), (r))
|
||
+PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request);
|
||
+
|
||
+#define http_request_pool_detach(p, r) _http_request_pool_detach((p), (r))
|
||
+PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request);
|
||
+
|
||
+#define http_request_pool_apply(p, f) _http_request_pool_apply((p), (f))
|
||
+PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb);
|
||
+
|
||
+#define http_request_pool_apply_with_arg(p, f, a) _http_request_pool_apply_with_arg((p), (f), (a))
|
||
+PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg);
|
||
+
|
||
+#define http_request_pool_detach_all(p) _http_request_pool_detach_all((p))
|
||
+PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool);
|
||
+
|
||
+#define http_request_pool_send(p) _http_request_pool_send((p))
|
||
+PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool);
|
||
+
|
||
+#define http_request_pool_select _http_request_pool_select
|
||
+PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool);
|
||
+
|
||
+#define http_request_pool_select_ex _http_request_pool_select_ex
|
||
+PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout);
|
||
+
|
||
+#define http_request_pool_perform(p) _http_request_pool_perform((p))
|
||
+PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool);
|
||
+
|
||
+#define http_request_pool_dtor(p) _http_request_pool_dtor((p))
|
||
+PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_requestdatashare_object.h
|
||
@@ -0,0 +1,59 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_requestdatashare_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUEST_DATASHARE_OBJECT_H
|
||
+#define PHP_HTTP_REQUEST_DATASHARE_OBJECT_H
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+typedef struct _http_requestdatashare_object_t {
|
||
+ zend_object zo;
|
||
+ http_request_datashare *share;
|
||
+} http_requestdatashare_object;
|
||
+
|
||
+extern zend_class_entry *http_requestdatashare_object_ce;
|
||
+extern zend_function_entry http_requestdatashare_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_requestdatashare_object);
|
||
+
|
||
+#define http_requestdatashare_object_new(ce) _http_requestdatashare_object_new((ce) TSRMLS_CC)
|
||
+extern zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC);
|
||
+#define http_requestdatashare_object_new_ex(ce, s, ptr) _http_requestdatashare_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
|
||
+extern zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC);
|
||
+#define http_requestdatashare_object_free(o) _http_requestdatashare_object_free((o) TSRMLS_CC)
|
||
+extern void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC);
|
||
+
|
||
+PHP_METHOD(HttpRequestDataShare, __destruct);
|
||
+PHP_METHOD(HttpRequestDataShare, count);
|
||
+PHP_METHOD(HttpRequestDataShare, attach);
|
||
+PHP_METHOD(HttpRequestDataShare, detach);
|
||
+PHP_METHOD(HttpRequestDataShare, reset);
|
||
+PHP_METHOD(HttpRequestDataShare, factory);
|
||
+#ifndef WONKY
|
||
+PHP_METHOD(HttpRequestDataShare, singleton);
|
||
+#endif
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_requestpool_object.h
|
||
@@ -0,0 +1,69 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_requestpool_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_REQUESTPOOL_OBJECT_H
|
||
+#define PHP_HTTP_REQUESTPOOL_OBJECT_H
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+typedef struct _http_requestpool_object_t {
|
||
+ zend_object zo;
|
||
+ http_request_pool pool;
|
||
+ struct {
|
||
+ long pos;
|
||
+ } iterator;
|
||
+} http_requestpool_object;
|
||
+
|
||
+extern zend_class_entry *http_requestpool_object_ce;
|
||
+extern zend_function_entry http_requestpool_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_requestpool_object);
|
||
+
|
||
+#define http_requestpool_object_new(ce) _http_requestpool_object_new(ce TSRMLS_CC)
|
||
+extern zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC);
|
||
+#define http_requestpool_object_free(o) _http_requestpool_object_free(o TSRMLS_CC)
|
||
+extern void _http_requestpool_object_free(zend_object *object TSRMLS_DC);
|
||
+
|
||
+PHP_METHOD(HttpRequestPool, __construct);
|
||
+PHP_METHOD(HttpRequestPool, __destruct);
|
||
+PHP_METHOD(HttpRequestPool, attach);
|
||
+PHP_METHOD(HttpRequestPool, detach);
|
||
+PHP_METHOD(HttpRequestPool, send);
|
||
+PHP_METHOD(HttpRequestPool, reset);
|
||
+PHP_METHOD(HttpRequestPool, socketPerform);
|
||
+PHP_METHOD(HttpRequestPool, socketSelect);
|
||
+PHP_METHOD(HttpRequestPool, valid);
|
||
+PHP_METHOD(HttpRequestPool, current);
|
||
+PHP_METHOD(HttpRequestPool, key);
|
||
+PHP_METHOD(HttpRequestPool, next);
|
||
+PHP_METHOD(HttpRequestPool, rewind);
|
||
+PHP_METHOD(HttpRequestPool, count);
|
||
+PHP_METHOD(HttpRequestPool, getAttachedRequests);
|
||
+PHP_METHOD(HttpRequestPool, getFinishedRequests);
|
||
+PHP_METHOD(HttpRequestPool, enablePipelining);
|
||
+PHP_METHOD(HttpRequestPool, enableEvents);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_response_object.h
|
||
@@ -0,0 +1,67 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_response_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_RESPONSE_OBJECT_H
|
||
+#define PHP_HTTP_RESPONSE_OBJECT_H
|
||
+#ifdef ZEND_ENGINE_2
|
||
+#ifndef WONKY
|
||
+
|
||
+extern zend_class_entry *http_response_object_ce;
|
||
+extern zend_function_entry http_response_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_response_object);
|
||
+
|
||
+PHP_METHOD(HttpResponse, setHeader);
|
||
+PHP_METHOD(HttpResponse, getHeader);
|
||
+PHP_METHOD(HttpResponse, setETag);
|
||
+PHP_METHOD(HttpResponse, getETag);
|
||
+PHP_METHOD(HttpResponse, setLastModified);
|
||
+PHP_METHOD(HttpResponse, getLastModified);
|
||
+PHP_METHOD(HttpResponse, setContentDisposition);
|
||
+PHP_METHOD(HttpResponse, getContentDisposition);
|
||
+PHP_METHOD(HttpResponse, setContentType);
|
||
+PHP_METHOD(HttpResponse, getContentType);
|
||
+PHP_METHOD(HttpResponse, guessContentType);
|
||
+PHP_METHOD(HttpResponse, setCache);
|
||
+PHP_METHOD(HttpResponse, getCache);
|
||
+PHP_METHOD(HttpResponse, setCacheControl);
|
||
+PHP_METHOD(HttpResponse, getCacheControl);
|
||
+PHP_METHOD(HttpResponse, setGzip);
|
||
+PHP_METHOD(HttpResponse, getGzip);
|
||
+PHP_METHOD(HttpResponse, setThrottleDelay);
|
||
+PHP_METHOD(HttpResponse, getThrottleDelay);
|
||
+PHP_METHOD(HttpResponse, setBufferSize);
|
||
+PHP_METHOD(HttpResponse, getBufferSize);
|
||
+PHP_METHOD(HttpResponse, setData);
|
||
+PHP_METHOD(HttpResponse, getData);
|
||
+PHP_METHOD(HttpResponse, setFile);
|
||
+PHP_METHOD(HttpResponse, getFile);
|
||
+PHP_METHOD(HttpResponse, setStream);
|
||
+PHP_METHOD(HttpResponse, getStream);
|
||
+PHP_METHOD(HttpResponse, send);
|
||
+PHP_METHOD(HttpResponse, capture);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_send_api.h
|
||
@@ -0,0 +1,91 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_send_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_SEND_API_H
|
||
+#define PHP_HTTP_SEND_API_H
|
||
+
|
||
+typedef enum _http_send_mode_t {
|
||
+ SEND_DATA,
|
||
+ SEND_RSRC
|
||
+} http_send_mode;
|
||
+
|
||
+#define HTTP_REDIRECT 0L
|
||
+#define HTTP_REDIRECT_PERM 301L
|
||
+#define HTTP_REDIRECT_FOUND 302L
|
||
+#define HTTP_REDIRECT_POST 303L
|
||
+#define HTTP_REDIRECT_PROXY 305L
|
||
+#define HTTP_REDIRECT_TEMP 307L
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_send);
|
||
+
|
||
+#define http_send_status(s) sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) (long) (s) TSRMLS_CC)
|
||
+#define http_send_header(n, v, r) _http_send_header_ex((n), strlen(n), (v), strlen(v), (r), NULL TSRMLS_CC)
|
||
+#define http_send_header_ex(n, nl, v, vl, r, s) _http_send_header_ex((n), (nl), (v), (vl), (r), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_header_ex(const char *name, size_t name_len, const char *value, size_t value_len, zend_bool replace, char **sent_header TSRMLS_DC);
|
||
+#define http_send_header_string(h) _http_send_status_header_ex(0, (h), strlen(h), 1 TSRMLS_CC)
|
||
+#define http_send_header_string_ex(h, l, r) _http_send_status_header_ex(0, (h), (l), (r) TSRMLS_CC)
|
||
+#define http_send_status_header(s, h) _http_send_status_header_ex((s), (h), (h)?strlen(h):0, 1 TSRMLS_CC)
|
||
+#define http_send_status_header_ex(s, h, l, r) _http_send_status_header_ex((s), (h), (l), (r) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC);
|
||
+
|
||
+#define http_send_header_zval(n, z, r) http_send_header_zval_ex((n), strlen(n), (z), (r))
|
||
+#define http_send_header_zval_ex(n, l, z, r) _http_send_header_zval_ex((n), (l), (z), (r) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC);
|
||
+
|
||
+#define http_hide_header(h) http_hide_header_ex((h), strlen(h))
|
||
+#define http_hide_header_ex(h, l) _http_hide_header_ex((h), (l) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC);
|
||
+
|
||
+#define http_send_last_modified(t) _http_send_last_modified_ex((t), NULL TSRMLS_CC)
|
||
+#define http_send_last_modified_ex(t, s) _http_send_last_modified_ex((t), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC);
|
||
+
|
||
+#define http_send_etag(e, l) _http_send_etag_ex((e), (l), NULL TSRMLS_CC)
|
||
+#define http_send_etag_ex(e, l, s) _http_send_etag_ex((e), (l), (s) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC);
|
||
+
|
||
+#define http_send_cache_control(cc, cl) http_send_header_ex("Cache-Control", lenof("Cache-Control"), (cc), (cl), 1, NULL)
|
||
+
|
||
+#define http_send_content_type(c, l) _http_send_content_type((c), (l) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC);
|
||
+
|
||
+#define http_send_content_disposition(f, l, i) _http_send_content_disposition((f), (l), (i) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC);
|
||
+
|
||
+#define http_send_data(d, l) http_send((d), (l), SEND_DATA)
|
||
+#define http_send_data_ex(d, l, nc) http_send_ex((d), (l), SEND_DATA, (nc))
|
||
+#define http_send(d, s, m) _http_send_ex((d), (s), (m), 0 TSRMLS_CC)
|
||
+#define http_send_ex(d, s, m, nc) _http_send_ex((d), (s), (m), (nc) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_ex(const void *data, size_t data_size, http_send_mode mode, zend_bool no_cache TSRMLS_DC);
|
||
+
|
||
+#define http_send_file(f) http_send_stream_ex(php_stream_open_wrapper_ex(f, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT), 1, 0)
|
||
+#define http_send_file_ex(f, nc) http_send_stream_ex(php_stream_open_wrapper_ex(f, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT), 1, (nc))
|
||
+#define http_send_stream(s) http_send_stream_ex((s), 0, 0)
|
||
+#define http_send_stream_ex(s, c, nc) _http_send_stream_ex((s), (c), (nc) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *s, zend_bool close_stream, zend_bool no_cache TSRMLS_DC);
|
||
+
|
||
+#define http_guess_content_type(mf, mm, d, l, m) _http_guess_content_type((mf), (mm), (d), (l), (m) TSRMLS_CC)
|
||
+PHP_HTTP_API char *_http_guess_content_type(const char *magic_file, long magic_mode, void *data_ptr, size_t data_len, http_send_mode mode TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_std_defs.h
|
||
@@ -0,0 +1,406 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_std_defs.h 310777 2011-05-05 06:43:10Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_STD_DEFS_H
|
||
+#define PHP_HTTP_STD_DEFS_H
|
||
+
|
||
+#if defined(PHP_WIN32)
|
||
+# if defined(HTTP_EXPORTS)
|
||
+# define PHP_HTTP_API __declspec(dllexport)
|
||
+# elif defined(COMPILE_DL_HTTP)
|
||
+# define PHP_HTTP_API __declspec(dllimport)
|
||
+# else
|
||
+# define PHP_HTTP_API
|
||
+# endif
|
||
+#else
|
||
+# define PHP_HTTP_API
|
||
+#endif
|
||
+
|
||
+/* make functions that return SUCCESS|FAILURE more obvious */
|
||
+typedef int STATUS;
|
||
+
|
||
+/* lenof() */
|
||
+#define lenof(S) (sizeof(S) - 1)
|
||
+
|
||
+#ifndef MIN
|
||
+# define MIN(a,b) (a<b?a:b)
|
||
+#endif
|
||
+#ifndef MAX
|
||
+# define MAX(a,b) (a>b?a:b)
|
||
+#endif
|
||
+
|
||
+/* STR_SET() */
|
||
+#ifndef STR_SET
|
||
+# define STR_SET(STR, SET) \
|
||
+ { \
|
||
+ STR_FREE(STR); \
|
||
+ STR = SET; \
|
||
+ }
|
||
+#endif
|
||
+
|
||
+#define STR_PTR(s) (s?s:"")
|
||
+
|
||
+#define INIT_ZARR(zv, ht) \
|
||
+ { \
|
||
+ INIT_PZVAL(&(zv)); \
|
||
+ Z_TYPE(zv) = IS_ARRAY; \
|
||
+ Z_ARRVAL(zv) = (ht); \
|
||
+ }
|
||
+
|
||
+/* return bool (v == SUCCESS) */
|
||
+#define RETVAL_SUCCESS(v) RETVAL_BOOL(SUCCESS == (v))
|
||
+#define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v))
|
||
+/* return object(values) */
|
||
+#define RETVAL_OBJECT(o, addref) \
|
||
+ RETVAL_OBJVAL((o)->value.obj, addref)
|
||
+#define RETURN_OBJECT(o, addref) \
|
||
+ RETVAL_OBJECT(o, addref); \
|
||
+ return
|
||
+#define RETVAL_OBJVAL(ov, addref) \
|
||
+ ZVAL_OBJVAL(return_value, ov, addref)
|
||
+#define RETURN_OBJVAL(ov, addref) \
|
||
+ RETVAL_OBJVAL(ov, addref); \
|
||
+ return
|
||
+#define ZVAL_OBJVAL(zv, ov, addref) \
|
||
+ (zv)->type = IS_OBJECT; \
|
||
+ (zv)->value.obj = (ov);\
|
||
+ if (addref && Z_OBJ_HT_P(zv)->add_ref) { \
|
||
+ Z_OBJ_HT_P(zv)->add_ref((zv) TSRMLS_CC); \
|
||
+ }
|
||
+/* return property */
|
||
+#define RETVAL_PROP(n) RETVAL_PROP_EX(getThis(), n)
|
||
+#define RETURN_PROP(n) RETURN_PROP_EX(getThis(), n)
|
||
+#define RETVAL_PROP_EX(this, n) \
|
||
+ { \
|
||
+ zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \
|
||
+ RETVAL_ZVAL(__prop, 1, 0); \
|
||
+ }
|
||
+#define RETURN_PROP_EX(this, n) \
|
||
+ { \
|
||
+ zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \
|
||
+ RETURN_ZVAL(__prop, 1, 0); \
|
||
+ }
|
||
+
|
||
+/* function accepts no args */
|
||
+#define NO_ARGS zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "");
|
||
+
|
||
+/* CR LF */
|
||
+#define HTTP_CRLF "\r\n"
|
||
+
|
||
+/* default cache control */
|
||
+#define HTTP_DEFAULT_CACHECONTROL "private, must-revalidate, max-age=0"
|
||
+
|
||
+/* max URL length */
|
||
+#define HTTP_URL_MAXLEN 4096
|
||
+
|
||
+/* max request method length */
|
||
+#define HTTP_REQUEST_METHOD_MAXLEN 31
|
||
+
|
||
+/* def URL arg separator */
|
||
+#define HTTP_URL_ARGSEP "&"
|
||
+
|
||
+/* send buffer size */
|
||
+#define HTTP_SENDBUF_SIZE 40960
|
||
+
|
||
+/* CURL buffer size */
|
||
+#define HTTP_CURLBUF_SIZE 16384
|
||
+
|
||
+/* known methods */
|
||
+#define HTTP_KNOWN_METHODS \
|
||
+ /* HTTP 1.1 */ \
|
||
+ "GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, " \
|
||
+ /* WebDAV - RFC 2518 */ \
|
||
+ "PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, " \
|
||
+ /* WebDAV Versioning - RFC 3253 */ \
|
||
+ "VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, " \
|
||
+ "MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, " \
|
||
+ /* WebDAV Access Control - RFC 3744 */ \
|
||
+ "ACL, " \
|
||
+ /* END */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+# include "ext/standard/file.h"
|
||
+# define HTTP_DEFAULT_STREAM_CONTEXT FG(default_context)
|
||
+#else
|
||
+# define HTTP_DEFAULT_STREAM_CONTEXT NULL
|
||
+#endif
|
||
+
|
||
+#define HTTP_PHP_INI_ENTRY(entry, default, scope, updater, global) \
|
||
+ STD_PHP_INI_ENTRY(entry, default, scope, updater, global, zend_http_globals, http_globals)
|
||
+#define HTTP_PHP_INI_ENTRY_EX(entry, default, scope, updater, displayer, global) \
|
||
+ STD_PHP_INI_ENTRY_EX(entry, default, scope, updater, global, zend_http_globals, http_globals, displayer)
|
||
+
|
||
+
|
||
+#define HTTP_LONG_CONSTANT(name, const) REGISTER_LONG_CONSTANT(name, const, CONST_CS | CONST_PERSISTENT)
|
||
+
|
||
+/* {{{ objects & properties */
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+# define HTTP_STATIC_ME_ALIAS(me, al, ai) ZEND_FENTRY(me, ZEND_FN(al), ai, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
|
||
+
|
||
+# define HTTP_REGISTER_CLASS_EX(classname, name, parent, flags) \
|
||
+ { \
|
||
+ zend_class_entry ce; \
|
||
+ memset(&ce, 0, sizeof(zend_class_entry)); \
|
||
+ INIT_CLASS_ENTRY(ce, #classname, name## _fe); \
|
||
+ ce.create_object = _ ##name## _new; \
|
||
+ name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
|
||
+ name## _ce->ce_flags |= flags; \
|
||
+ memcpy(& name## _handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
|
||
+ }
|
||
+
|
||
+# define HTTP_REGISTER_CLASS(classname, name, parent, flags) \
|
||
+ { \
|
||
+ zend_class_entry ce; \
|
||
+ memset(&ce, 0, sizeof(zend_class_entry)); \
|
||
+ INIT_CLASS_ENTRY(ce, #classname, name## _fe); \
|
||
+ ce.create_object = NULL; \
|
||
+ name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
|
||
+ name## _ce->ce_flags |= flags; \
|
||
+ }
|
||
+
|
||
+# define HTTP_REGISTER_EXCEPTION(classname, cename, parent) \
|
||
+ { \
|
||
+ zend_class_entry ce; \
|
||
+ memset(&ce, 0, sizeof(zend_class_entry)); \
|
||
+ INIT_CLASS_ENTRY(ce, #classname, NULL); \
|
||
+ ce.create_object = NULL; \
|
||
+ cename = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
|
||
+ }
|
||
+
|
||
+# define getObject(t, o) getObjectEx(t, o, getThis())
|
||
+# define getObjectEx(t, o, v) t * o = ((t *) zend_object_store_get_object(v TSRMLS_CC))
|
||
+# define putObject(t, o) zend_objects_store_put(o, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) _ ##t## _free, NULL TSRMLS_CC);
|
||
+# ifndef WONKY
|
||
+# define freeObject(o) \
|
||
+ if (OBJ_GUARDS(o)) { \
|
||
+ zend_hash_destroy(OBJ_GUARDS(o)); \
|
||
+ FREE_HASHTABLE(OBJ_GUARDS(o)); \
|
||
+ } \
|
||
+ if (OBJ_PROP(o)) { \
|
||
+ zend_hash_destroy(OBJ_PROP(o)); \
|
||
+ FREE_HASHTABLE(OBJ_PROP(o)); \
|
||
+ } \
|
||
+ efree(o);
|
||
+# else
|
||
+# define freeObject(o) \
|
||
+ if (OBJ_PROP(o)) { \
|
||
+ zend_hash_destroy(OBJ_PROP(o)); \
|
||
+ FREE_HASHTABLE(OBJ_PROP(o)); \
|
||
+ } \
|
||
+ efree(o);
|
||
+# endif
|
||
+# define OBJ_PROP(o) (o)->zo.properties
|
||
+# define OBJ_GUARDS(o) (o)->zo.guards
|
||
+
|
||
+# define ACC_PROP_PRIVATE(ce, flags) ((flags & ZEND_ACC_PRIVATE) && (EG(scope) && ce == EG(scope))
|
||
+# define ACC_PROP_PROTECTED(ce, flags) ((flags & ZEND_ACC_PROTECTED) && (zend_check_protected(ce, EG(scope))))
|
||
+# define ACC_PROP_PUBLIC(flags) (flags & ZEND_ACC_PUBLIC)
|
||
+# define ACC_PROP(ce, flags) (ACC_PROP_PUBLIC(flags) || ACC_PROP_PRIVATE(ce, flags) || ACC_PROP_PROTECTED(ce, flags))
|
||
+
|
||
+# define SET_EH_THROW_HTTP() SET_EH_THROW_EX(http_exception_get_default())
|
||
+# define SET_EH_THROW_EX(ex) php_set_error_handling(EH_THROW, ex TSRMLS_CC)
|
||
+# define SET_EH_NORMAL() php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC)
|
||
+
|
||
+#endif /* ZEND_ENGINE_2 */
|
||
+/* }}} */
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+# define with_error_handling(eh, ec) \
|
||
+ { \
|
||
+ error_handling_t __eh = GLOBAL_ERROR_HANDLING; \
|
||
+ zend_class_entry *__ec= GLOBAL_EXCEPTION_CLASS; \
|
||
+ php_set_error_handling(eh, ec TSRMLS_CC);
|
||
+# define end_error_handling() \
|
||
+ php_set_error_handling(__eh, __ec TSRMLS_CC); \
|
||
+ }
|
||
+#else
|
||
+# define with_error_handling(eh, ec)
|
||
+# define end_error_handling()
|
||
+#endif
|
||
+
|
||
+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 5
|
||
+# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default(TSRMLS_C)
|
||
+#else
|
||
+# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default()
|
||
+#endif
|
||
+
|
||
+#ifndef E_THROW
|
||
+# define E_THROW 0
|
||
+#endif
|
||
+#ifdef ZEND_ENGINE_2
|
||
+# define HE_THROW E_THROW TSRMLS_CC
|
||
+# define HE_NOTICE (HTTP_G->only_exceptions ? E_THROW : E_NOTICE) TSRMLS_CC
|
||
+# define HE_WARNING (HTTP_G->only_exceptions ? E_THROW : E_WARNING) TSRMLS_CC
|
||
+# define HE_ERROR (HTTP_G->only_exceptions ? E_THROW : E_ERROR) TSRMLS_CC
|
||
+#else
|
||
+# define HE_THROW E_WARNING TSRMLS_CC
|
||
+# define HE_NOTICE E_NOTICE TSRMLS_CC
|
||
+# define HE_WARNING E_WARNING TSRMLS_CC
|
||
+# define HE_ERROR E_ERROR TSRMLS_CC
|
||
+#endif
|
||
+
|
||
+#define HTTP_E_RUNTIME 1L
|
||
+#define HTTP_E_INVALID_PARAM 2L
|
||
+#define HTTP_E_HEADER 3L
|
||
+#define HTTP_E_MALFORMED_HEADERS 4L
|
||
+#define HTTP_E_REQUEST_METHOD 5L
|
||
+#define HTTP_E_MESSAGE_TYPE 6L
|
||
+#define HTTP_E_ENCODING 7L
|
||
+#define HTTP_E_REQUEST 8L
|
||
+#define HTTP_E_REQUEST_POOL 9L
|
||
+#define HTTP_E_SOCKET 10L
|
||
+#define HTTP_E_RESPONSE 11L
|
||
+#define HTTP_E_URL 12L
|
||
+#define HTTP_E_QUERYSTRING 13L
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+# define HTTP_BEGIN_ARGS_EX(class, method, ret_ref, req_args) HTTP_STATIC_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(args_for_ ##class## _ ##method , 0, ret_ref, req_args)
|
||
+# define HTTP_BEGIN_ARGS_AR(class, method, ret_ref, req_args) HTTP_STATIC_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(args_for_ ##class## _ ##method , 1, ret_ref, req_args)
|
||
+# define HTTP_END_ARGS }
|
||
+# define HTTP_EMPTY_ARGS_EX(class, method, ret_ref) HTTP_BEGIN_ARGS_EX(class, method, ret_ref, 0) HTTP_END_ARGS
|
||
+# define HTTP_ARGS(class, method) args_for_ ##class## _ ##method
|
||
+# define HTTP_ARG_VAL(name, pass_ref) ZEND_ARG_INFO(pass_ref, name)
|
||
+# define HTTP_ARG_OBJ(class, name, allow_null) ZEND_ARG_OBJ_INFO(0, name, class, allow_null)
|
||
+#endif
|
||
+
|
||
+#ifdef ZEND_ENGINE_2
|
||
+# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL, 0, 0}
|
||
+#else
|
||
+# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL}
|
||
+#endif
|
||
+
|
||
+#ifdef HTTP_HAVE_CURL
|
||
+# ifdef ZEND_ENGINE_2
|
||
+# define HTTP_DECLARE_ARG_PASS_INFO() \
|
||
+ HTTP_STATIC_ARG_INFO \
|
||
+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(1) \
|
||
+ ZEND_END_ARG_INFO(); \
|
||
+ \
|
||
+ HTTP_STATIC_ARG_INFO \
|
||
+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(1) \
|
||
+ ZEND_END_ARG_INFO(); \
|
||
+ \
|
||
+ HTTP_STATIC_ARG_INFO \
|
||
+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(1) \
|
||
+ ZEND_END_ARG_INFO(); \
|
||
+ \
|
||
+ HTTP_STATIC_ARG_INFO \
|
||
+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_5, 0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(1) \
|
||
+ ZEND_END_ARG_INFO();
|
||
+
|
||
+# else
|
||
+# define HTTP_DECLARE_ARG_PASS_INFO() \
|
||
+ static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \
|
||
+ static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
|
||
+ static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
|
||
+ static unsigned char http_arg_pass_ref_5[] = {5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
|
||
+# endif /* ZEND_ENGINE_2 */
|
||
+#else
|
||
+# ifdef ZEND_ENGINE_2
|
||
+# define HTTP_DECLARE_ARG_PASS_INFO() \
|
||
+ HTTP_STATIC_ARG_INFO \
|
||
+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(1) \
|
||
+ ZEND_END_ARG_INFO(); \
|
||
+\
|
||
+ HTTP_STATIC_ARG_INFO \
|
||
+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(1) \
|
||
+ ZEND_END_ARG_INFO(); \
|
||
+\
|
||
+ HTTP_STATIC_ARG_INFO \
|
||
+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(0) \
|
||
+ ZEND_ARG_PASS_INFO(1) \
|
||
+ ZEND_END_ARG_INFO();
|
||
+# else
|
||
+# define HTTP_DECLARE_ARG_PASS_INFO() \
|
||
+ static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \
|
||
+ static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
|
||
+ static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
|
||
+# endif /* ZEND_ENGINE_2 */
|
||
+#endif /* HTTP_HAVE_CURL */
|
||
+
|
||
+
|
||
+#ifndef HAVE_CURL_SHARE_STRERROR
|
||
+# define curl_share_strerror(dummy) "unknown error"
|
||
+#endif
|
||
+#ifndef HAVE_CURL_EASY_STRERROR
|
||
+# define curl_easy_strerror(dummy) "unknown error"
|
||
+#endif
|
||
+#ifndef HAVE_CURL_MULTI_STRERROR
|
||
+# define curl_multi_strerror(dummy) "unknown error"
|
||
+#endif
|
||
+
|
||
+#define PHP_MINIT_CALL(func) PHP_MINIT(func)(INIT_FUNC_ARGS_PASSTHRU)
|
||
+#define PHP_RINIT_CALL(func) PHP_RINIT(func)(INIT_FUNC_ARGS_PASSTHRU)
|
||
+#define PHP_MSHUTDOWN_CALL(func) PHP_MSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU)
|
||
+#define PHP_RSHUTDOWN_CALL(func) PHP_RSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU)
|
||
+
|
||
+#define Z_OBJ_DELREF(z) \
|
||
+ if (Z_OBJ_HT(z)->del_ref) { \
|
||
+ Z_OBJ_HT(z)->del_ref(&(z) TSRMLS_CC); \
|
||
+ }
|
||
+#define Z_OBJ_ADDREF(z) \
|
||
+ if (Z_OBJ_HT(z)->add_ref) { \
|
||
+ Z_OBJ_HT(z)->add_ref(&(z) TSRMLS_CC); \
|
||
+ }
|
||
+#define Z_OBJ_DELREF_P(z) \
|
||
+ if (Z_OBJ_HT_P(z)->del_ref) { \
|
||
+ Z_OBJ_HT_P(z)->del_ref((z) TSRMLS_CC); \
|
||
+ }
|
||
+#define Z_OBJ_ADDREF_P(z) \
|
||
+ if (Z_OBJ_HT_P(z)->add_ref) { \
|
||
+ Z_OBJ_HT_P(z)->add_ref((z) TSRMLS_CC); \
|
||
+ }
|
||
+#define Z_OBJ_DELREF_PP(z) \
|
||
+ if (Z_OBJ_HT_PP(z)->del_ref) { \
|
||
+ Z_OBJ_HT_PP(z)->del_ref(*(z) TSRMLS_CC); \
|
||
+ }
|
||
+#define Z_OBJ_ADDREF_PP(z) \
|
||
+ if (Z_OBJ_HT_PP(z)->add_ref) { \
|
||
+ Z_OBJ_HT_PP(z)->add_ref(*(z) TSRMLS_CC); \
|
||
+ }
|
||
+
|
||
+#endif /* PHP_HTTP_STD_DEFS_H */
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_url_api.h
|
||
@@ -0,0 +1,165 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_url_api.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_URL_API_H
|
||
+#define PHP_HTTP_URL_API_H
|
||
+
|
||
+#include "ext/standard/url.h"
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_url);
|
||
+
|
||
+#define http_absolute_url(u) _http_absolute_url_ex((u), HTTP_URL_REPLACE TSRMLS_CC)
|
||
+#define http_absolute_url_ex(u, f) _http_absolute_url_ex((u), (f) TSRMLS_CC)
|
||
+PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC);
|
||
+
|
||
+#define HTTP_URL_REPLACE 0x000
|
||
+#define HTTP_URL_JOIN_PATH 0x001
|
||
+#define HTTP_URL_JOIN_QUERY 0x002
|
||
+#define HTTP_URL_STRIP_USER 0x004
|
||
+#define HTTP_URL_STRIP_PASS 0x008
|
||
+#define HTTP_URL_STRIP_AUTH (HTTP_URL_STRIP_USER|HTTP_URL_STRIP_PASS)
|
||
+#define HTTP_URL_STRIP_PORT 0x020
|
||
+#define HTTP_URL_STRIP_PATH 0x040
|
||
+#define HTTP_URL_STRIP_QUERY 0x080
|
||
+#define HTTP_URL_STRIP_FRAGMENT 0x100
|
||
+#define HTTP_URL_STRIP_ALL ( \
|
||
+ HTTP_URL_STRIP_AUTH | \
|
||
+ HTTP_URL_STRIP_PORT | \
|
||
+ HTTP_URL_STRIP_PATH | \
|
||
+ HTTP_URL_STRIP_QUERY | \
|
||
+ HTTP_URL_STRIP_FRAGMENT \
|
||
+)
|
||
+#define HTTP_URL_FROM_ENV 0x1000
|
||
+
|
||
+#define http_build_url(f, o, n, p, s, l) _http_build_url((f), (o), (n), (p), (s), (l) TSRMLS_CC)
|
||
+PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_url *new_url, php_url **url_ptr, char **url_str, size_t *url_len TSRMLS_DC);
|
||
+
|
||
+#define http_urlencode_hash(h, q) _http_urlencode_hash_ex((h), 1, NULL, 0, (q), NULL TSRMLS_CC)
|
||
+#define http_urlencode_hash_ex(h, o, p, pl, q, ql) _http_urlencode_hash_ex((h), (o), (p), (pl), (q), (ql) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep, char *pre_encoded_data, size_t pre_encoded_len, char **encoded_data, size_t *encoded_len TSRMLS_DC);
|
||
+
|
||
+#define http_urlencode_hash_recursive(ht, s, as, al, pr, pl) _http_urlencode_hash_recursive((ht), (s), (as), (al), (pr), (pl) TSRMLS_CC)
|
||
+PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC);
|
||
+
|
||
+#define http_url_from_struct(u, ht) _http_url_from_struct((u), (ht) TSRMLS_CC)
|
||
+static inline php_url *_http_url_from_struct(php_url *url, HashTable *ht TSRMLS_DC)
|
||
+{
|
||
+ zval **e;
|
||
+
|
||
+ if (!url) {
|
||
+ url = ecalloc(1, sizeof(php_url));
|
||
+ }
|
||
+
|
||
+ if ((SUCCESS == zend_hash_find(ht, "scheme", sizeof("scheme"), (void *) &e))
|
||
+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
|
||
+ url->scheme = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
|
||
+ }
|
||
+ if ((SUCCESS == zend_hash_find(ht, "user", sizeof("user"), (void *) &e))
|
||
+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
|
||
+ url->user = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
|
||
+ }
|
||
+ if ((SUCCESS == zend_hash_find(ht, "pass", sizeof("pass"), (void *) &e))
|
||
+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
|
||
+ url->pass = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
|
||
+ }
|
||
+ if ((SUCCESS == zend_hash_find(ht, "host", sizeof("host"), (void *) &e))
|
||
+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
|
||
+ url->host = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
|
||
+ }
|
||
+ if ((SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &e))
|
||
+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
|
||
+ url->path = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
|
||
+ }
|
||
+ if ((SUCCESS == zend_hash_find(ht, "query", sizeof("query"), (void *) &e))
|
||
+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
|
||
+ url->query = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
|
||
+ }
|
||
+ if ((SUCCESS == zend_hash_find(ht, "fragment", sizeof("fragment"), (void *) &e))
|
||
+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
|
||
+ url->fragment = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
|
||
+ }
|
||
+ if (SUCCESS == zend_hash_find(ht, "port", sizeof("port"), (void *) &e)) {
|
||
+ if (Z_TYPE_PP(e) == IS_LONG) {
|
||
+ url->port = (unsigned short) Z_LVAL_PP(e);
|
||
+ } else {
|
||
+ zval *o = http_zsep(IS_LONG, *e);
|
||
+
|
||
+ url->port = (unsigned short) Z_LVAL_P(o);
|
||
+ zval_ptr_dtor(&o);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return url;
|
||
+}
|
||
+
|
||
+#define http_url_tostruct(u, strct) _http_url_tostruct((u), (strct) TSRMLS_CC)
|
||
+static inline HashTable *_http_url_tostruct(php_url *url, zval *strct TSRMLS_DC)
|
||
+{
|
||
+ zval arr;
|
||
+
|
||
+ if (strct) {
|
||
+ switch (Z_TYPE_P(strct)) {
|
||
+ default:
|
||
+ zval_dtor(strct);
|
||
+ array_init(strct);
|
||
+ case IS_ARRAY:
|
||
+ case IS_OBJECT:
|
||
+ INIT_ZARR(arr, HASH_OF(strct));
|
||
+ }
|
||
+ } else {
|
||
+ INIT_PZVAL(&arr);
|
||
+ array_init(&arr);
|
||
+ }
|
||
+
|
||
+ if (url) {
|
||
+ if (url->scheme) {
|
||
+ add_assoc_string(&arr, "scheme", url->scheme, 1);
|
||
+ }
|
||
+ if (url->user) {
|
||
+ add_assoc_string(&arr, "user", url->user, 1);
|
||
+ }
|
||
+ if (url->pass) {
|
||
+ add_assoc_string(&arr, "pass", url->pass, 1);
|
||
+ }
|
||
+ if (url->host) {
|
||
+ add_assoc_string(&arr, "host", url->host, 1);
|
||
+ }
|
||
+ if (url->port) {
|
||
+ add_assoc_long(&arr, "port", (long) url->port);
|
||
+ }
|
||
+ if (url->path) {
|
||
+ add_assoc_string(&arr, "path", url->path, 1);
|
||
+ }
|
||
+ if (url->query) {
|
||
+ add_assoc_string(&arr, "query", url->query, 1);
|
||
+ }
|
||
+ if (url->fragment) {
|
||
+ add_assoc_string(&arr, "fragment", url->fragment, 1);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return Z_ARRVAL(arr);
|
||
+}
|
||
+
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/php_http_util_object.h
|
||
@@ -0,0 +1,35 @@
|
||
+/*
|
||
+ +--------------------------------------------------------------------+
|
||
+ | PECL :: http |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Redistribution and use in source and binary forms, with or without |
|
||
+ | modification, are permitted provided that the conditions mentioned |
|
||
+ | in the accompanying LICENSE file are met. |
|
||
+ +--------------------------------------------------------------------+
|
||
+ | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
|
||
+ +--------------------------------------------------------------------+
|
||
+*/
|
||
+
|
||
+/* $Id: php_http_util_object.h 292841 2009-12-31 08:48:57Z mike $ */
|
||
+
|
||
+#ifndef PHP_HTTP_UTIL_OBJECT_H
|
||
+#define PHP_HTTP_UTIL_OBJECT_H
|
||
+#ifdef ZEND_ENGINE_2
|
||
+
|
||
+extern zend_class_entry *http_util_object_ce;
|
||
+extern zend_function_entry http_util_object_fe[];
|
||
+
|
||
+extern PHP_MINIT_FUNCTION(http_util_object);
|
||
+
|
||
+#endif
|
||
+#endif
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: noet sw=4 ts=4 fdm=marker
|
||
+ * vim<600: noet sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/phpstr/phpstr.c
|
||
@@ -0,0 +1,379 @@
|
||
+
|
||
+/* $Id: phpstr.c 211942 2006-04-24 17:17:09Z mike $ */
|
||
+
|
||
+#include "php.h"
|
||
+#include "phpstr.h"
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags)
|
||
+{
|
||
+ if (!buf) {
|
||
+ buf = pemalloc(sizeof(phpstr), flags & PHPSTR_INIT_PERSISTENT);
|
||
+ }
|
||
+
|
||
+ if (buf) {
|
||
+ buf->size = (chunk_size) ? chunk_size : PHPSTR_DEFAULT_SIZE;
|
||
+ buf->pmem = (flags & PHPSTR_INIT_PERSISTENT) ? 1 : 0;
|
||
+ buf->data = (flags & PHPSTR_INIT_PREALLOC) ? pemalloc(buf->size, buf->pmem) : NULL;
|
||
+ buf->free = (flags & PHPSTR_INIT_PREALLOC) ? buf->size : 0;
|
||
+ buf->used = 0;
|
||
+ }
|
||
+
|
||
+ return buf;
|
||
+}
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length)
|
||
+{
|
||
+ if ((buf = phpstr_init(buf))) {
|
||
+ if (PHPSTR_NOMEM == phpstr_append(buf, string, length)) {
|
||
+ pefree(buf, buf->pmem);
|
||
+ buf = NULL;
|
||
+ }
|
||
+ }
|
||
+ return buf;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error)
|
||
+{
|
||
+ char *ptr = NULL;
|
||
+#if 0
|
||
+ fprintf(stderr, "RESIZE: size=%lu, used=%lu, free=%lu\n", buf->size, buf->used, buf->free);
|
||
+#endif
|
||
+ if (buf->free < len) {
|
||
+ size_t size = override_size ? override_size : buf->size;
|
||
+
|
||
+ while ((size + buf->free) < len) {
|
||
+ size <<= 1;
|
||
+ }
|
||
+
|
||
+ if (allow_error) {
|
||
+ ptr = perealloc_recoverable(buf->data, buf->used + buf->free + size, buf->pmem);
|
||
+ } else {
|
||
+ ptr = perealloc(buf->data, buf->used + buf->free + size, buf->pmem);
|
||
+ }
|
||
+
|
||
+ if (ptr) {
|
||
+ buf->data = ptr;
|
||
+ } else {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+
|
||
+ buf->free += size;
|
||
+ return size;
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_shrink(phpstr *buf)
|
||
+{
|
||
+ /* avoid another realloc on fixation */
|
||
+ if (buf->free > 1) {
|
||
+ char *ptr = perealloc(buf->data, buf->used + 1, buf->pmem);
|
||
+
|
||
+ if (ptr) {
|
||
+ buf->data = ptr;
|
||
+ } else {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+ buf->free = 1;
|
||
+ }
|
||
+ return buf->used;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len)
|
||
+{
|
||
+ if (PHPSTR_NOMEM == phpstr_resize(buf, append_len)) {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+ memcpy(buf->data + buf->used, append, append_len);
|
||
+ buf->used += append_len;
|
||
+ buf->free -= append_len;
|
||
+ return append_len;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...)
|
||
+{
|
||
+ va_list argv;
|
||
+ char *append;
|
||
+ size_t append_len, alloc;
|
||
+
|
||
+ va_start(argv, format);
|
||
+ append_len = vspprintf(&append, 0, format, argv);
|
||
+ va_end(argv);
|
||
+
|
||
+ alloc = phpstr_append(buf, append, append_len);
|
||
+ efree(append);
|
||
+
|
||
+ if (PHPSTR_NOMEM == alloc) {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+ return append_len;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset)
|
||
+{
|
||
+ if (PHPSTR_NOMEM == phpstr_resize(buf, insert_len)) {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+ memmove(buf->data + offset + insert_len, buf->data + offset, insert_len);
|
||
+ memcpy(buf->data + offset, insert, insert_len);
|
||
+ buf->used += insert_len;
|
||
+ buf->free -= insert_len;
|
||
+ return insert_len;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...)
|
||
+{
|
||
+ va_list argv;
|
||
+ char *insert;
|
||
+ size_t insert_len, alloc;
|
||
+
|
||
+ va_start(argv, format);
|
||
+ insert_len = vspprintf(&insert, 0, format, argv);
|
||
+ va_end(argv);
|
||
+
|
||
+ alloc = phpstr_insert(buf, insert, insert_len, offset);
|
||
+ efree(insert);
|
||
+
|
||
+ if (PHPSTR_NOMEM == alloc) {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+ return insert_len;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len)
|
||
+{
|
||
+ if (PHPSTR_NOMEM == phpstr_resize(buf, prepend_len)) {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+ memmove(buf->data + prepend_len, buf->data, buf->used);
|
||
+ memcpy(buf->data, prepend, prepend_len);
|
||
+ buf->used += prepend_len;
|
||
+ buf->free -= prepend_len;
|
||
+ return prepend_len;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...)
|
||
+{
|
||
+ va_list argv;
|
||
+ char *prepend;
|
||
+ size_t prepend_len, alloc;
|
||
+
|
||
+ va_start(argv, format);
|
||
+ prepend_len = vspprintf(&prepend, 0, format, argv);
|
||
+ va_end(argv);
|
||
+
|
||
+ alloc = phpstr_prepend(buf, prepend, prepend_len);
|
||
+ efree(prepend);
|
||
+
|
||
+ if (PHPSTR_NOMEM == alloc) {
|
||
+ return PHPSTR_NOMEM;
|
||
+ }
|
||
+ return prepend_len;
|
||
+}
|
||
+
|
||
+PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len)
|
||
+{
|
||
+ char *copy = ecalloc(1, buf->used + 1);
|
||
+ memcpy(copy, buf->data, buf->used);
|
||
+ if (into) {
|
||
+ *into = copy;
|
||
+ }
|
||
+ if (len) {
|
||
+ *len = buf->used;
|
||
+ }
|
||
+ return copy;
|
||
+}
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_dup(const phpstr *buf)
|
||
+{
|
||
+ phpstr *dup = phpstr_clone(buf);
|
||
+ if (PHPSTR_NOMEM == phpstr_append(dup, buf->data, buf->used)) {
|
||
+ phpstr_free(&dup);
|
||
+ }
|
||
+ return dup;
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length)
|
||
+{
|
||
+ if (offset >= buf->used) {
|
||
+ return 0;
|
||
+ }
|
||
+ if (offset + length > buf->used) {
|
||
+ length = buf->used - offset;
|
||
+ }
|
||
+ memmove(buf->data + offset, buf->data + offset + length, buf->used - length);
|
||
+ buf->used -= length;
|
||
+ buf->free += length;
|
||
+ return length;
|
||
+}
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t length)
|
||
+{
|
||
+ if (offset >= buf->used) {
|
||
+ return NULL;
|
||
+ } else {
|
||
+ size_t need = 1 + ((length + offset) > buf->used ? (buf->used - offset) : (length - offset));
|
||
+ phpstr *sub = phpstr_init_ex(NULL, need, PHPSTR_INIT_PREALLOC | (buf->pmem ? PHPSTR_INIT_PERSISTENT:0));
|
||
+ if (sub) {
|
||
+ if (PHPSTR_NOMEM == phpstr_append(sub, buf->data + offset, need)) {
|
||
+ phpstr_free(&sub);
|
||
+ } else {
|
||
+ sub->size = buf->size;
|
||
+ }
|
||
+ }
|
||
+ return sub;
|
||
+ }
|
||
+}
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length)
|
||
+{
|
||
+ if (length < buf->used) {
|
||
+ return phpstr_sub(buf, buf->used - length, length);
|
||
+ } else {
|
||
+ return phpstr_sub(buf, 0, buf->used);
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv)
|
||
+{
|
||
+ unsigned i = 0;
|
||
+ buf = phpstr_init(buf);
|
||
+
|
||
+ if (buf) {
|
||
+ while (argc > i++) {
|
||
+ phpstr_free_t f = va_arg(argv, phpstr_free_t);
|
||
+ phpstr *current = va_arg(argv, phpstr *);
|
||
+ phpstr_append(buf, current->data, current->used);
|
||
+ FREE_PHPSTR(f, current);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ return buf;
|
||
+}
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...)
|
||
+{
|
||
+ va_list argv;
|
||
+ phpstr *ret;
|
||
+
|
||
+ va_start(argv, argc);
|
||
+ ret = phpstr_merge_va(buf, argc, argv);
|
||
+ va_end(argv);
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...)
|
||
+{
|
||
+ va_list argv;
|
||
+ phpstr *ret;
|
||
+
|
||
+ va_start(argv, argc);
|
||
+ ret = phpstr_merge_va(NULL, argc, argv);
|
||
+ va_end(argv);
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+PHPSTR_API phpstr *phpstr_fix(phpstr *buf)
|
||
+{
|
||
+ if (PHPSTR_NOMEM == phpstr_resize_ex(buf, 1, 1, 0)) {
|
||
+ return NULL;
|
||
+ }
|
||
+ buf->data[buf->used] = '\0';
|
||
+ return buf;
|
||
+}
|
||
+
|
||
+PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right)
|
||
+{
|
||
+ if (left->used > right->used) {
|
||
+ return -1;
|
||
+ } else if (right->used > left->used) {
|
||
+ return 1;
|
||
+ } else {
|
||
+ return memcmp(left->data, right->data, left->used);
|
||
+ }
|
||
+}
|
||
+
|
||
+PHPSTR_API void phpstr_reset(phpstr *buf)
|
||
+{
|
||
+ buf->free += buf->used;
|
||
+ buf->used = 0;
|
||
+}
|
||
+
|
||
+PHPSTR_API void phpstr_dtor(phpstr *buf)
|
||
+{
|
||
+ if (buf->data) {
|
||
+ pefree(buf->data, buf->pmem);
|
||
+ buf->data = NULL;
|
||
+ }
|
||
+ buf->used = 0;
|
||
+ buf->free = 0;
|
||
+}
|
||
+
|
||
+PHPSTR_API void phpstr_free(phpstr **buf)
|
||
+{
|
||
+ if (*buf) {
|
||
+ phpstr_dtor(*buf);
|
||
+ pefree(*buf, (*buf)->pmem);
|
||
+ *buf = NULL;
|
||
+ }
|
||
+}
|
||
+
|
||
+PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size)
|
||
+{
|
||
+ phpstr *storage;
|
||
+
|
||
+ *chunk = NULL;
|
||
+
|
||
+ if (!*s) {
|
||
+ *s = phpstr_init_ex(NULL, chunk_size << 1, chunk_size ? PHPSTR_INIT_PREALLOC : 0);
|
||
+ }
|
||
+ storage = *s;
|
||
+
|
||
+ if (data_len) {
|
||
+ phpstr_append(storage, data, data_len);
|
||
+ }
|
||
+
|
||
+ if (!chunk_size) {
|
||
+ phpstr_data(storage, chunk, &chunk_size);
|
||
+ phpstr_free(s);
|
||
+ return chunk_size;
|
||
+ }
|
||
+
|
||
+ if (storage->used >= (chunk_size = storage->size >> 1)) {
|
||
+ *chunk = estrndup(storage->data, chunk_size);
|
||
+ phpstr_cut(storage, 0, chunk_size);
|
||
+ return chunk_size;
|
||
+ }
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+PHPSTR_API void phpstr_chunked_output(phpstr **s, const char *data, size_t data_len, size_t chunk_len, phpstr_passthru_func passthru, void *opaque TSRMLS_DC)
|
||
+{
|
||
+ char *chunk = NULL;
|
||
+ size_t got = 0;
|
||
+
|
||
+ while ((got = phpstr_chunk_buffer(s, data, data_len, &chunk, chunk_len))) {
|
||
+ passthru(opaque, chunk, got TSRMLS_CC);
|
||
+ if (!chunk_len) {
|
||
+ /* we already got the last chunk,
|
||
+ and freed all resources */
|
||
+ break;
|
||
+ }
|
||
+ data = NULL;
|
||
+ data_len = 0;
|
||
+ STR_SET(chunk, NULL);
|
||
+ }
|
||
+ STR_FREE(chunk);
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: sw=4 ts=4 fdm=marker
|
||
+ * vim<600: sw=4 ts=4
|
||
+ */
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/phpstr/phpstr.h
|
||
@@ -0,0 +1,224 @@
|
||
+
|
||
+/* $Id: phpstr.h 229282 2007-02-07 15:31:50Z mike $ */
|
||
+
|
||
+#ifndef _PHPSTR_H_
|
||
+#define _PHPSTR_H_
|
||
+
|
||
+#ifndef PHPSTR_DEFAULT_SIZE
|
||
+# define PHPSTR_DEFAULT_SIZE 256
|
||
+#endif
|
||
+
|
||
+#define PHPSTR_NOMEM ((size_t) -1)
|
||
+
|
||
+#ifndef STR_FREE
|
||
+# define STR_FREE(STR) \
|
||
+ { \
|
||
+ if (STR) { \
|
||
+ efree(STR); \
|
||
+ } \
|
||
+ }
|
||
+#endif
|
||
+#ifndef STR_SET
|
||
+# define STR_SET(STR, SET) \
|
||
+ { \
|
||
+ STR_FREE(STR); \
|
||
+ STR = SET; \
|
||
+ }
|
||
+#endif
|
||
+#ifndef TSRMLS_D
|
||
+# define TSRMLS_D
|
||
+# define TSRMLS_DC
|
||
+# define TSRMLS_CC
|
||
+# define TSRMLS_C
|
||
+#endif
|
||
+#ifdef PHP_ATTRIBUTE_FORMAT
|
||
+# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b) PHP_ATTRIBUTE_FORMAT(f, a, b)
|
||
+#else
|
||
+# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b)
|
||
+#endif
|
||
+#ifndef pemalloc
|
||
+# define pemalloc(s,p) malloc(s)
|
||
+# define pefree(x,p) free(x)
|
||
+# define perealloc(x,s,p) realloc(x,s)
|
||
+# define perealloc_recoverable perealloc
|
||
+# define ecalloc calloc
|
||
+static inline void *estrndup(void *p, size_t s)
|
||
+{
|
||
+ char *r = (char *) malloc(s+1);
|
||
+ if (r) memcpy((void *) r, p, s), r[s] = '\0';
|
||
+ return (void *) r;
|
||
+}
|
||
+#endif
|
||
+
|
||
+#if defined(PHP_WIN32)
|
||
+# if defined(PHPSTR_EXPORTS)
|
||
+# define PHPSTR_API __declspec(dllexport)
|
||
+# elif defined(COMPILE_DL_PHPSTR)
|
||
+# define PHPSTR_API __declspec(dllimport)
|
||
+# else
|
||
+# define PHPSTR_API
|
||
+# endif
|
||
+#else
|
||
+# define PHPSTR_API
|
||
+#endif
|
||
+
|
||
+#define PHPSTR(p) ((phpstr *) (p))
|
||
+#define PHPSTR_VAL(p) (PHPSTR(p))->data
|
||
+#define PHPSTR_LEN(p) (PHPSTR(p))->used
|
||
+
|
||
+#define FREE_PHPSTR_PTR(STR) pefree(STR, STR->pmem)
|
||
+#define FREE_PHPSTR_VAL(STR) phpstr_dtor(STR)
|
||
+#define FREE_PHPSTR_ALL(STR) phpstr_free(&(STR))
|
||
+#define FREE_PHPSTR(free, STR) \
|
||
+ switch (free) \
|
||
+ { \
|
||
+ case PHPSTR_FREE_NOT: break; \
|
||
+ case PHPSTR_FREE_PTR: pefree(STR, STR->pmem); break; \
|
||
+ case PHPSTR_FREE_VAL: phpstr_dtor(STR); break; \
|
||
+ case PHPSTR_FREE_ALL: \
|
||
+ { \
|
||
+ phpstr *PTR = (STR); \
|
||
+ phpstr_free(&PTR); \
|
||
+ } \
|
||
+ break; \
|
||
+ default: break; \
|
||
+ }
|
||
+
|
||
+#define RETURN_PHPSTR_PTR(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_PTR, 0)
|
||
+#define RETURN_PHPSTR_VAL(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 0)
|
||
+#define RETURN_PHPSTR_DUP(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
|
||
+#define RETVAL_PHPSTR_PTR(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_PTR, 0)
|
||
+#define RETVAL_PHPSTR_VAL(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 0)
|
||
+#define RETVAL_PHPSTR_DUP(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
|
||
+/* RETURN_PHPSTR(buf, PHPSTR_FREE_PTR, 0) */
|
||
+#define RETURN_PHPSTR(STR, free, dup) \
|
||
+ RETVAL_PHPSTR((STR), (free), (dup)); \
|
||
+ return;
|
||
+
|
||
+#define RETVAL_PHPSTR(STR, free, dup) \
|
||
+ phpstr_fix(STR); \
|
||
+ RETVAL_STRINGL((STR)->data, (STR)->used, (dup)); \
|
||
+ FREE_PHPSTR((free), (STR));
|
||
+
|
||
+typedef struct _phpstr_t {
|
||
+ char *data;
|
||
+ size_t used;
|
||
+ size_t free;
|
||
+ size_t size;
|
||
+ unsigned pmem:1;
|
||
+ unsigned reserved:31;
|
||
+} phpstr;
|
||
+
|
||
+typedef enum _phpstr_free_t {
|
||
+ PHPSTR_FREE_NOT = 0,
|
||
+ PHPSTR_FREE_PTR, /* pefree() */
|
||
+ PHPSTR_FREE_VAL, /* phpstr_dtor() */
|
||
+ PHPSTR_FREE_ALL /* phpstr_free() */
|
||
+} phpstr_free_t;
|
||
+
|
||
+#define PHPSTR_ALL_FREE(STR) PHPSTR_FREE_ALL,(STR)
|
||
+#define PHPSTR_PTR_FREE(STR) PHPSTR_FREE_PTR,(STR)
|
||
+#define PHPSTR_VAL_FREE(STR) PHPSTR_FREE_VAL,(STR)
|
||
+#define PHPSTR_NOT_FREE(STR) PHPSTR_FREE_NOT,(STR)
|
||
+
|
||
+#define PHPSTR_INIT_PREALLOC 0x01
|
||
+#define PHPSTR_INIT_PERSISTENT 0x02
|
||
+
|
||
+/* create a new phpstr */
|
||
+#define phpstr_new() phpstr_init(NULL)
|
||
+#define phpstr_init(b) phpstr_init_ex(b, PHPSTR_DEFAULT_SIZE, 0)
|
||
+#define phpstr_clone(phpstr_pointer) phpstr_init_ex(NULL, (phpstr_pointer)->size, (phpstr_pointer)->pmem ? PHPSTR_INIT_PERSISTENT:0)
|
||
+PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags);
|
||
+
|
||
+/* create a phpstr from a zval or c-string */
|
||
+#define phpstr_from_zval(z) phpstr_from_string(Z_STRVAL(z), Z_STRLEN(z))
|
||
+#define phpstr_from_zval_ex(b, z) phpstr_from_string_ex(b, Z_STRVAL(z), Z_STRLEN(z))
|
||
+#define phpstr_from_string(s, l) phpstr_from_string_ex(NULL, (s), (l))
|
||
+PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length);
|
||
+
|
||
+/* usually only called from within the internal functions */
|
||
+#define phpstr_resize(b, s) phpstr_resize_ex((b), (s), 0, 0)
|
||
+PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error);
|
||
+
|
||
+/* shrink memory chunk to actually used size (+1) */
|
||
+PHPSTR_API size_t phpstr_shrink(phpstr *buf);
|
||
+
|
||
+/* append data to the phpstr */
|
||
+#define phpstr_appends(b, a) phpstr_append((b), (a), sizeof(a)-1)
|
||
+#define phpstr_appendl(b, a) phpstr_append((b), (a), strlen(a))
|
||
+PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len);
|
||
+PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||
+
|
||
+/* insert data at a specific position of the phpstr */
|
||
+#define phpstr_inserts(b, i, o) phpstr_insert((b), (i), sizeof(i)-1, (o))
|
||
+#define phpstr_insertl(b, i, o) phpstr_insert((b), (i), strlen(i), (o))
|
||
+PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset);
|
||
+PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 3, 4);
|
||
+
|
||
+/* prepend data */
|
||
+#define phpstr_prepends(b, p) phpstr_prepend((b), (p), sizeof(p)-1)
|
||
+#define phpstr_prependl(b, p) phpstr_prepend((b), (p), strlen(p))
|
||
+PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len);
|
||
+PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||
+
|
||
+/* get a zero-terminated string */
|
||
+PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len);
|
||
+
|
||
+/* get a part of the phpstr */
|
||
+#define phpstr_mid(b, o, l) phpstr_sub((b), (o), (l))
|
||
+#define phpstr_left(b, l) phpstr_sub((b), 0, (l))
|
||
+PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length);
|
||
+PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t len);
|
||
+
|
||
+/* remove a substring */
|
||
+PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length);
|
||
+
|
||
+/* get a complete phpstr duplicate */
|
||
+PHPSTR_API phpstr *phpstr_dup(const phpstr *buf);
|
||
+
|
||
+/* merge several phpstr objects
|
||
+ use like:
|
||
+
|
||
+ phpstr *final = phpstr_merge(3,
|
||
+ PHPSTR_NOT_FREE(&keep),
|
||
+ PHPSTR_ALL_FREE(middle_ptr),
|
||
+ PHPSTR_VAL_FREE(&local);
|
||
+*/
|
||
+PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...);
|
||
+PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...);
|
||
+PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv);
|
||
+
|
||
+/* sets a trailing NUL byte */
|
||
+PHPSTR_API phpstr *phpstr_fix(phpstr *buf);
|
||
+
|
||
+/* memcmp for phpstr objects */
|
||
+PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right);
|
||
+
|
||
+/* reset phpstr object */
|
||
+PHPSTR_API void phpstr_reset(phpstr *buf);
|
||
+
|
||
+/* free a phpstr objects contents */
|
||
+PHPSTR_API void phpstr_dtor(phpstr *buf);
|
||
+
|
||
+/* free a phpstr object completely */
|
||
+PHPSTR_API void phpstr_free(phpstr **buf);
|
||
+
|
||
+/* stores data in a phpstr until it reaches chunk_size */
|
||
+PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size);
|
||
+
|
||
+typedef void (*phpstr_passthru_func)(void *opaque, const char *, size_t TSRMLS_DC);
|
||
+
|
||
+/* wrapper around phpstr_chunk_buffer, which passes available chunks to passthru() */
|
||
+PHPSTR_API void phpstr_chunked_output(phpstr **s, const char *data, size_t data_len, size_t chunk_size, phpstr_passthru_func passthru, void *opaque TSRMLS_DC);
|
||
+
|
||
+#endif
|
||
+
|
||
+
|
||
+/*
|
||
+ * Local variables:
|
||
+ * tab-width: 4
|
||
+ * c-basic-offset: 4
|
||
+ * End:
|
||
+ * vim600: sw=4 ts=4 fdm=marker
|
||
+ * vim<600: sw=4 ts=4
|
||
+ */
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_001.phpt
|
||
@@ -0,0 +1,70 @@
|
||
+--TEST--
|
||
+HttpMessage
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$m = new HttpMessage(
|
||
+ "HTTP/1.1 301\r\n".
|
||
+ "Location: /anywhere\r\n".
|
||
+ "HTTP/1.1 302\r\n".
|
||
+ "Location: /somewhere\r\n".
|
||
+ "HTTP/1.1 206 Partial content\r\n".
|
||
+ "Content-Range: bytes=2-3\r\n".
|
||
+ "Transfer-Encoding: chunked\r\n".
|
||
+ "\r\n".
|
||
+ "01\r\n".
|
||
+ "X\r\n".
|
||
+ "00"
|
||
+);
|
||
+
|
||
+var_dump($m->getResponseStatus());
|
||
+
|
||
+$x = $m->getParentMessage();
|
||
+$x = $m->getParentMessage();
|
||
+$x = $m->getParentMessage();
|
||
+
|
||
+var_dump($m->getBody());
|
||
+var_dump(HttpMessage::fromString($m->toString(true))->toString(true));
|
||
+try {
|
||
+ do {
|
||
+ var_dump($m->toString());
|
||
+ } while ($m = $m->getParentMessage());
|
||
+} catch (HttpException $ex) {
|
||
+}
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(15) "Partial content"
|
||
+string(1) "X"
|
||
+string(190) "HTTP/1.1 301
|
||
+Location: /anywhere
|
||
+HTTP/1.1 302
|
||
+Location: /somewhere
|
||
+HTTP/1.1 206 Partial content
|
||
+Content-Range: bytes=2-3
|
||
+X-Original-Transfer-Encoding: chunked
|
||
+Content-Length: 1
|
||
+
|
||
+X
|
||
+"
|
||
+string(119) "HTTP/1.1 206 Partial content
|
||
+Content-Range: bytes=2-3
|
||
+X-Original-Transfer-Encoding: chunked
|
||
+Content-Length: 1
|
||
+
|
||
+X
|
||
+"
|
||
+string(36) "HTTP/1.1 302
|
||
+Location: /somewhere
|
||
+"
|
||
+string(35) "HTTP/1.1 301
|
||
+Location: /anywhere
|
||
+"
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_002.phpt
|
||
@@ -0,0 +1,65 @@
|
||
+--TEST--
|
||
+HttpMessage properties
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpMessage');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+class Message extends HttpMessage
|
||
+{
|
||
+ var $var_property = 'var';
|
||
+ public $public_property = 'public';
|
||
+ protected $protected_property = 'protected';
|
||
+ private $private_property = 'private';
|
||
+
|
||
+ public function test()
|
||
+ {
|
||
+ var_dump($this->var_property);
|
||
+ var_dump($this->public_property);
|
||
+ var_dump($this->protected_property);
|
||
+ var_dump($this->private_property);
|
||
+ var_dump($this->non_ex_property);
|
||
+ $this->var_property.='_property';
|
||
+ $this->public_property.='_property';
|
||
+ $this->protected_property.='_property';
|
||
+ $this->private_property.='_property';
|
||
+ $this->non_ex_property = 'non_ex';
|
||
+ var_dump($this->var_property);
|
||
+ var_dump($this->public_property);
|
||
+ var_dump($this->protected_property);
|
||
+ var_dump($this->private_property);
|
||
+ var_dump($this->non_ex_property);
|
||
+
|
||
+ print_r($this->headers);
|
||
+ $this->headers['Foo'] = 'Bar';
|
||
+ }
|
||
+}
|
||
+
|
||
+error_reporting(E_ALL|E_STRICT);
|
||
+
|
||
+echo "-TEST\n";
|
||
+$m = new Message;
|
||
+$m->test();
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(3) "var"
|
||
+string(6) "public"
|
||
+string(9) "protected"
|
||
+string(7) "private"
|
||
+
|
||
+Notice: Undefined property: Message::$non_ex_property in %s
|
||
+NULL
|
||
+string(12) "var_property"
|
||
+string(15) "public_property"
|
||
+string(18) "protected_property"
|
||
+string(16) "private_property"
|
||
+string(6) "non_ex"
|
||
+Array
|
||
+(
|
||
+)
|
||
+%aFatal error%sCannot access HttpMessage properties by reference or array key/index in%s
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_003.phpt
|
||
@@ -0,0 +1,70 @@
|
||
+--TEST--
|
||
+HttpMessage implements Serializable, Countable
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$m = new HttpMessage(
|
||
+ "HTTP/1.1 301\r\n".
|
||
+ "Location: /anywhere\r\n".
|
||
+ "HTTP/1.1 302\r\n".
|
||
+ "Location: /somewhere\r\n".
|
||
+ "HTTP/1.1 200\r\n".
|
||
+ "Transfer-Encoding: chunked\r\n".
|
||
+ "\r\n".
|
||
+ "01\r\n".
|
||
+ "X\r\n".
|
||
+ "00"
|
||
+);
|
||
+
|
||
+var_dump($m->count());
|
||
+var_dump($m->serialize());
|
||
+$m->unserialize("HTTP/1.1 200 Ok\r\nServer: Funky/1.0");
|
||
+var_dump($m);
|
||
+var_dump($m->count());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+int(3)
|
||
+string(148) "HTTP/1.1 301
|
||
+Location: /anywhere
|
||
+HTTP/1.1 302
|
||
+Location: /somewhere
|
||
+HTTP/1.1 200
|
||
+X-Original-Transfer-Encoding: chunked
|
||
+Content-Length: 1
|
||
+
|
||
+X
|
||
+"
|
||
+object(HttpMessage)#%d (%d) {
|
||
+ ["type%s]=>
|
||
+ int(2)
|
||
+ ["body%s]=>
|
||
+ string(0) ""
|
||
+ ["requestMethod%s]=>
|
||
+ string(0) ""
|
||
+ ["requestUrl%s]=>
|
||
+ string(0) ""
|
||
+ ["responseStatus%s]=>
|
||
+ string(2) "Ok"
|
||
+ ["responseCode%s]=>
|
||
+ int(200)
|
||
+ ["httpVersion%s]=>
|
||
+ float(1.1)
|
||
+ ["headers%s]=>
|
||
+ array(1) {
|
||
+ ["Server"]=>
|
||
+ string(9) "Funky/1.0"
|
||
+ }
|
||
+ ["parentMessage%s]=>
|
||
+ NULL
|
||
+}
|
||
+int(1)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_004.phpt
|
||
@@ -0,0 +1,36 @@
|
||
+--TEST--
|
||
+HttpMessage::detach()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$m = new HttpMessage("
|
||
+GET / HTTP/1.1
|
||
+Host: example.com
|
||
+Accept: */*
|
||
+Connection: close
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/1.0
|
||
+Content-Type: text/plain
|
||
+Content-Length: 3
|
||
+
|
||
+Hi!"
|
||
+);
|
||
+
|
||
+$d = $m->detach();
|
||
+$d->addHeaders(array('Server'=>'Funky/2.0'));
|
||
+var_dump($d->getHeaders() == $m->getHeaders());
|
||
+var_dump($d->getBody());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(false)
|
||
+string(3) "Hi!"
|
||
+Done
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_005.phpt
|
||
@@ -0,0 +1,86 @@
|
||
+--TEST--
|
||
+HttpMessage::prepend()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$m1 = new HttpMessage("
|
||
+GET / HTTP/1.1
|
||
+Host: example.com
|
||
+Accept: */*
|
||
+Connection: close
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/1.0
|
||
+Content-Type: text/plain
|
||
+Content-Length: 3
|
||
+
|
||
+Hi!"
|
||
+);
|
||
+
|
||
+$m2 = new HttpMessage("
|
||
+GET http://example.com/ HTTP/1.0
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/2.0
|
||
+Content-Type: text/html
|
||
+Content-Length: 9
|
||
+
|
||
+Hi there!"
|
||
+);
|
||
+
|
||
+$m1->prepend($m2);
|
||
+$m2 = NULL;
|
||
+echo $m1->toString(true);
|
||
+
|
||
+$m1->prepend($m1->detach(), false);
|
||
+echo $m1->toString(true);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+GET http://example.com/ HTTP/1.0
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/2.0
|
||
+Content-Type: text/html
|
||
+Content-Length: 9
|
||
+
|
||
+Hi there!
|
||
+GET / HTTP/1.1
|
||
+Host: example.com
|
||
+Accept: */*
|
||
+Connection: close
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/1.0
|
||
+Content-Type: text/plain
|
||
+Content-Length: 3
|
||
+
|
||
+Hi!
|
||
+GET http://example.com/ HTTP/1.0
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/2.0
|
||
+Content-Type: text/html
|
||
+Content-Length: 9
|
||
+
|
||
+Hi there!
|
||
+GET / HTTP/1.1
|
||
+Host: example.com
|
||
+Accept: */*
|
||
+Connection: close
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/1.0
|
||
+Content-Type: text/plain
|
||
+Content-Length: 3
|
||
+
|
||
+Hi!
|
||
+HTTP/1.1 200 ok
|
||
+Server: Funky/1.0
|
||
+Content-Type: text/plain
|
||
+Content-Length: 3
|
||
+
|
||
+Hi!
|
||
+Done
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_006.phpt
|
||
@@ -0,0 +1,35 @@
|
||
+--TEST--
|
||
+HttpMessage iterator
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$m = new HttpMessage("
|
||
+GET / HTTP/1.1
|
||
+HTTP/1.1 200 OK
|
||
+GET /foo HTTP/1.1
|
||
+HTTP/1.1 304 Not Modified
|
||
+");
|
||
+
|
||
+foreach ($m as $msg) {
|
||
+ echo "==\n", $msg;
|
||
+}
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+==
|
||
+HTTP/1.1 304 Not Modified
|
||
+==
|
||
+GET /foo HTTP/1.1
|
||
+==
|
||
+HTTP/1.1 200 OK
|
||
+==
|
||
+GET / HTTP/1.1
|
||
+Done
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_007.phpt
|
||
@@ -0,0 +1,46 @@
|
||
+--TEST--
|
||
+HttpMessage::reverse()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$s = "GET /first HTTP/1.1\nHTTP/1.1 200 Ok-first\nGET /second HTTP/1.1\nHTTP/1.1 200 Ok-second\nGET /third HTTP/1.1\nHTTP/1.1 200 Ok-third\n";
|
||
+echo HttpMessage::fromString($s)->toString(true);
|
||
+echo "===\n";
|
||
+echo HttpMessage::fromString($s)->reverse()->toString(true);
|
||
+
|
||
+$m = new HttpMessage($s);
|
||
+$r = $m->reverse();
|
||
+unset($m);
|
||
+var_dump($r->count());
|
||
+echo $r->toString(true);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+GET /first HTTP/1.1
|
||
+HTTP/1.1 200 Ok-first
|
||
+GET /second HTTP/1.1
|
||
+HTTP/1.1 200 Ok-second
|
||
+GET /third HTTP/1.1
|
||
+HTTP/1.1 200 Ok-third
|
||
+===
|
||
+HTTP/1.1 200 Ok-third
|
||
+GET /third HTTP/1.1
|
||
+HTTP/1.1 200 Ok-second
|
||
+GET /second HTTP/1.1
|
||
+HTTP/1.1 200 Ok-first
|
||
+GET /first HTTP/1.1
|
||
+int(6)
|
||
+HTTP/1.1 200 Ok-third
|
||
+GET /third HTTP/1.1
|
||
+HTTP/1.1 200 Ok-second
|
||
+GET /second HTTP/1.1
|
||
+HTTP/1.1 200 Ok-first
|
||
+GET /first HTTP/1.1
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_008.phpt
|
||
@@ -0,0 +1,41 @@
|
||
+--TEST--
|
||
+HttpMessage::toMessageTypeObject()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$b = HttpRequest::encodeBody(array("a"=>"b",1=>2),null);
|
||
+
|
||
+$m = new HttpMessage;
|
||
+$m->setType(HttpMessage::TYPE_REQUEST);
|
||
+$m->setRequestMethod('POST');
|
||
+$m->setRequestUrl("http://www.example.com");
|
||
+$m->setHttpVersion('1.1');
|
||
+$m->addHeaders(
|
||
+ array(
|
||
+ "Content-Type" => "application/x-www-form-urlencoded",
|
||
+ "Host" => "www.example.com",
|
||
+ "Content-Length"=> strlen($b),
|
||
+ )
|
||
+);
|
||
+$m->setBody($b);
|
||
+$r = $m->toMessageTypeObject();
|
||
+echo $m,"\n";
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+POST http://www.example.com HTTP/1.1
|
||
+Content-Type: application/x-www-form-urlencoded
|
||
+Host: www.example.com
|
||
+Content-Length: 7
|
||
+
|
||
+a=b&1=2
|
||
+
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpMessage_009_bug16700.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+Bug #16700 - child classes of HttpMessage cannot not have array properties
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+class ChildMessage extends HttpMessage {
|
||
+ public $properties = array();
|
||
+}
|
||
+
|
||
+$child = new ChildMessage;
|
||
+$child->properties['foo'] = 'bar';
|
||
+echo $child->properties['foo'], "\n";
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bar
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpQueryString_001.phpt
|
||
@@ -0,0 +1,116 @@
|
||
+--TEST--
|
||
+HttpQueryString global
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$_GET = array('a'=>'b','c'=>'3.4','r'=>array(1,2,3));
|
||
+$_SERVER['QUERY_STRING'] = 'a=b&c=3.4&r[0]=1&r[1]=2&r[2]=3';
|
||
+
|
||
+var_dump(HttpQueryString::singleton()->get());
|
||
+var_dump(HttpQueryString::singleton()->get('n'));
|
||
+var_dump(HttpQueryString::singleton()->get('a'));
|
||
+var_dump(HttpQueryString::singleton()->get('a', "i", 0, true));
|
||
+var_dump(HttpQueryString::singleton()->get('a', "string", 'hi!'));
|
||
+var_dump(HttpQueryString::singleton()->get('c'));
|
||
+var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_INT));
|
||
+var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_FLOAT));
|
||
+var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_BOOL));
|
||
+var_dump(HttpQueryString::singleton()->get('r'));
|
||
+var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_ARRAY));
|
||
+var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_OBJECT));
|
||
+
|
||
+HttpQueryString::singleton()->set(new HttpQueryString(false, 'z[0]=2'));
|
||
+
|
||
+HttpQueryString::singleton()->set(array('a'=>'b', 'c'=> "3.4"));
|
||
+HttpQueryString::singleton()->set(array('a' => NULL));
|
||
+
|
||
+var_dump(HttpQueryString::singleton());
|
||
+var_dump($_GET);
|
||
+var_dump($_SERVER['QUERY_STRING']);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3"
|
||
+NULL
|
||
+string(1) "b"
|
||
+int(0)
|
||
+string(3) "hi!"
|
||
+string(3) "3.4"
|
||
+int(3)
|
||
+float(3.4)
|
||
+bool(true)
|
||
+array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+}
|
||
+array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+}
|
||
+object(stdClass)#%d (%d) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+}
|
||
+object(HttpQueryString)#1 (2) {
|
||
+ ["queryArray%s]=>
|
||
+ &array(3) {
|
||
+ ["c"]=>
|
||
+ string(3) "3.4"
|
||
+ ["r"]=>
|
||
+ array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+ }
|
||
+ ["z"]=>
|
||
+ array(1) {
|
||
+ [0]=>
|
||
+ string(1) "2"
|
||
+ }
|
||
+ }
|
||
+ ["queryString%s]=>
|
||
+ &string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
|
||
+}
|
||
+array(3) {
|
||
+ ["c"]=>
|
||
+ string(3) "3.4"
|
||
+ ["r"]=>
|
||
+ array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+ }
|
||
+ ["z"]=>
|
||
+ array(1) {
|
||
+ [0]=>
|
||
+ string(1) "2"
|
||
+ }
|
||
+}
|
||
+string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
|
||
+Done
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpQueryString_002.phpt
|
||
@@ -0,0 +1,108 @@
|
||
+--TEST--
|
||
+HttpQueryString local
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$q = new HttpQueryString(false, $array = array('a'=>'b','c'=>'3.4','r'=>array(1,2,3)));
|
||
+var_dump($q->get());
|
||
+var_dump($q->get('n'));
|
||
+var_dump($q->get('a'));
|
||
+var_dump($q->get('a', "i", 0, true));
|
||
+var_dump($q->get('a', "string", 'hi!'));
|
||
+var_dump($q->get('c'));
|
||
+var_dump($q->get('c', HttpQueryString::TYPE_INT));
|
||
+var_dump($q->get('c', HttpQueryString::TYPE_FLOAT));
|
||
+var_dump($q->get('c', HttpQueryString::TYPE_BOOL));
|
||
+var_dump($q->get('r'));
|
||
+var_dump($q->get('r', HttpQueryString::TYPE_ARRAY));
|
||
+var_dump($q->get('r', HttpQueryString::TYPE_OBJECT));
|
||
+
|
||
+$q->set('z[0]=2');
|
||
+$q->set(array('a'=>'b', 'c'=> "3.4"));
|
||
+$q->set(array('a' => NULL));
|
||
+
|
||
+var_dump($q);
|
||
+var_dump($array);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3"
|
||
+NULL
|
||
+string(1) "b"
|
||
+int(0)
|
||
+string(3) "hi!"
|
||
+string(3) "3.4"
|
||
+int(3)
|
||
+float(3.4)
|
||
+bool(true)
|
||
+array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+}
|
||
+array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+}
|
||
+object(stdClass)#%d (%d) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+}
|
||
+object(HttpQueryString)#1 (2) {
|
||
+ ["queryArray%s]=>
|
||
+ array(3) {
|
||
+ ["c"]=>
|
||
+ string(3) "3.4"
|
||
+ ["r"]=>
|
||
+ array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+ }
|
||
+ ["z"]=>
|
||
+ array(1) {
|
||
+ [0]=>
|
||
+ string(1) "2"
|
||
+ }
|
||
+ }
|
||
+ ["queryString%s]=>
|
||
+ string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
|
||
+}
|
||
+array(3) {
|
||
+ ["a"]=>
|
||
+ string(1) "b"
|
||
+ ["c"]=>
|
||
+ string(3) "3.4"
|
||
+ ["r"]=>
|
||
+ array(3) {
|
||
+ [0]=>
|
||
+ int(1)
|
||
+ [1]=>
|
||
+ int(2)
|
||
+ [2]=>
|
||
+ int(3)
|
||
+ }
|
||
+}
|
||
+Done
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpQueryString_003.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+HttpQueryString xlate
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkext('iconv');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$qs = new HttpQueryString(false, "<22>[0]=<3D>&<26>[a]=<3D>");
|
||
+var_dump($qs->get());
|
||
+$qs->xlate("latin1", "utf8");
|
||
+var_dump($qs->get());
|
||
+$qs->xlate("utf8", "latin1");
|
||
+var_dump($qs->get());
|
||
+echo "Done\n";
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF"
|
||
+string(41) "%C3%A4%5B0%5D=%C3%BC&%C3%B6%5Ba%5D=%C3%9F"
|
||
+string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF"
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpQueryString_004.phpt
|
||
@@ -0,0 +1,54 @@
|
||
+--TEST--
|
||
+HttpQueryString w/ objects
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+class test_props {
|
||
+ public $bar;
|
||
+ public $baz;
|
||
+ protected $dont_show;
|
||
+ private $dont_show2;
|
||
+ function __construct() {
|
||
+ $this->bar = (object) array("baz"=>1);
|
||
+ $this->dont_show = 'xxx';
|
||
+ $this->dont_show2 = 'zzz';
|
||
+ }
|
||
+}
|
||
+$foo = new test_props;
|
||
+var_dump($q = new HttpQueryString(false, $foo));
|
||
+$foo->bar->baz = 0;
|
||
+var_dump($q->mod($foo));
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+object(HttpQueryString)#3 (2) {
|
||
+ ["queryArray%s]=>
|
||
+ array(1) {
|
||
+ ["bar"]=>
|
||
+ array(1) {
|
||
+ ["baz"]=>
|
||
+ int(1)
|
||
+ }
|
||
+ }
|
||
+ ["queryString%s]=>
|
||
+ string(14) "bar%5Bbaz%5D=1"
|
||
+}
|
||
+object(HttpQueryString)#4 (2) {
|
||
+ ["queryArray%s]=>
|
||
+ array(1) {
|
||
+ ["bar"]=>
|
||
+ array(1) {
|
||
+ ["baz"]=>
|
||
+ int(0)
|
||
+ }
|
||
+ }
|
||
+ ["queryString%s]=>
|
||
+ string(14) "bar%5Bbaz%5D=0"
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestDataShare_001.phpt
|
||
@@ -0,0 +1,38 @@
|
||
+--TEST--
|
||
+HttpRequestDataShare
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include "skip.inc";
|
||
+checkurl("www.google.com");
|
||
+checkcls("HttpRequestDataShare");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$s = new HttpRequestDataShare;
|
||
+$s->dns = true;
|
||
+$s->cookie = true;
|
||
+
|
||
+$r1 = new HttpRequest("http://www.google.com/");
|
||
+$r2 = new HttpRequest("http://www.google.com/");
|
||
+
|
||
+$r1->enableCookies();
|
||
+$r2->enableCookies();
|
||
+
|
||
+$s->attach($r1);
|
||
+$s->attach($r2);
|
||
+
|
||
+$r1->send();
|
||
+$r2->send();
|
||
+
|
||
+$s->reset();
|
||
+
|
||
+var_dump(current($r1->getResponseCookies())->cookies["PREF"] === HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(true)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestDataShare_002.phpt
|
||
@@ -0,0 +1,52 @@
|
||
+--TEST--
|
||
+HttpRequestDataShare global
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include "skip.inc";
|
||
+checkurl("www.google.com");
|
||
+checkcls("HttpRequestDataShare");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$s = HttpRequestDataShare::singleton(true);
|
||
+$s->cookie = true;
|
||
+var_dump($s);
|
||
+
|
||
+$r1 = new HttpRequest("http://www.google.com/");
|
||
+$r2 = new HttpRequest("http://www.google.com/");
|
||
+
|
||
+$r1->enableCookies();
|
||
+$r2->enableCookies();
|
||
+
|
||
+$s->attach($r1);
|
||
+$s->attach($r2);
|
||
+
|
||
+$r1->send();
|
||
+$r2->send();
|
||
+
|
||
+$s->reset();
|
||
+
|
||
+if (current($r1->getResponseCookies())->cookies["PREF"] !== HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]) {
|
||
+ var_dump(
|
||
+ current($r1->getResponseCookies())->cookies["PREF"],
|
||
+ HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]
|
||
+ );
|
||
+}
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+object(HttpRequestDataShare)#1 (4) {
|
||
+ ["cookie"]=>
|
||
+ bool(true)
|
||
+ ["dns"]=>
|
||
+ bool(true)
|
||
+ ["ssl"]=>
|
||
+ bool(false)
|
||
+ ["connect"]=>
|
||
+ bool(false)
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestPool_001.phpt
|
||
@@ -0,0 +1,51 @@
|
||
+--TEST--
|
||
+HttpRequestPool
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpRequestPool');
|
||
+checkurl('www.php.net');
|
||
+checkurl('dev.iworks.at');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$post = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
|
||
+$post->addPostFields(array('a'=>1,'b'=>2)) ;
|
||
+
|
||
+$pool = new HttpRequestPool(
|
||
+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
|
||
+ $post
|
||
+);
|
||
+
|
||
+$pool->send();
|
||
+
|
||
+foreach ($pool as $req) {
|
||
+ echo $req->getUrl(), '=',
|
||
+ $req->getResponseCode(), ':',
|
||
+ $req->getResponseMessage()->getResponseCode(), "\n";
|
||
+}
|
||
+
|
||
+foreach ($pool as $req) {
|
||
+ try {
|
||
+ $pool->attach(new HttpRequest('http://foo.bar'));
|
||
+ } catch (HttpRequestPoolException $x) {
|
||
+ echo ".\n";
|
||
+ }
|
||
+}
|
||
+
|
||
+foreach ($pool as $req) {
|
||
+ $pool->detach($req);
|
||
+}
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+http://www.php.net/=200:200
|
||
+http://dev.iworks.at/ext-http/.print_request.php=200:200
|
||
+.
|
||
+.
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestPool_002.phpt
|
||
@@ -0,0 +1,51 @@
|
||
+--TEST--
|
||
+extending HttpRequestPool
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls('HttpRequestPool');
|
||
+checkurl('www.php.net');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+class MyPool extends HttpRequestPool
|
||
+{
|
||
+ public function send()
|
||
+ {
|
||
+ while ($this->socketPerform()) {
|
||
+ if (!$this->socketSelect()) {
|
||
+ throw new HttpSocketException;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ protected final function socketPerform()
|
||
+ {
|
||
+ $result = parent::socketPerform();
|
||
+
|
||
+ echo ".";
|
||
+ foreach ($this->getFinishedRequests() as $r) {
|
||
+ echo "=", $r->getResponseCode(), "=";
|
||
+ $this->detach($r);
|
||
+ }
|
||
+
|
||
+ return $result;
|
||
+ }
|
||
+}
|
||
+
|
||
+$pool = new MyPool(
|
||
+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
|
||
+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
|
||
+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD)
|
||
+);
|
||
+
|
||
+$pool->send();
|
||
+
|
||
+echo "\nDone\n";
|
||
+?>
|
||
+--EXPECTREGEX--
|
||
+.+TEST
|
||
+\.*=200=\.*=200=\.*=200=
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestPool_003.phpt
|
||
@@ -0,0 +1,175 @@
|
||
+--TEST--
|
||
+HttpRequestPool chain
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls('HttpRequest');
|
||
+checkcls('HttpRequestPool');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+
|
||
+echo "-TEST\n";
|
||
+
|
||
+set_time_limit(0);
|
||
+ini_set('error_reporting', E_ALL);
|
||
+ini_set('html_errors', 0);
|
||
+
|
||
+class Pool extends HttpRequestPool
|
||
+{
|
||
+ private $all;
|
||
+ private $rem;
|
||
+ private $dir;
|
||
+
|
||
+ public final function __construct($urls_file = 'urls.txt', $cache_dir = 'HttpRequestPool_cache')
|
||
+ {
|
||
+ $this->dir = (is_dir($cache_dir) or @mkdir($cache_dir)) ? $cache_dir : null;
|
||
+
|
||
+ foreach (array_map('trim', file($urls_file)) as $url) {
|
||
+ $this->all[$url] = $this->dir ? $this->dir .'/'. md5($url) : null;
|
||
+ }
|
||
+
|
||
+ $this->send();
|
||
+ }
|
||
+
|
||
+ public final function send()
|
||
+ {
|
||
+ if (RMAX) {
|
||
+ $now = array_slice($this->all, 0, RMAX);
|
||
+ $this->rem = array_slice($this->all, RMAX);
|
||
+ } else {
|
||
+ $now = $urls;
|
||
+ $this->rem = array();
|
||
+ }
|
||
+
|
||
+ foreach ($now as $url => $file) {
|
||
+ $this->attach(
|
||
+ new HttpRequest(
|
||
+ $url,
|
||
+ HttpRequest::METH_GET,
|
||
+ array(
|
||
+ 'redirect' => 5,
|
||
+ 'compress' => GZIP,
|
||
+ 'timeout' => TOUT,
|
||
+ 'connecttimeout' => TOUT,
|
||
+ 'lastmodified' => is_file($file)?filemtime($file):0
|
||
+ )
|
||
+ )
|
||
+ );
|
||
+ }
|
||
+
|
||
+ while ($this->socketPerform()) {
|
||
+ if (!$this->socketSelect()) {
|
||
+ throw new HttpSocketException;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ protected final function socketPerform()
|
||
+ {
|
||
+ try {
|
||
+ $rc = parent::socketPerform();
|
||
+ } catch (HttpRequestException $x) {
|
||
+ // a request may have thrown an exception,
|
||
+ // but it is still save to continue
|
||
+ echo $x->getMessage(), "\n";
|
||
+ }
|
||
+
|
||
+ foreach ($this->getFinishedRequests() as $r) {
|
||
+ $this->detach($r);
|
||
+
|
||
+ $u = $r->getUrl();
|
||
+ $c = $r->getResponseCode();
|
||
+ $b = $r->getResponseBody();
|
||
+
|
||
+ printf("%d %s %d\n", $c, $u, strlen($b));
|
||
+
|
||
+ if ($c == 200 && $this->dir) {
|
||
+ file_put_contents($this->all[$u], $b);
|
||
+ }
|
||
+
|
||
+ if ($a = each($this->rem)) {
|
||
+ list($url, $file) = $a;
|
||
+ $this->attach(
|
||
+ new HttpRequest(
|
||
+ $url,
|
||
+ HttpRequest::METH_GET,
|
||
+ array(
|
||
+ 'redirect' => 5,
|
||
+ 'compress' => GZIP,
|
||
+ 'timeout' => TOUT,
|
||
+ 'connecttimeout' => TOUT,
|
||
+ 'lastmodified' => is_file($file)?filemtime($file):0
|
||
+ )
|
||
+ )
|
||
+ );
|
||
+ }
|
||
+ }
|
||
+ return $rc;
|
||
+ }
|
||
+}
|
||
+
|
||
+define('GZIP', true);
|
||
+define('TOUT', 50);
|
||
+define('RMAX', 10);
|
||
+chdir(dirname(__FILE__));
|
||
+
|
||
+$time = microtime(true);
|
||
+$pool = new Pool();
|
||
+printf("Elapsed: %0.3fs\n", microtime(true)-$time);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+%d %s %d
|
||
+Elapsed: %fs
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestPool_004.phpt
|
||
@@ -0,0 +1,19 @@
|
||
+--TEST--
|
||
+HttpRequestPool::__destruct() invalid curl handle
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpRequest');
|
||
+checkcls('HttpRequestPool');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$p = new HttpRequestPool(new HttpRequest('http://example.com'));
|
||
+$p = null;
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestPool_005.phpt
|
||
@@ -0,0 +1,46 @@
|
||
+--TEST--
|
||
+HttpRequestPool exception
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpRequestPool');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$p = new HttpRequestPool(new HttpRequest('http://_____'));
|
||
+try {
|
||
+ $p->send();
|
||
+} catch (HttpRequestPoolException $x) {
|
||
+ for ($i=0; $x; ++$i, $x = @$x->innerException) {
|
||
+ printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage());
|
||
+ }
|
||
+ var_dump($i);
|
||
+}
|
||
+$p = new HttpRequestPool(new HttpRequest('http://_____'), new HttpRequest('http://_____'));
|
||
+try {
|
||
+ $p->send();
|
||
+} catch (HttpRequestPoolException $x) {
|
||
+ for ($i=0; $x; ++$i, $x = @$x->innerException) {
|
||
+ printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage());
|
||
+ }
|
||
+ var_dump($i);
|
||
+}
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+HttpRequestPoolException: Exception caused by 2 inner exception(s)
|
||
+ HttpInvalidParamException: Empty or too short HTTP message: ''
|
||
+ HttpRequestException: %souldn't resolve host name; %s (http://_____/)
|
||
+int(3)
|
||
+HttpRequestPoolException: Exception caused by 4 inner exception(s)
|
||
+ HttpInvalidParamException: Empty or too short HTTP message: ''
|
||
+ HttpRequestException: %souldn't resolve host name; %s (http://_____/)
|
||
+ HttpInvalidParamException: Empty or too short HTTP message: ''
|
||
+ HttpRequestException: %souldn't resolve host name; %s (http://_____/)
|
||
+int(5)
|
||
+Done
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequestPool_006.phpt
|
||
@@ -0,0 +1,50 @@
|
||
+--TEST--
|
||
+HttpRequestPool detaching in callbacks
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls("HttpRequestPool");
|
||
+checkurl("at.php.net");
|
||
+checkurl("de.php.net");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+class r extends HttpRequest {
|
||
+ function onProgress() {
|
||
+ static $i = array();
|
||
+ if (empty($i[$this->getUrl()])) {
|
||
+ $i[$this->getUrl()] = true;
|
||
+ try {
|
||
+ $GLOBALS['p']->detach($this);
|
||
+ } catch (Exception $ex) {
|
||
+ echo $ex, "\n";
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ function onFinish() {
|
||
+ $GLOBALS['p']->detach($this);
|
||
+ }
|
||
+}
|
||
+$p = new HttpRequestPool(new r("http://at.php.net"), new r("http://de.php.net"));
|
||
+$p->send();
|
||
+var_dump($p->getAttachedRequests());
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d
|
||
+Stack trace:
|
||
+#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r))
|
||
+#1 [internal function]: r->onProgress(Array)
|
||
+#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send()
|
||
+#3 {main}
|
||
+exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d
|
||
+Stack trace:
|
||
+#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r))
|
||
+#1 [internal function]: r->onProgress(Array)
|
||
+#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send()
|
||
+#3 {main}
|
||
+array(0) {
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_001.phpt
|
||
@@ -0,0 +1,51 @@
|
||
+--TEST--
|
||
+HttpRequest options
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$r1 = new HttpRequest(null, 0, array('redirect'=>11, 'headers'=>array('X-Foo'=>'Bar')));
|
||
+$r2 = new HttpRequest;
|
||
+$r2->setOptions(array('redirect'=>99, 'headers'=>array('X-Bar'=>'Foo')));
|
||
+$o1 = $r1->getOptions();
|
||
+$o2 = $r2->getOptions();
|
||
+$r1->setOptions($o2);
|
||
+$r2->setOptions($o1);
|
||
+print_r(array($o1, $o2));
|
||
+var_dump(serialize($r1->getOptions()) === serialize($r2->getOptions()));
|
||
+$r1 = null;
|
||
+$r2 = null;
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Array
|
||
+(
|
||
+ [0] => Array
|
||
+ (
|
||
+ [headers] => Array
|
||
+ (
|
||
+ [X-Foo] => Bar
|
||
+ [X-Bar] => Foo
|
||
+ )
|
||
+
|
||
+ [redirect] => 11
|
||
+ )
|
||
+
|
||
+ [1] => Array
|
||
+ (
|
||
+ [headers] => Array
|
||
+ (
|
||
+ [X-Bar] => Foo
|
||
+ [X-Foo] => Bar
|
||
+ )
|
||
+
|
||
+ [redirect] => 99
|
||
+ )
|
||
+
|
||
+)
|
||
+bool(false)
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_002.phpt
|
||
@@ -0,0 +1,86 @@
|
||
+--TEST--
|
||
+HttpRequest GET/POST
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpRequest');
|
||
+checkurl('www.google.com');
|
||
+checkurl('dev.iworks.at');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$r = new HttpRequest('http://www.google.com', HttpRequest::METH_GET);
|
||
+$r->send();
|
||
+print_r($r->getResponseInfo());
|
||
+
|
||
+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
|
||
+$r->addCookies(array('MyCookie' => 'foobar'));
|
||
+$r->addQueryData(array('gq'=>'foobar','gi'=>10));
|
||
+$r->addPostFields(array('pq'=>'foobar','pi'=>10));
|
||
+$r->addPostFile('upload', dirname(__FILE__).'/data.txt', 'text/plain');
|
||
+$r->send();
|
||
+echo $r->getResponseBody();
|
||
+var_dump($r->getResponseMessage()->getResponseCode());
|
||
+
|
||
+echo "Done";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Array
|
||
+(
|
||
+ [effective_url] => http://www.google.com/
|
||
+ [response_code] => 302
|
||
+ [total_time] => %f
|
||
+ [namelookup_time] => %f
|
||
+ [connect_time] => %f
|
||
+ [pretransfer_time] => %f
|
||
+ [size_upload] => %d
|
||
+ [size_download] => %d
|
||
+ [speed_download] => %d
|
||
+ [speed_upload] => %d
|
||
+ [header_size] => %d
|
||
+ [request_size] => %d
|
||
+ [ssl_verifyresult] => %d
|
||
+ [filetime] => -1
|
||
+ [content_length_download] => %d
|
||
+ [content_length_upload] => %d
|
||
+ [starttransfer_time] => %f
|
||
+ [content_type] => %s
|
||
+ [redirect_time] => %d
|
||
+ [redirect_count] => %d
|
||
+ [connect_code] => %d
|
||
+ [httpauth_avail] => %d
|
||
+ [proxyauth_avail] => %d
|
||
+ [os_errno] => %d
|
||
+ [num_connects] => %d
|
||
+ [ssl_engines] => Array
|
||
+ %a
|
||
+ [cookies] => Array
|
||
+ %a
|
||
+ [error] =>
|
||
+)
|
||
+Array
|
||
+(
|
||
+ [gq] => foobar
|
||
+ [gi] => 10
|
||
+ [pq] => foobar
|
||
+ [pi] => 10
|
||
+ [MyCookie] => foobar
|
||
+)
|
||
+Array
|
||
+(
|
||
+ [upload] => Array
|
||
+ (
|
||
+ [name] => data.txt
|
||
+ [type] => text/plain
|
||
+ [tmp_name] => %a
|
||
+ [error] => 0
|
||
+ [size] => 1010
|
||
+ )
|
||
+
|
||
+)
|
||
+int(200)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_003.phpt
|
||
@@ -0,0 +1,54 @@
|
||
+--TEST--
|
||
+HttpRequest SSL
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkurl('arweb.info');
|
||
+skipif(!http_support(HTTP_SUPPORT_SSLREQUESTS), 'need ssl-request support')
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$o = array('redirect' => '3', 'ssl' => array('version' => '3', 'verifyhost' => '1'));
|
||
+$r = new HttpRequest('https://ssl.irmler.at/iworks/data.txt');
|
||
+$r->setOptions($o);
|
||
+$r->send();
|
||
+var_dump($r->getResponseBody());
|
||
+var_dump(is_object($r->getResponseMessage()));
|
||
+var_dump(is_object($r->getResponseMessage()));
|
||
+var_dump(is_object($r->getResponseMessage()));
|
||
+var_dump($o);
|
||
+$r->setOptions($o);
|
||
+$r->send();
|
||
+var_dump($o);
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(10) "1234567890"
|
||
+bool(true)
|
||
+bool(true)
|
||
+bool(true)
|
||
+array(2) {
|
||
+ ["redirect"]=>
|
||
+ string(1) "3"
|
||
+ ["ssl"]=>
|
||
+ array(2) {
|
||
+ ["version"]=>
|
||
+ string(1) "3"
|
||
+ ["verifyhost"]=>
|
||
+ string(1) "1"
|
||
+ }
|
||
+}
|
||
+array(2) {
|
||
+ ["redirect"]=>
|
||
+ string(1) "3"
|
||
+ ["ssl"]=>
|
||
+ array(2) {
|
||
+ ["version"]=>
|
||
+ string(1) "3"
|
||
+ ["verifyhost"]=>
|
||
+ string(1) "1"
|
||
+ }
|
||
+}
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_004.phpt
|
||
@@ -0,0 +1,162 @@
|
||
+--TEST--
|
||
+HttpRequest multiple posts
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$fields = array(
|
||
+ array('int' => 1, 'dbl' => M_PI),
|
||
+ array('str' => 'something', 'nil' => null)
|
||
+);
|
||
+
|
||
+echo "\nFirst Request\n";
|
||
+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HttpRequest::METH_POST);
|
||
+$r->setPostFields($fields[0]);
|
||
+$r->addPostFields($fields[1]);
|
||
+var_dump($r->send()->getBody());
|
||
+var_dump($fields);
|
||
+
|
||
+echo "\nSecond Request\n";
|
||
+$r->setPostFields($fields);
|
||
+var_dump($r->send()->getBody());
|
||
+var_dump($fields);
|
||
+
|
||
+echo "\nThird Request\n";
|
||
+$r->addPostFields(array('x' => 'X'));
|
||
+var_dump($r->send()->getBody());
|
||
+var_dump($fields);
|
||
+
|
||
+echo "\nFourth Request\n";
|
||
+$r->setPostFields(array());
|
||
+var_dump($r->send()->getBody());
|
||
+var_dump($fields);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+
|
||
+First Request
|
||
+string(%d) "Array
|
||
+(
|
||
+ [int] => 1
|
||
+ [dbl] => 3.1415926535898
|
||
+ [str] => something
|
||
+ [nil] =>
|
||
+)
|
||
+string(44) "int=1&dbl=3.1415926535898&str=something&nil="
|
||
+"
|
||
+array(2) {
|
||
+ [0]=>
|
||
+ array(2) {
|
||
+ ["int"]=>
|
||
+ int(1)
|
||
+ ["dbl"]=>
|
||
+ float(3.1415926535898)
|
||
+ }
|
||
+ [1]=>
|
||
+ array(2) {
|
||
+ ["str"]=>
|
||
+ string(9) "something"
|
||
+ ["nil"]=>
|
||
+ NULL
|
||
+ }
|
||
+}
|
||
+
|
||
+Second Request
|
||
+string(%d) "Array
|
||
+(
|
||
+ [0] => Array
|
||
+ (
|
||
+ [int] => 1
|
||
+ [dbl] => 3.1415926535898
|
||
+ )
|
||
+
|
||
+ [1] => Array
|
||
+ (
|
||
+ [str] => something
|
||
+ [nil] =>
|
||
+ )
|
||
+
|
||
+)
|
||
+string(72) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D="
|
||
+"
|
||
+array(2) {
|
||
+ [0]=>
|
||
+ array(2) {
|
||
+ ["int"]=>
|
||
+ int(1)
|
||
+ ["dbl"]=>
|
||
+ float(3.1415926535898)
|
||
+ }
|
||
+ [1]=>
|
||
+ array(2) {
|
||
+ ["str"]=>
|
||
+ string(9) "something"
|
||
+ ["nil"]=>
|
||
+ NULL
|
||
+ }
|
||
+}
|
||
+
|
||
+Third Request
|
||
+string(%d) "Array
|
||
+(
|
||
+ [0] => Array
|
||
+ (
|
||
+ [int] => 1
|
||
+ [dbl] => 3.1415926535898
|
||
+ )
|
||
+
|
||
+ [1] => Array
|
||
+ (
|
||
+ [str] => something
|
||
+ [nil] =>
|
||
+ )
|
||
+
|
||
+ [x] => X
|
||
+)
|
||
+string(76) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D=&x=X"
|
||
+"
|
||
+array(2) {
|
||
+ [0]=>
|
||
+ array(2) {
|
||
+ ["int"]=>
|
||
+ int(1)
|
||
+ ["dbl"]=>
|
||
+ float(3.1415926535898)
|
||
+ }
|
||
+ [1]=>
|
||
+ array(2) {
|
||
+ ["str"]=>
|
||
+ string(9) "something"
|
||
+ ["nil"]=>
|
||
+ NULL
|
||
+ }
|
||
+}
|
||
+
|
||
+Fourth Request
|
||
+string(13) "string(0) ""
|
||
+"
|
||
+array(2) {
|
||
+ [0]=>
|
||
+ array(2) {
|
||
+ ["int"]=>
|
||
+ int(1)
|
||
+ ["dbl"]=>
|
||
+ float(3.1415926535898)
|
||
+ }
|
||
+ [1]=>
|
||
+ array(2) {
|
||
+ ["str"]=>
|
||
+ string(9) "something"
|
||
+ ["nil"]=>
|
||
+ NULL
|
||
+ }
|
||
+}
|
||
+Done
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_005.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+HttpRequest accessors
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+error_reporting(0);
|
||
+$r = new HttpRequest;
|
||
+foreach (get_class_methods('HttpRequest') as $method) {
|
||
+ try {
|
||
+ if (strlen($method) > 3 && substr($method, 0, 3) == 'get')
|
||
+ $x = $r->$method();
|
||
+ } catch (HttpException $e) {
|
||
+ }
|
||
+}
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_006.phpt
|
||
@@ -0,0 +1,147 @@
|
||
+--TEST--
|
||
+HttpRequest XMLRPC
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkext('xmlrpc');
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
|
||
+$r->setContentType('text/xml');
|
||
+$r->setBody(xmlrpc_encode_request('testMethod', array('foo' => 'bar')));
|
||
+var_dump($r->send());
|
||
+var_dump($r->send());
|
||
+var_dump($r->send());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+object(HttpMessage)#%d (%d) {
|
||
+ ["type:protected"]=>
|
||
+ int(2)
|
||
+ ["body:protected"]=>
|
||
+ string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
|
||
+<methodCall>
|
||
+<methodName>testMethod</methodName>
|
||
+<params>
|
||
+ <param>
|
||
+ <value>
|
||
+ <struct>
|
||
+ <member>
|
||
+ <name>foo</name>
|
||
+ <value>
|
||
+ <string>bar</string>
|
||
+ </value>
|
||
+ </member>
|
||
+ </struct>
|
||
+ </value>
|
||
+ </param>
|
||
+</params>
|
||
+</methodCall>
|
||
+"
|
||
+"
|
||
+ ["requestMethod:protected"]=>
|
||
+ string(0) ""
|
||
+ ["requestUrl:protected"]=>
|
||
+ string(0) ""
|
||
+ ["responseStatus:protected"]=>
|
||
+ string(2) "OK"
|
||
+ ["responseCode:protected"]=>
|
||
+ int(200)
|
||
+ ["httpVersion:protected"]=>
|
||
+ float(1.1)
|
||
+ ["headers:protected"]=>
|
||
+ array(6) {
|
||
+ %a
|
||
+ }
|
||
+ ["parentMessage:protected"]=>
|
||
+ NULL
|
||
+}
|
||
+object(HttpMessage)#%d (%d) {
|
||
+ ["type:protected"]=>
|
||
+ int(2)
|
||
+ ["body:protected"]=>
|
||
+ string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
|
||
+<methodCall>
|
||
+<methodName>testMethod</methodName>
|
||
+<params>
|
||
+ <param>
|
||
+ <value>
|
||
+ <struct>
|
||
+ <member>
|
||
+ <name>foo</name>
|
||
+ <value>
|
||
+ <string>bar</string>
|
||
+ </value>
|
||
+ </member>
|
||
+ </struct>
|
||
+ </value>
|
||
+ </param>
|
||
+</params>
|
||
+</methodCall>
|
||
+"
|
||
+"
|
||
+ ["requestMethod:protected"]=>
|
||
+ string(0) ""
|
||
+ ["requestUrl:protected"]=>
|
||
+ string(0) ""
|
||
+ ["responseStatus:protected"]=>
|
||
+ string(2) "OK"
|
||
+ ["responseCode:protected"]=>
|
||
+ int(200)
|
||
+ ["httpVersion:protected"]=>
|
||
+ float(1.1)
|
||
+ ["headers:protected"]=>
|
||
+ array(6) {
|
||
+ %a
|
||
+ }
|
||
+ ["parentMessage:protected"]=>
|
||
+ NULL
|
||
+}
|
||
+object(HttpMessage)#%d (%d) {
|
||
+ ["type:protected"]=>
|
||
+ int(2)
|
||
+ ["body:protected"]=>
|
||
+ string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
|
||
+<methodCall>
|
||
+<methodName>testMethod</methodName>
|
||
+<params>
|
||
+ <param>
|
||
+ <value>
|
||
+ <struct>
|
||
+ <member>
|
||
+ <name>foo</name>
|
||
+ <value>
|
||
+ <string>bar</string>
|
||
+ </value>
|
||
+ </member>
|
||
+ </struct>
|
||
+ </value>
|
||
+ </param>
|
||
+</params>
|
||
+</methodCall>
|
||
+"
|
||
+"
|
||
+ ["requestMethod:protected"]=>
|
||
+ string(0) ""
|
||
+ ["requestUrl:protected"]=>
|
||
+ string(0) ""
|
||
+ ["responseStatus:protected"]=>
|
||
+ string(2) "OK"
|
||
+ ["responseCode:protected"]=>
|
||
+ int(200)
|
||
+ ["httpVersion:protected"]=>
|
||
+ float(1.1)
|
||
+ ["headers:protected"]=>
|
||
+ array(6) {
|
||
+ %a
|
||
+ }
|
||
+ ["parentMessage:protected"]=>
|
||
+ NULL
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_007.phpt
|
||
@@ -0,0 +1,64 @@
|
||
+--TEST--
|
||
+HttpRequest PUT
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
|
||
+$r->recordHistory = true;
|
||
+$r->addHeaders(array('content-type' => 'text/plain'));
|
||
+$r->setPutFile(__FILE__);
|
||
+$r->send();
|
||
+var_dump($r->getHistory()->toString(true));
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(%d) "PUT /ext-http/.print_put.php5 HTTP/1.1
|
||
+User-Agent: PECL::HTTP/%a
|
||
+Host: dev.iworks.at
|
||
+Accept: */*
|
||
+Content-Type: text/plain
|
||
+Content-Length: %d
|
||
+Expect: 100-continue
|
||
+
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
|
||
+$r->recordHistory = true;
|
||
+$r->addHeaders(array('content-type' => 'text/plain'));
|
||
+$r->setPutFile(__FILE__);
|
||
+$r->send();
|
||
+var_dump($r->getHistory()->toString(true));
|
||
+echo "Done\n";
|
||
+?>
|
||
+
|
||
+HTTP/1.1 100 Continue
|
||
+HTTP/1.1 200 OK
|
||
+Date: %a
|
||
+Server: %a
|
||
+X-Powered-By: %a
|
||
+Vary: Accept-Encoding
|
||
+Content-Length: %d
|
||
+Content-Type: text/html
|
||
+
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
|
||
+$r->recordHistory = true;
|
||
+$r->addHeaders(array('content-type' => 'text/plain'));
|
||
+$r->setPutFile(__FILE__);
|
||
+$r->send();
|
||
+var_dump($r->getHistory()->toString(true));
|
||
+echo "Done\n";
|
||
+?>
|
||
+
|
||
+"
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_008.phpt
|
||
@@ -0,0 +1,32 @@
|
||
+--TEST--
|
||
+HttpRequest custom request method
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+HttpRequest::methodRegister('foobar');
|
||
+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HttpRequest::METH_FOOBAR);
|
||
+$r->setContentType('text/plain');
|
||
+$r->setBody('Yep, this is FOOBAR!');
|
||
+var_dump($r->send()->getResponseCode());
|
||
+var_dump($r->getRawRequestMessage());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+int(200)
|
||
+string(%d) "FOOBAR /ext-http/.print_request.php HTTP/1.1
|
||
+User-Agent: %a
|
||
+Host: dev.iworks.at
|
||
+Accept: */*
|
||
+Content-Type: text/plain
|
||
+Content-Length: 20
|
||
+
|
||
+Yep, this is FOOBAR!"
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_009.phpt
|
||
@@ -0,0 +1,48 @@
|
||
+--TEST--
|
||
+HttpRequest callbacks
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+class _R extends HttpRequest
|
||
+{
|
||
+ function onProgress($progress)
|
||
+ {
|
||
+ print_r($progress);
|
||
+ }
|
||
+
|
||
+ function onFinish()
|
||
+ {
|
||
+ var_dump($this->getResponseCode());
|
||
+ }
|
||
+}
|
||
+
|
||
+$r = new _R('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
|
||
+$r->addPostFile('upload', __FILE__, 'text/plain');
|
||
+$r->send();
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Array
|
||
+(
|
||
+ [dltotal] => %f
|
||
+ [dlnow] => %f
|
||
+ [ultotal] => %f
|
||
+ [ulnow] => %f
|
||
+)
|
||
+%array
|
||
+(
|
||
+ [dltotal] => %f
|
||
+ [dlnow] => %f
|
||
+ [ultotal] => %f
|
||
+ [ulnow] => %f
|
||
+)
|
||
+int(200)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpRequest_010.phpt
|
||
@@ -0,0 +1,48 @@
|
||
+--TEST--
|
||
+HttpRequest cookie API
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls("HttpRequest");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$r = new HttpRequest("http://dev.iworks.at/ext-http/.cookie.php");
|
||
+
|
||
+$r->send();
|
||
+$c[0] = $r->getResponseInfo("cookies");
|
||
+if (!empty($c[0])) {
|
||
+ var_dump('$c[0]', $c[0]);
|
||
+}
|
||
+
|
||
+var_dump($r->enableCookies());
|
||
+$r->send();
|
||
+
|
||
+$c[1] = $r->getResponseInfo("cookies");
|
||
+if (empty($c[1])) {
|
||
+ var_dump('$c[1]', $c[1]);
|
||
+}
|
||
+
|
||
+var_dump($r->resetCookies());
|
||
+$r->send();
|
||
+
|
||
+$c[2] = $r->getResponseInfo("cookies");
|
||
+if ($c[1] === $c[2]) {
|
||
+ var_dump('$c[1]', $c[1], '$c[2]', $c[2]);
|
||
+}
|
||
+
|
||
+$r->send();
|
||
+$c[3] = $r->getResponseInfo("cookies");
|
||
+if ($c[2] !== $c[3]) {
|
||
+ var_dump('$c[2]', $c[2], '$c[3]', $c[3]);
|
||
+}
|
||
+
|
||
+echo "Done\n";
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(true)
|
||
+bool(true)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpResponse_001.phpt
|
||
@@ -0,0 +1,25 @@
|
||
+--TEST--
|
||
+HttpResponse - send data with caching headers
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcgi();
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+HttpResponse::setCache(true);
|
||
+HttpResponse::setCacheControl('public', 3600);
|
||
+HttpResponse::setData('foobar');
|
||
+HttpResponse::send();
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: public, must-revalidate, max-age=3600
|
||
+Last-Modified: %a, %d %a 20%d %d:%d:%d GMT
|
||
+Content-Type: %a
|
||
+Accept-Ranges: bytes
|
||
+ETag: "3858f62230ac3c915f300c664312c63f"
|
||
+Content-Length: 6
|
||
+
|
||
+foobar
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpResponse_002.phpt
|
||
@@ -0,0 +1,25 @@
|
||
+--TEST--
|
||
+HttpResponse - send gzipped file
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcgi();
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_ACCEPT_ENCODING=gzip
|
||
+--FILE--
|
||
+<?php
|
||
+HttpResponse::setGzip(true);
|
||
+HttpResponse::setFile(__FILE__);
|
||
+HttpResponse::send();
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Content-Type: %a
|
||
+Accept-Ranges: bytes
|
||
+Content-Encoding: gzip
|
||
+Vary: Accept-Encoding
|
||
+
|
||
+%a
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpResponse_003.phpt
|
||
@@ -0,0 +1,30 @@
|
||
+--TEST--
|
||
+HttpResponse - send gzipped file with caching headers
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcgi();
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_ACCEPT_ENCODING=gzip
|
||
+--FILE--
|
||
+<?php
|
||
+HttpResponse::setGzip(true);
|
||
+HttpResponse::setCache(true);
|
||
+HttpResponse::setCacheControl('public', 3600);
|
||
+HttpResponse::setFile(__FILE__);
|
||
+HttpResponse::send();
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: public, must-revalidate, max-age=3600
|
||
+Last-Modified: %a, %d %a 20%d %d:%d:%d GMT
|
||
+Content-Type: %a
|
||
+Accept-Ranges: bytes
|
||
+ETag: "%a"
|
||
+Content-Encoding: gzip
|
||
+Vary: Accept-Encoding
|
||
+
|
||
+%a
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpResponse_004.phpt
|
||
@@ -0,0 +1,27 @@
|
||
+--TEST--
|
||
+HttpResponse - send cached gzipped data
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.7");
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_IF_NONE_MATCH="900150983cd24fb0d6963f7d28e17f72"
|
||
+HTTP_ACCEPT_ENCODING=gzip
|
||
+--FILE--
|
||
+<?php
|
||
+HttpResponse::setGzip(true);
|
||
+HttpResponse::setCache(true);
|
||
+HttpResponse::setCacheControl('public', 3600);
|
||
+HttpResponse::setData("abc");
|
||
+HttpResponse::send();
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 304%s
|
||
+X-Powered-By: PHP/%s
|
||
+Cache-Control: public, must-revalidate, max-age=3600
|
||
+Last-Modified: %s
|
||
+Accept-Ranges: bytes
|
||
+ETag: "900150983cd24fb0d6963f7d28e17f72"
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/HttpResponse_005.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+HttpResponse file not found
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set("error_reporting", 0);
|
||
+ini_set("default_mimetype", "text/plain");
|
||
+
|
||
+HttpResponse::setContentType("application/pdf");
|
||
+HttpResponse::setContentDisposition("doc.pdf");
|
||
+HttpResponse::setFile("__nonexistant__.pdf");
|
||
+HttpResponse::send();
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 404%s
|
||
+X-Powered-By: PHP/%s
|
||
+Content-Type: text/plain
|
||
+
|
||
+File not found
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/allowed_methods_002.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+allowed methods
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+include 'log.inc';
|
||
+log_prepare(_AMETH_LOG);
|
||
+ini_set('http.request.methods.allowed', 'POST');
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 405%s
|
||
+X-Powered-By: PHP/%a
|
||
+Allow: POST
|
||
+Content-type: %a
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/allowed_methods_002_logging.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+logging allowed methods
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=example.com
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+include 'log.inc';
|
||
+log_content(_AMETH_LOG);
|
||
+echo "Done";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [405-ALLOWED] Allow: POST <%a>
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/bug_15800.phpt
|
||
@@ -0,0 +1,49 @@
|
||
+--TEST--
|
||
+Bug #15800 Double free when zval is separated in convert_to_*
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpRequest');
|
||
+skipif(!function_exists('debug_zval_dump'), "need DEBUG version of PHP");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$o = array('ssl' => array('verifypeer'=>'1'));
|
||
+debug_zval_dump($o);
|
||
+
|
||
+$r = new HttpRequest('http://www.google.com');
|
||
+$r->setOptions($o);
|
||
+$r->send();
|
||
+debug_zval_dump($o);
|
||
+
|
||
+unset($r);
|
||
+debug_zval_dump($o);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+array(1) refcount(2){
|
||
+ ["ssl"]=>
|
||
+ array(1) refcount(1){
|
||
+ ["verifypeer"]=>
|
||
+ string(1) "1" refcount(1)
|
||
+ }
|
||
+}
|
||
+array(1) refcount(2){
|
||
+ ["ssl"]=>
|
||
+ array(1) refcount(1){
|
||
+ ["verifypeer"]=>
|
||
+ string(1) "1" refcount(2)
|
||
+ }
|
||
+}
|
||
+array(1) refcount(2){
|
||
+ ["ssl"]=>
|
||
+ array(1) refcount(1){
|
||
+ ["verifypeer"]=>
|
||
+ string(1) "1" refcount(1)
|
||
+ }
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/build_str_001.phpt
|
||
@@ -0,0 +1,30 @@
|
||
+--TEST--
|
||
+http_build_str
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+parse_str("a=b", $q);
|
||
+echo http_build_str($q, null, "&"), "\n";
|
||
+
|
||
+parse_str("a=b&c[0]=1", $q);
|
||
+echo http_build_str($q, null, "&"), "\n";
|
||
+
|
||
+parse_str("a=b&c[0]=1&d[e]=f", $q);
|
||
+echo http_build_str($q, null, "&"), "\n";
|
||
+
|
||
+echo http_build_str(array(1,2,array(3)), "foo", "&"), "\n";
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+a=b
|
||
+a=b&c%5B0%5D=1
|
||
+a=b&c%5B0%5D=1&d%5Be%5D=f
|
||
+foo%5B0%5D=1&foo%5B1%5D=2&foo%5B2%5D%5B0%5D=3
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/build_url_001.phpt
|
||
@@ -0,0 +1,18 @@
|
||
+--TEST--
|
||
+http_build_url() with relative paths
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+echo http_build_url('page'), "\n";
|
||
+echo http_build_url('with/some/path/'), "\n";
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+http://%a/page
|
||
+http://%a/with/some/path/
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/build_url_002.phpt
|
||
@@ -0,0 +1,30 @@
|
||
+--TEST--
|
||
+http_build_url() with parse_url()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+echo http_build_url(parse_url("http://example.org/orig?q=1#f"),
|
||
+ parse_url("https://www.example.com:9999/replaced#n")), "\n";
|
||
+echo http_build_url(("http://example.org/orig?q=1#f"),
|
||
+ ("https://www.example.com:9999/replaced#n"), 0, $u), "\n";
|
||
+print_r($u);
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+https://www.example.com:9999/replaced?q=1#n
|
||
+https://www.example.com:9999/replaced?q=1#n
|
||
+Array
|
||
+(
|
||
+ [scheme] => https
|
||
+ [host] => www.example.com
|
||
+ [port] => 9999
|
||
+ [path] => /replaced
|
||
+ [query] => q=1
|
||
+ [fragment] => n
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/build_url_003.phpt
|
||
@@ -0,0 +1,26 @@
|
||
+--TEST--
|
||
+http_build_url()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=www.example.com
|
||
+--FILE--
|
||
+<?php
|
||
+$url = '/path/?query#anchor';
|
||
+echo "-TEST\n";
|
||
+printf("-%s-\n", http_build_url($url));
|
||
+printf("-%s-\n", http_build_url($url, array('scheme' => 'https')));
|
||
+printf("-%s-\n", http_build_url($url, array('scheme' => 'https', 'host' => 'ssl.example.com')));
|
||
+printf("-%s-\n", http_build_url($url, array('scheme' => 'ftp', 'host' => 'ftp.example.com', 'port' => 21)));
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+-http://www.example.com/path/?query#anchor-
|
||
+-https://www.example.com/path/?query#anchor-
|
||
+-https://ssl.example.com/path/?query#anchor-
|
||
+-ftp://ftp.example.com/path/?query#anchor-
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/build_url_004.phpt
|
||
@@ -0,0 +1,22 @@
|
||
+--TEST--
|
||
+http_build_url flags
|
||
+--SKPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+echo http_build_url("http://mike@www.example.com/foo/bar", "./baz", HTTP_URL_STRIP_AUTH|HTTP_URL_JOIN_PATH), "\n";
|
||
+echo http_build_url("http://mike@www.example.com/foo/bar/", "../baz", HTTP_URL_STRIP_USER|HTTP_URL_JOIN_PATH), "\n";
|
||
+echo http_build_url("http://mike:1234@www.example.com/foo/bar/", "./../baz", HTTP_URL_STRIP_PASS|HTTP_URL_JOIN_PATH), "\n";
|
||
+echo http_build_url("http://www.example.com:8080/foo?a[0]=b#frag", "?a[0]=1&b=c&a[1]=b", HTTP_URL_JOIN_QUERY|HTTP_URL_STRIP_PORT|HTTP_URL_STRIP_FRAGMENT|HTTP_URL_STRIP_PATH), "\n";
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+http://www.example.com/foo/baz
|
||
+http://www.example.com/foo/baz
|
||
+http://mike@www.example.com/foo/baz
|
||
+http://www.example.com/?a%5B0%5D=1&a%5B1%5D=b&b=c
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/chunked_decode_001.phpt
|
||
@@ -0,0 +1,25 @@
|
||
+--TEST--
|
||
+http_chunked_decode() "\r\n"
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$data =
|
||
+"02\r\n".
|
||
+"ab\r\n".
|
||
+"04\r\n".
|
||
+"ra\nc\r\n".
|
||
+"06\r\n".
|
||
+"adabra\r\n".
|
||
+"0\r\n".
|
||
+"nothing\n";
|
||
+var_dump(http_chunked_decode($data));
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(12) "abra
|
||
+cadabra"
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/chunked_decode_002.phpt
|
||
@@ -0,0 +1,25 @@
|
||
+--TEST--
|
||
+http_chunked_decode() "\n"
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$data =
|
||
+"02\n".
|
||
+"ab\n".
|
||
+"04\n".
|
||
+"ra\nc\n".
|
||
+"06\n".
|
||
+"adabra\n".
|
||
+"0\n".
|
||
+"hidden\n";
|
||
+var_dump(http_chunked_decode($data));
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(12) "abra
|
||
+cadabra"
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/chunked_decode_003.phpt
|
||
@@ -0,0 +1,27 @@
|
||
+--TEST--
|
||
+http_chunked_decode() truncated message
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$data =
|
||
+"02\r\n".
|
||
+"ab\r\n".
|
||
+"04\r\n".
|
||
+"ra\nc\r\n".
|
||
+"06\r\n".
|
||
+"adabra\r\n".
|
||
+"ff\r\n".
|
||
+"\nall we got\n";
|
||
+var_dump(http_chunked_decode($data));
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+%aWarning%ahttp_chunked_decode()%aTruncated message: chunk size 255 exceeds remaining data size 12 at pos 34 of 46 in%a
|
||
+string(24) "abra
|
||
+cadabra
|
||
+all we got
|
||
+"
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/chunked_decode_004.phpt
|
||
@@ -0,0 +1,26 @@
|
||
+--TEST--
|
||
+http_chunked_decode() truncated message ending with NUL after a chunk
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$data =
|
||
+"02\r\n".
|
||
+"ab\r\n".
|
||
+"04\r\n".
|
||
+"ra\nc\r\n".
|
||
+"06\r\n".
|
||
+"adabra\r\n".
|
||
+"0c\r\n".
|
||
+"\nall we got\n";
|
||
+var_dump(http_chunked_decode($data));
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(24) "abra
|
||
+cadabra
|
||
+all we got
|
||
+"
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/cloning_001.phpt
|
||
@@ -0,0 +1,29 @@
|
||
+--TEST--
|
||
+cloning
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+checkcls('HttpRequest');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$r1 = new HttpRequest;
|
||
+$r2 = clone $r1;
|
||
+$r1->setOptions(array('redirect' => 3));
|
||
+var_dump($r1->getOptions() == $r2->getOptions());
|
||
+$r1->setUrl('http://www.google.com/');
|
||
+var_dump($r1->getUrl() == $r2->getUrl());
|
||
+$r1->send();
|
||
+var_dump($r1->getResponseInfo() == $r2->getResponseInfo());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(false)
|
||
+bool(false)
|
||
+bool(false)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/data.txt
|
||
@@ -0,0 +1,10 @@
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/date_001.phpt
|
||
@@ -0,0 +1,17 @@
|
||
+--TEST--
|
||
+http_date() with timestamp
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+echo http_date(1), "\n";
|
||
+echo http_date(1234567890), "\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Thu, 01 Jan 1970 00:00:01 GMT
|
||
+Fri, 13 Feb 2009 23:31:30 GMT
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/date_002.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+http_date() without timestamp
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+ini_set('date.timezone', 'GMT');
|
||
+$d = http_date();
|
||
+$t = strtotime($d);
|
||
+var_dump($t > 1);
|
||
+echo "$t\n$d\nDone\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(true)
|
||
+%d
|
||
+%a, %d %a %d %d:%d:%d GMT
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/encoding_objects_001.phpt
|
||
@@ -0,0 +1,35 @@
|
||
+--TEST--
|
||
+encoding stream objects
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$d = new HttpDeflateStream;
|
||
+$i = new HttpInflateStream;
|
||
+echo $i->flush($d->flush("Hi "));
|
||
+echo $i->finish($d->finish("there!\n"));
|
||
+echo $i->finish($d->finish("Yo...\n"));
|
||
+
|
||
+$id = $i->update($d->update($pd = file_get_contents(__FILE__)));
|
||
+foreach (glob('*.phpt') as $f) {
|
||
+ $id .= $i->update($d->update($tmp = file_get_contents($f)));
|
||
+ $pd .= $tmp;
|
||
+}
|
||
+$id .= $i->finish($d->finish());
|
||
+
|
||
+var_dump($id == $pd);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Hi there!
|
||
+Yo...
|
||
+bool(true)
|
||
+Done
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/encodings.phpt
|
||
@@ -0,0 +1,44 @@
|
||
+--TEST--
|
||
+encodings
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+skipif(!function_exists('http_deflate'), 'need zlib');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+set_time_limit(0);
|
||
+error_reporting(E_ALL);
|
||
+
|
||
+$s = '';
|
||
+
|
||
+for ($i = 0; $i < 5000; ++$i) {
|
||
+ $s .= chr(rand(0,255));
|
||
+}
|
||
+
|
||
+var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_ZLIB)));
|
||
+var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_GZIP)));
|
||
+var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_RAW)));
|
||
+
|
||
+if (extension_loaded('zlib')) {
|
||
+
|
||
+ $s = "A simple test string, which won't blow up ext/zlib.\n";
|
||
+
|
||
+ ($s == http_inflate(gzencode($s))) or print "GZIP Failed\n";
|
||
+ ($s == http_inflate(gzdeflate($s))) or print "DEFLATE Failed\n";
|
||
+ ($s == http_inflate(gzcompress($s))) or print "COMPRESS Failed\n";
|
||
+
|
||
+ ($s == gzinflate(http_deflate($s, HTTP_DEFLATE_TYPE_RAW))) or print "INFLATE Failed\n";
|
||
+ ($s == gzuncompress(http_deflate($s, HTTP_DEFLATE_TYPE_ZLIB))) or print "UNCOMPRESS Failed\n";
|
||
+}
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(true)
|
||
+bool(true)
|
||
+bool(true)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_031.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+crc32 etag (may fail because PHPs crc32 is actually crc32b)
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', extension_loaded('hash')?'crc32b':'crc32');
|
||
+http_cache_etag();
|
||
+http_send_data("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+Accept-Ranges: bytes
|
||
+ETag: "4e818847"
|
||
+Content-Length: 4
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_032.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+sha1 etag
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', 'SHA1');
|
||
+http_cache_etag();
|
||
+http_send_data("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+Accept-Ranges: bytes
|
||
+ETag: "03cfd743661f07975fa2f1220c5194cbaff48451"
|
||
+Content-Length: 4
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_033.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+md5 etag
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', 'MD5');
|
||
+http_cache_etag();
|
||
+http_send_data("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+Accept-Ranges: bytes
|
||
+ETag: "0bee89b07a248e27c83fc3d5951213c1"
|
||
+Content-Length: 4
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_034.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+ext/hash etag
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+skipif(!extension_loaded('hash'), 'need ext/hash support');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', 'sha256');
|
||
+http_cache_etag();
|
||
+http_send_data("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+Accept-Ranges: bytes
|
||
+ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb"
|
||
+Content-Length: 4
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_041.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+ob crc32 etag (may fail because PHPs crc32 is actually crc32b)
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', extension_loaded('hash')?'crc32b':'crc32');
|
||
+http_cache_etag();
|
||
+print("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+ETag: "4e818847"
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_042.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+ob sha1 etag
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', 'SHA1');
|
||
+http_cache_etag();
|
||
+print("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+ETag: "03cfd743661f07975fa2f1220c5194cbaff48451"
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_043.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+ob md5 etag
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', 'bogus');
|
||
+http_cache_etag();
|
||
+print("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+ETag: "0bee89b07a248e27c83fc3d5951213c1"
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/etag_mode_044.phpt
|
||
@@ -0,0 +1,22 @@
|
||
+--TEST--
|
||
+ob ext/hash etag
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+skipif(!extension_loaded('hash'), 'need ext/hash support');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ini_set('http.etag.mode', 'sha256');
|
||
+http_cache_etag();
|
||
+print("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%a
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb"
|
||
+Content-type: %a
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/exceptions.phpt
|
||
@@ -0,0 +1,53 @@
|
||
+--TEST--
|
||
+exceptions
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+ini_set('http.only_exceptions', true);
|
||
+
|
||
+$e = array(
|
||
+ HTTP_E_RUNTIME => 'Runtime',
|
||
+ HTTP_E_INVALID_PARAM => 'InvalidParam',
|
||
+ HTTP_E_HEADER => 'Header',
|
||
+ HTTP_E_MALFORMED_HEADERS => 'MalformedHeaders',
|
||
+ HTTP_E_REQUEST_METHOD => 'RequestMethod',
|
||
+ HTTP_E_MESSAGE_TYPE => 'MessageType',
|
||
+ HTTP_E_ENCODING => 'Encoding',
|
||
+ HTTP_E_REQUEST => 'Request',
|
||
+ HTTP_E_REQUEST_POOL => 'RequestPool',
|
||
+ HTTP_E_SOCKET => 'Socket',
|
||
+ HTTP_E_RESPONSE => 'Response',
|
||
+ HTTP_E_URL => 'Url',
|
||
+);
|
||
+
|
||
+foreach ($e as $i => $c) {
|
||
+ try {
|
||
+ $n = "Http{$c}Exception";
|
||
+ throw new $n;
|
||
+ } catch (HttpException $x) {
|
||
+ printf("%2d: %s\n", $i, get_class($x));
|
||
+ }
|
||
+}
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+ 1: HttpRuntimeException
|
||
+ 2: HttpInvalidParamException
|
||
+ 3: HttpHeaderException
|
||
+ 4: HttpMalformedHeadersException
|
||
+ 5: HttpRequestMethodException
|
||
+ 6: HttpMessageTypeException
|
||
+ 7: HttpEncodingException
|
||
+ 8: HttpRequestException
|
||
+ 9: HttpRequestPoolException
|
||
+10: HttpSocketException
|
||
+11: HttpResponseException
|
||
+12: HttpUrlException
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/get_request_data_001.phpt
|
||
@@ -0,0 +1,40 @@
|
||
+--TEST--
|
||
+get request data
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--POST--
|
||
+a=b&c=d
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$_SERVER['HTTP_ACCEPT_CHARSET'] = 'iso-8859-1, *';
|
||
+$_SERVER['HTTP_ACCEPT_ENCODING'] = 'none';
|
||
+$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0';
|
||
+$_SERVER['HTTP_HOST'] = 'localhost';
|
||
+
|
||
+$h = http_get_request_headers();
|
||
+ksort($h);
|
||
+print_r($h);
|
||
+var_dump(http_get_request_body());
|
||
+var_dump(http_get_request_body());
|
||
+var_dump(http_get_request_body());
|
||
+var_dump(fread(http_get_request_body_stream(), 4096));
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Array
|
||
+(
|
||
+ [Accept-Charset] => iso-8859-1, *
|
||
+ [Accept-Encoding] => none
|
||
+ [Host] => localhost
|
||
+ [User-Agent] => Mozilla/5.0
|
||
+)
|
||
+string(7) "a=b&c=d"
|
||
+string(7) "a=b&c=d"
|
||
+string(7) "a=b&c=d"
|
||
+string(7) "a=b&c=d"
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/log.inc
|
||
@@ -0,0 +1,23 @@
|
||
+<?php
|
||
+define('_REDIR_LOG', '__r_log');
|
||
+define('_CACHE_LOG', '__c_log');
|
||
+define('_AMETH_LOG', '__m_log');
|
||
+define('_CMPST_LOG', '__a_log');
|
||
+
|
||
+function log_prepare($log)
|
||
+{
|
||
+ is_file($log) and @unlink($log);
|
||
+ switch ($log)
|
||
+ {
|
||
+ case _REDIR_LOG: ini_set('http.log.redirect', _REDIR_LOG); break;
|
||
+ case _CACHE_LOG: ini_set('http.log.cache', _CACHE_LOG); break;
|
||
+ case _AMETH_LOG: ini_set('http.log.allowed_methods', _AMETH_LOG); break;
|
||
+ case _CMPTS_LOG: ini_set('http.log.composite', _CMPST_LOG); break;
|
||
+ }
|
||
+}
|
||
+function log_content($log)
|
||
+{
|
||
+ echo file_get_contents($log);
|
||
+ unlink($log);
|
||
+}
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/match_request_header_001.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+http_match_request_header()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_FOO=bar
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+var_dump(http_match_request_header("Foo", "bar", 1));
|
||
+var_dump(http_match_request_header("fOO", "BAR", 0));
|
||
+var_dump(http_match_request_header("foo", "BAR", 1));
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(true)
|
||
+bool(true)
|
||
+bool(false)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/negotiation_001.phpt
|
||
@@ -0,0 +1,64 @@
|
||
+--TEST--
|
||
+negotiation
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_ACCEPT=application/xml, application/xhtml+xml, text/html ; q = .8
|
||
+HTTP_ACCEPT_LANGUAGE=de-AT,de-DE;q=0.8,en-GB;q=0.3,en-US;q=0.2
|
||
+HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$langs = array(
|
||
+ array('de', 'en', 'es'),
|
||
+);
|
||
+$csets = array(
|
||
+ array('utf-8', 'iso-8859-1'),
|
||
+);
|
||
+$ctype = array(
|
||
+ array('foo/bar', 'application/xhtml+xml', 'text/html')
|
||
+);
|
||
+var_dump(http_negotiate_language($langs[0]));
|
||
+var_dump(http_negotiate_language($langs[0], $lresult));
|
||
+var_dump(http_negotiate_charset($csets[0]));
|
||
+var_dump(http_negotiate_charset($csets[0], $cresult));
|
||
+var_dump(http_negotiate_content_type($ctype[0]));
|
||
+var_dump(http_negotiate_content_type($ctype[0], $tresult));
|
||
+var_dump(http_negotiate_language(array("unknown")));
|
||
+var_dump(http_negotiate_charset(array("unknown")));
|
||
+var_dump(http_negotiate_content_type(array("unknown")));
|
||
+print_r($lresult);
|
||
+print_r($cresult);
|
||
+print_r($tresult);
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(2) "de"
|
||
+string(2) "de"
|
||
+string(10) "iso-8859-1"
|
||
+string(10) "iso-8859-1"
|
||
+string(21) "application/xhtml+xml"
|
||
+string(21) "application/xhtml+xml"
|
||
+string(7) "unknown"
|
||
+string(7) "unknown"
|
||
+string(7) "unknown"
|
||
+Array
|
||
+(
|
||
+ [de] => 900
|
||
+ [en] => 0.27
|
||
+)
|
||
+Array
|
||
+(
|
||
+ [iso-8859-1] => 1000
|
||
+ [utf-8] => 0.7
|
||
+)
|
||
+Array
|
||
+(
|
||
+ [application/xhtml+xml] => 999
|
||
+ [text/html] => 0.8
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/ob_deflatehandler_001.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+ob_deflatehandler
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_ACCEPT_ENCODING=gzip
|
||
+--FILE--
|
||
+<?php
|
||
+ob_start('ob_deflatehandler');
|
||
+echo "-TEST\n";
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%a
|
||
+Content-Encoding: gzip
|
||
+Vary: Accept-Encoding
|
||
+%a
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/ob_inflatehandler_001.phpt
|
||
@@ -0,0 +1,16 @@
|
||
+--TEST--
|
||
+ob_inflatehandler
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+ob_start('ob_inflatehandler');
|
||
+echo http_deflate("TEST\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_cookie_001.phpt
|
||
@@ -0,0 +1,41 @@
|
||
+--TEST--
|
||
+parse cookie
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+var_dump(http_parse_cookie('name="value"; foo="bar\"baz"; hey=got"it ; path=/ ; comment=; expires='.http_date(1).' secure ; httpOnly', 0, array("comment")));
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+object(stdClass)%a {
|
||
+ ["cookies"]=>
|
||
+ array(3) {
|
||
+ ["name"]=>
|
||
+ string(5) "value"
|
||
+ ["foo"]=>
|
||
+ string(7) "bar"baz"
|
||
+ ["hey"]=>
|
||
+ string(6) "got"it"
|
||
+ }
|
||
+ ["extras"]=>
|
||
+ array(1) {
|
||
+ ["comment"]=>
|
||
+ string(0) ""
|
||
+ }
|
||
+ ["flags"]=>
|
||
+ int(32)
|
||
+ ["expires"]=>
|
||
+ int(1)
|
||
+ ["path"]=>
|
||
+ string(1) "/"
|
||
+ ["domain"]=>
|
||
+ string(0) ""
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_cookie_002.phpt
|
||
@@ -0,0 +1,80 @@
|
||
+--TEST--
|
||
+parse cookie
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+var_dump(http_parse_cookie('foo')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo ')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo ;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo ; ')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo=')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo=;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo =')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo =;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo= ')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo= ;')->cookies['foo']);
|
||
+
|
||
+var_dump(http_parse_cookie('foo=1')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo=1;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo=1 ;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo= 1;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo = 1;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo = 1 ;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo=1')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo= 1')->cookies['foo']);
|
||
+
|
||
+var_dump(http_parse_cookie('foo="1"')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo="1" ')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo="1";')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo = "1" ;')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo= "1" ')->cookies['foo']);
|
||
+
|
||
+var_dump(http_parse_cookie('foo=""')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo="\""')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo=" "')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo= "')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo=" ')->cookies['foo']);
|
||
+var_dump(http_parse_cookie('foo= " ')->cookies['foo']);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(0) ""
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(1) "1"
|
||
+string(0) ""
|
||
+string(1) """
|
||
+string(1) " "
|
||
+string(1) """
|
||
+string(1) """
|
||
+string(1) """
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_headers_001.phpt
|
||
@@ -0,0 +1,41 @@
|
||
+--TEST--
|
||
+http_parse_headers()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+print_r(http_parse_headers(
|
||
+"Host: localhost\r\n".
|
||
+"Host: ambigious\r\n".
|
||
+"Nospace:here\r\n".
|
||
+"Muchspace: there \r\n".
|
||
+"Empty:\r\n".
|
||
+"Empty2: \r\n".
|
||
+"Folded: one\r\n".
|
||
+"\ttwo\r\n".
|
||
+" three\r\n\r\n".
|
||
+"stop\r\n"
|
||
+));
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+Array
|
||
+(
|
||
+ [Host] => Array
|
||
+ (
|
||
+ [0] => localhost
|
||
+ [1] => ambigious
|
||
+ )
|
||
+
|
||
+ [Nospace] => here
|
||
+ [Muchspace] => there
|
||
+ [Empty] =>
|
||
+ [Empty2] =>
|
||
+ [Folded] => one
|
||
+ two
|
||
+ three
|
||
+)
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_message_001.phpt
|
||
@@ -0,0 +1,18 @@
|
||
+--TEST--
|
||
+http_parse_message()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkurl('www.google.com');
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), 'need curl support');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+$m = http_parse_message(http_get('http://www.google.com'));
|
||
+echo $m->body;
|
||
+echo "Done\n";
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+<HTML>%aThe document has moved%a</HTML>
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_message_002.phpt
|
||
@@ -0,0 +1,39 @@
|
||
+--TEST--
|
||
+identity encoding trap
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$message =
|
||
+"HTTP/1.1 200 Ok\n".
|
||
+"Transfer-Encoding: identity\n".
|
||
+"Content-Length: 3\n".
|
||
+"Content-Type: text/plain\n\n".
|
||
+"Hi!\n\n\n\n";
|
||
+
|
||
+print_r(http_parse_message($message));
|
||
+
|
||
+echo "Done\n";
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+stdClass Object
|
||
+(
|
||
+ [type] => 2
|
||
+ [httpVersion] => 1.1
|
||
+ [responseCode] => 200
|
||
+ [responseStatus] => Ok
|
||
+ [headers] => Array
|
||
+ (
|
||
+ [Transfer-Encoding] => identity
|
||
+ [Content-Length] => 3
|
||
+ [Content-Type] => text/plain
|
||
+ )
|
||
+
|
||
+ [body] => Hi!
|
||
+ [parentMessage] =>
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_message_003.phpt
|
||
@@ -0,0 +1,31 @@
|
||
+--TEST--
|
||
+content range message
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$message =
|
||
+"HTTP/1.1 200 Ok\n".
|
||
+"Content-Range: bytes: 0-1/5\n\n".
|
||
+"OK\n";
|
||
+
|
||
+$msg = http_parse_message($message);
|
||
+var_dump($msg->body);
|
||
+
|
||
+$message =
|
||
+"HTTP/1.1 200 Ok\n".
|
||
+"Content-Range: bytes 0-1/1\n\n".
|
||
+"X\n";
|
||
+
|
||
+$msg = http_parse_message($message);
|
||
+
|
||
+echo "Done\n";
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(2) "OK"
|
||
+%a Invalid Content-Range header: bytes 0-1/1 in%a
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_message_004.phpt
|
||
@@ -0,0 +1,115 @@
|
||
+--TEST--
|
||
+http_parse_message() recursive
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+
|
||
+echo "-TEST\n";
|
||
+$message =
|
||
+"HEAD / HTTP/1.1
|
||
+Host: www.example.com
|
||
+Accept: */*
|
||
+HTTP/1.1 200 Ok
|
||
+Server: Funky/1.0
|
||
+Content-Length: 10
|
||
+GET / HTTP/1.1
|
||
+Host: www.example.com
|
||
+Accept: */*
|
||
+HTTP/1.1 200 Ok
|
||
+Server: Funky/1.0
|
||
+Content-Length: 10
|
||
+
|
||
+1234567890
|
||
+";
|
||
+
|
||
+var_dump(http_parse_message($message));
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+object(stdClass)%a {
|
||
+ ["type"]=>
|
||
+ int(2)
|
||
+ ["httpVersion"]=>
|
||
+ float(1.1)
|
||
+ ["responseCode"]=>
|
||
+ int(200)
|
||
+ ["responseStatus"]=>
|
||
+ string(2) "Ok"
|
||
+ ["headers"]=>
|
||
+ array(2) {
|
||
+ ["Server"]=>
|
||
+ string(9) "Funky/1.0"
|
||
+ ["Content-Length"]=>
|
||
+ string(2) "10"
|
||
+ }
|
||
+ ["body"]=>
|
||
+ string(10) "1234567890"
|
||
+ ["parentMessage"]=>
|
||
+ object(stdClass)%a {
|
||
+ ["type"]=>
|
||
+ int(1)
|
||
+ ["httpVersion"]=>
|
||
+ float(1.1)
|
||
+ ["requestMethod"]=>
|
||
+ string(3) "GET"
|
||
+ ["requestUrl"]=>
|
||
+ string(1) "/"
|
||
+ ["headers"]=>
|
||
+ array(2) {
|
||
+ ["Host"]=>
|
||
+ string(15) "www.example.com"
|
||
+ ["Accept"]=>
|
||
+ string(3) "*/*"
|
||
+ }
|
||
+ ["body"]=>
|
||
+ string(0) ""
|
||
+ ["parentMessage"]=>
|
||
+ object(stdClass)%a {
|
||
+ ["type"]=>
|
||
+ int(2)
|
||
+ ["httpVersion"]=>
|
||
+ float(1.1)
|
||
+ ["responseCode"]=>
|
||
+ int(200)
|
||
+ ["responseStatus"]=>
|
||
+ string(2) "Ok"
|
||
+ ["headers"]=>
|
||
+ array(2) {
|
||
+ ["Server"]=>
|
||
+ string(9) "Funky/1.0"
|
||
+ ["Content-Length"]=>
|
||
+ string(2) "10"
|
||
+ }
|
||
+ ["body"]=>
|
||
+ string(0) ""
|
||
+ ["parentMessage"]=>
|
||
+ object(stdClass)%a {
|
||
+ ["type"]=>
|
||
+ int(1)
|
||
+ ["httpVersion"]=>
|
||
+ float(1.1)
|
||
+ ["requestMethod"]=>
|
||
+ string(4) "HEAD"
|
||
+ ["requestUrl"]=>
|
||
+ string(1) "/"
|
||
+ ["headers"]=>
|
||
+ array(2) {
|
||
+ ["Host"]=>
|
||
+ string(15) "www.example.com"
|
||
+ ["Accept"]=>
|
||
+ string(3) "*/*"
|
||
+ }
|
||
+ ["body"]=>
|
||
+ string(0) ""
|
||
+ ["parentMessage"]=>
|
||
+ NULL
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_message_005.phpt
|
||
@@ -0,0 +1,60 @@
|
||
+--TEST--
|
||
+http_parse_message() content range header w/(o) =
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+print_r(http_parse_message(
|
||
+"
|
||
+HTTP/1.1 206
|
||
+Server: Funky/1.0
|
||
+Content-Range: bytes: 0-0/100
|
||
+
|
||
+1
|
||
+
|
||
+HTTP/1.1 206
|
||
+Server: Funky/1.0
|
||
+Content-Range: bytes 0-0/100
|
||
+
|
||
+1
|
||
+
|
||
+"
|
||
+));
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+stdClass Object
|
||
+(
|
||
+ [type] => 2
|
||
+ [httpVersion] => 1.1
|
||
+ [responseCode] => 206
|
||
+ [responseStatus] =>
|
||
+ [headers] => Array
|
||
+ (
|
||
+ [Server] => Funky/1.0
|
||
+ [Content-Range] => bytes 0-0/100
|
||
+ )
|
||
+
|
||
+ [body] => 1
|
||
+ [parentMessage] => stdClass Object
|
||
+ (
|
||
+ [type] => 2
|
||
+ [httpVersion] => 1.1
|
||
+ [responseCode] => 206
|
||
+ [responseStatus] =>
|
||
+ [headers] => Array
|
||
+ (
|
||
+ [Server] => Funky/1.0
|
||
+ [Content-Range] => bytes: 0-0/100
|
||
+ )
|
||
+
|
||
+ [body] => 1
|
||
+ [parentMessage] =>
|
||
+ )
|
||
+
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_message_006.phpt
|
||
@@ -0,0 +1,38 @@
|
||
+--TEST--
|
||
+mixed EOL trap
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$message =
|
||
+"HTTP/1.1 200 Ok\n".
|
||
+"Header: Value\r\n".
|
||
+"Connection: close\r\n".
|
||
+"\n".
|
||
+"Bug!";
|
||
+
|
||
+print_r(http_parse_message($message));
|
||
+
|
||
+echo "Done\n";
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+stdClass Object
|
||
+(
|
||
+ [type] => 2
|
||
+ [httpVersion] => 1.1
|
||
+ [responseCode] => 200
|
||
+ [responseStatus] => Ok
|
||
+ [headers] => Array
|
||
+ (
|
||
+ [Header] => Value
|
||
+ [Connection] => close
|
||
+ )
|
||
+
|
||
+ [body] => Bug!
|
||
+ [parentMessage] =>
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/parse_params_001.phpt
|
||
@@ -0,0 +1,75 @@
|
||
+--TEST--
|
||
+http_parse_params
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+var_dump(http_parse_params('text/html; charset=iso-8859-1'));
|
||
+var_dump(http_parse_params('text/html; charset="iso-8859-1"'));
|
||
+var_dump(http_parse_params('attachment; filename="gol;got,a.ext"'));
|
||
+var_dump(http_parse_params('public, must-revalidate, max-age=0'));
|
||
+$p = http_parse_params('a'); var_dump($p->params[0]);
|
||
+$p = http_parse_params('a=b'); var_dump($p->params[0]);
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+object(stdClass)%a {
|
||
+ ["params"]=>
|
||
+ array(2) {
|
||
+ [0]=>
|
||
+ string(9) "text/html"
|
||
+ [1]=>
|
||
+ array(1) {
|
||
+ ["charset"]=>
|
||
+ string(10) "iso-8859-1"
|
||
+ }
|
||
+ }
|
||
+}
|
||
+object(stdClass)%a {
|
||
+ ["params"]=>
|
||
+ array(2) {
|
||
+ [0]=>
|
||
+ string(9) "text/html"
|
||
+ [1]=>
|
||
+ array(1) {
|
||
+ ["charset"]=>
|
||
+ string(10) "iso-8859-1"
|
||
+ }
|
||
+ }
|
||
+}
|
||
+object(stdClass)%a {
|
||
+ ["params"]=>
|
||
+ array(2) {
|
||
+ [0]=>
|
||
+ string(10) "attachment"
|
||
+ [1]=>
|
||
+ array(1) {
|
||
+ ["filename"]=>
|
||
+ string(13) "gol;got,a.ext"
|
||
+ }
|
||
+ }
|
||
+}
|
||
+object(stdClass)%a {
|
||
+ ["params"]=>
|
||
+ array(3) {
|
||
+ [0]=>
|
||
+ string(6) "public"
|
||
+ [1]=>
|
||
+ string(15) "must-revalidate"
|
||
+ [2]=>
|
||
+ array(1) {
|
||
+ ["max-age"]=>
|
||
+ string(1) "0"
|
||
+ }
|
||
+ }
|
||
+}
|
||
+string(1) "a"
|
||
+array(1) {
|
||
+ ["a"]=>
|
||
+ string(1) "b"
|
||
+}
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/persistent_handles_001.phpt
|
||
@@ -0,0 +1,91 @@
|
||
+--TEST--
|
||
+persistent handles
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
|
||
+skipif(!function_exists('zend_thread_id'), "need ZTS build");
|
||
+?>
|
||
+--INI--
|
||
+http.persistent.handles.limit=-1
|
||
+http.persistent.handles.ident=GLOBAL
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+echo "No free handles!\n";
|
||
+foreach (http_persistent_handles_count() as $provider => $idents) {
|
||
+ foreach ((array)$idents as $ident => $counts) {
|
||
+ if (!empty($counts["free"])) {
|
||
+ printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+http_get("http://www.google.com/", null, $info[]);
|
||
+
|
||
+echo "One free request handle within GLOBAL: ";
|
||
+var_dump(http_persistent_handles_count()->http_request["GLOBAL"]["free"]);
|
||
+
|
||
+echo "Reusing request handle: ";
|
||
+http_get("http://www.google.com/", null, $info[]);
|
||
+var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
|
||
+
|
||
+echo "Handles' been cleaned up:\n";
|
||
+http_persistent_handles_clean();
|
||
+print_r(http_persistent_handles_count());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+No free handles!
|
||
+One free request handle within GLOBAL: int(1)
|
||
+Reusing request handle: bool(true)
|
||
+float(%f)
|
||
+float(%f)
|
||
+Handles' been cleaned up:
|
||
+stdClass Object
|
||
+(
|
||
+ [http_request] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+ [http_request_datashare] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+ [http_request_datashare_lock] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+ [http_request_pool] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/persistent_handles_002.phpt
|
||
@@ -0,0 +1,83 @@
|
||
+--TEST--
|
||
+persistent handles
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
|
||
+skipif(function_exists('zend_thread_id'), "need non-ZTS build");
|
||
+?>
|
||
+--INI--
|
||
+http.persistent.handles.limit=-1
|
||
+http.persistent.handles.ident=GLOBAL
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+echo "No free handles!\n";
|
||
+foreach (http_persistent_handles_count() as $provider => $idents) {
|
||
+ foreach ((array)$idents as $ident => $counts) {
|
||
+ if (!empty($counts["free"])) {
|
||
+ printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+http_get("http://www.google.com/", null, $info[]);
|
||
+
|
||
+echo "One free request handle within GLOBAL: ";
|
||
+$h = http_persistent_handles_count();
|
||
+var_dump($h->http_request["GLOBAL"]["free"]);
|
||
+
|
||
+echo "Reusing request handle: ";
|
||
+http_get("http://www.google.com/", null, $info[]);
|
||
+var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
|
||
+
|
||
+echo "Handles' been cleaned up:\n";
|
||
+http_persistent_handles_clean();
|
||
+print_r(http_persistent_handles_count());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+No free handles!
|
||
+One free request handle within GLOBAL: int(1)
|
||
+Reusing request handle: bool(true)
|
||
+float(%f)
|
||
+float(%f)
|
||
+Handles' been cleaned up:
|
||
+stdClass Object
|
||
+(
|
||
+ [http_request] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+ [http_request_datashare] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+ [http_request_pool] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/persistent_handles_003.phpt
|
||
@@ -0,0 +1,62 @@
|
||
+--TEST--
|
||
+persistent handles
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmax(4.4);
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
|
||
+?>
|
||
+--INI--
|
||
+http.persistent.handles.limit=-1
|
||
+http.persistent.handles.ident=GLOBAL
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+echo "No free handles!\n";
|
||
+foreach (http_persistent_handles_count() as $provider => $idents) {
|
||
+ foreach ((array)$idents as $ident => $counts) {
|
||
+ if (!empty($counts["free"])) {
|
||
+ printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+http_get("http://www.google.com/", null, $info[]);
|
||
+
|
||
+echo "One free request handle within GLOBAL: ";
|
||
+$h = http_persistent_handles_count();
|
||
+var_dump($h->http_request["GLOBAL"]["free"]);
|
||
+
|
||
+echo "Reusing request handle: ";
|
||
+http_get("http://www.google.com/", null, $info[]);
|
||
+var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
|
||
+
|
||
+echo "Handles' been cleaned up:\n";
|
||
+http_persistent_handles_clean();
|
||
+print_r(http_persistent_handles_count());
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+No free handles!
|
||
+One free request handle within GLOBAL: int(1)
|
||
+Reusing request handle: bool(true)
|
||
+float(%f)
|
||
+float(%f)
|
||
+Handles' been cleaned up:
|
||
+stdClass Object
|
||
+(
|
||
+ [http_request] => Array
|
||
+ (
|
||
+ [GLOBAL] => Array
|
||
+ (
|
||
+ [used] => 0
|
||
+ [free] => 0
|
||
+ )
|
||
+
|
||
+ )
|
||
+
|
||
+)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/redirect_011.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+http_redirect() with params
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=localhost
|
||
+--FILE--
|
||
+<?php
|
||
+include 'log.inc';
|
||
+log_prepare(_REDIR_LOG);
|
||
+http_redirect('redirect', array('a' => 1, 'b' => 2));
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 302%s
|
||
+X-Powered-By: PHP/%a
|
||
+Location: http://localhost/redirect?a=1&b=2
|
||
+Content-type: %a
|
||
+
|
||
+Redirecting to <a href="http://localhost/redirect?a=1&b=2">http://localhost/redirect?a=1&b=2</a>.
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/redirect_011_logging.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+logging redirects
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=example.com
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+include 'log.inc';
|
||
+log_content(_REDIR_LOG);
|
||
+echo "Done";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a>
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/redirect_012.phpt
|
||
@@ -0,0 +1,27 @@
|
||
+--TEST--
|
||
+http_redirect() with session
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+checkext('session');
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=localhost
|
||
+--FILE--
|
||
+<?php
|
||
+include 'log.inc';
|
||
+log_prepare(_REDIR_LOG);
|
||
+session_start();
|
||
+http_redirect('redirect', array('a' => 1), true);
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 302%s
|
||
+X-Powered-By: PHP/%a
|
||
+Set-Cookie: PHPSESSID=%a; path=/
|
||
+Expires: %a
|
||
+Cache-Control: %a
|
||
+Pragma: %a
|
||
+Location: http://localhost/redirect?a=1&PHPSESSID=%a
|
||
+Content-type: %a
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/redirect_012_logging.phpt
|
||
@@ -0,0 +1,22 @@
|
||
+--TEST--
|
||
+logging redirects
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+checkext("session");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=example.com
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+include 'log.inc';
|
||
+log_content(_REDIR_LOG);
|
||
+echo "Done";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a>
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/redirect_013.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+http_redirect() permanent
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=localhost
|
||
+--FILE--
|
||
+<?php
|
||
+include 'log.inc';
|
||
+log_prepare(_REDIR_LOG);
|
||
+http_redirect('redirect', null, false, HTTP_REDIRECT_PERM);
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 301%s
|
||
+X-Powered-By: PHP/%a
|
||
+Location: http://localhost/redirect
|
||
+Content-type: %a
|
||
+
|
||
+Redirecting to <a href="http://localhost/redirect">http://localhost/redirect</a>.
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/redirect_013_logging.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+logging redirects
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_HOST=example.com
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+include 'log.inc';
|
||
+log_content(_REDIR_LOG);
|
||
+echo "Done";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [301-REDIRECT] Location: http%a <%a>
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/request_cookies.phpt
|
||
@@ -0,0 +1,52 @@
|
||
+--TEST--
|
||
+urlencoded cookies
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$cookies = array("name" => "val=ue");
|
||
+
|
||
+$r = new HttpRequest("http://dev.iworks.at/ext-http/.print_request.php", HTTP_METH_GET, array("cookies" => $cookies));
|
||
+$r->recordHistory = true;
|
||
+$r->send();
|
||
+$r->setOptions(array('encodecookies' => false));
|
||
+$r->send();
|
||
+echo $r->getHistory()->toString(true);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+GET /ext-http/.print_request.php HTTP/1.1
|
||
+User-Agent: %a
|
||
+Host: dev.iworks.at
|
||
+Accept: */*
|
||
+Cookie: name=val%3Due
|
||
+HTTP/1.1 200 OK
|
||
+%a
|
||
+
|
||
+Array
|
||
+(
|
||
+ [name] => val=ue
|
||
+)
|
||
+
|
||
+GET /ext-http/.print_request.php HTTP/1.1
|
||
+User-Agent: %a
|
||
+Host: dev.iworks.at
|
||
+Accept: */*
|
||
+Cookie: name=val=ue;
|
||
+HTTP/1.1 200 OK
|
||
+%a
|
||
+
|
||
+Array
|
||
+(
|
||
+ [name] => val=ue
|
||
+)
|
||
+
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/request_etag.phpt
|
||
@@ -0,0 +1,21 @@
|
||
+--TEST--
|
||
+request etag
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+var_dump(http_get("http://dev.iworks.at/ext-http/etag", array("etag" => '"26ad3a-5-95eb19c0"')));
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(%d) "HTTP/1.1 304 Not Modified
|
||
+Date: %a
|
||
+Server: %a
|
||
+ETag: "26ad3a-5-95eb19c0"
|
||
+"
|
||
+Done
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/request_gzip.phpt
|
||
@@ -0,0 +1,51 @@
|
||
+--TEST--
|
||
+GZIP request
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkurl('dev.iworks.at');
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), 'need curl support');
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+var_dump(http_parse_message(http_get('http://dev.iworks.at/ext-http/.print_request.php?gzip=1', array('compress' => true))));
|
||
+
|
||
+echo "Done\n";
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+object(stdClass)%a {
|
||
+ ["type"]=>
|
||
+ int(2)
|
||
+ ["httpVersion"]=>
|
||
+ float(1.1)
|
||
+ ["responseCode"]=>
|
||
+ int(200)
|
||
+ ["responseStatus"]=>
|
||
+ string(2) "OK"
|
||
+ ["headers"]=>
|
||
+ array(8) {
|
||
+ %a
|
||
+ ["Vary"]=>
|
||
+ string(15) "Accept-Encoding"
|
||
+ ["Content-Length"]=>
|
||
+ string(2) "26"
|
||
+ ["Content-Type"]=>
|
||
+ string(9) "text/html"
|
||
+ ["X-Original-Content-Encoding"]=>
|
||
+ string(4) "gzip"
|
||
+ ["X-Original-Content-Length"]=>
|
||
+ string(2) "51"
|
||
+ }
|
||
+ ["body"]=>
|
||
+ string(26) "Array
|
||
+(
|
||
+ [gzip] => 1
|
||
+)
|
||
+"
|
||
+ ["parentMessage"]=>
|
||
+ NULL
|
||
+}
|
||
+Done
|
||
+
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/request_methods.phpt
|
||
@@ -0,0 +1,144 @@
|
||
+--TEST--
|
||
+request methods
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+for ($i = 0; $i <= HTTP_METH_ACL+1; ++$i) {
|
||
+ var_dump(http_request_method_exists($i));
|
||
+ echo $name = http_request_method_name($i), "\n";
|
||
+ var_dump(http_request_method_exists($name));
|
||
+}
|
||
+
|
||
+for ($i = 0; $i < 5; ++$i) {
|
||
+ $n = http_request_method_register("M$i");
|
||
+ var_dump(http_request_method_exists($n));
|
||
+ var_dump(http_request_method_exists("M$i"));
|
||
+}
|
||
+for ($i = 0; $i < 5; ++$i) {
|
||
+ var_dump(http_request_method_unregister("M$i"));
|
||
+ var_dump(http_request_method_exists("M$i"));
|
||
+ var_dump(http_request_method_exists($i+HTTP_METH_ACL+1));
|
||
+}
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+int(0)
|
||
+UNKNOWN
|
||
+int(0)
|
||
+int(1)
|
||
+GET
|
||
+int(1)
|
||
+int(2)
|
||
+HEAD
|
||
+int(2)
|
||
+int(3)
|
||
+POST
|
||
+int(3)
|
||
+int(4)
|
||
+PUT
|
||
+int(4)
|
||
+int(5)
|
||
+DELETE
|
||
+int(5)
|
||
+int(6)
|
||
+OPTIONS
|
||
+int(6)
|
||
+int(7)
|
||
+TRACE
|
||
+int(7)
|
||
+int(8)
|
||
+CONNECT
|
||
+int(8)
|
||
+int(9)
|
||
+PROPFIND
|
||
+int(9)
|
||
+int(10)
|
||
+PROPPATCH
|
||
+int(10)
|
||
+int(11)
|
||
+MKCOL
|
||
+int(11)
|
||
+int(12)
|
||
+COPY
|
||
+int(12)
|
||
+int(13)
|
||
+MOVE
|
||
+int(13)
|
||
+int(14)
|
||
+LOCK
|
||
+int(14)
|
||
+int(15)
|
||
+UNLOCK
|
||
+int(15)
|
||
+int(16)
|
||
+VERSION-CONTROL
|
||
+int(16)
|
||
+int(17)
|
||
+REPORT
|
||
+int(17)
|
||
+int(18)
|
||
+CHECKOUT
|
||
+int(18)
|
||
+int(19)
|
||
+CHECKIN
|
||
+int(19)
|
||
+int(20)
|
||
+UNCHECKOUT
|
||
+int(20)
|
||
+int(21)
|
||
+MKWORKSPACE
|
||
+int(21)
|
||
+int(22)
|
||
+UPDATE
|
||
+int(22)
|
||
+int(23)
|
||
+LABEL
|
||
+int(23)
|
||
+int(24)
|
||
+MERGE
|
||
+int(24)
|
||
+int(25)
|
||
+BASELINE-CONTROL
|
||
+int(25)
|
||
+int(26)
|
||
+MKACTIVITY
|
||
+int(26)
|
||
+int(27)
|
||
+ACL
|
||
+int(27)
|
||
+int(0)
|
||
+UNKNOWN
|
||
+int(0)
|
||
+int(28)
|
||
+int(28)
|
||
+int(29)
|
||
+int(29)
|
||
+int(30)
|
||
+int(30)
|
||
+int(31)
|
||
+int(31)
|
||
+int(32)
|
||
+int(32)
|
||
+bool(true)
|
||
+int(0)
|
||
+int(0)
|
||
+bool(true)
|
||
+int(0)
|
||
+int(0)
|
||
+bool(true)
|
||
+int(0)
|
||
+int(0)
|
||
+bool(true)
|
||
+int(0)
|
||
+int(0)
|
||
+bool(true)
|
||
+int(0)
|
||
+int(0)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/request_put_data.phpt
|
||
@@ -0,0 +1,22 @@
|
||
+--TEST--
|
||
+http_put_data()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+$data = str_repeat("abc", 6000/* > CURLBUF_SIZE */);
|
||
+$resp = http_put_data("http://dev.iworks.at/ext-http/.print_put.php5", $data);
|
||
+$mess = http_parse_message($resp);
|
||
+var_dump($data === $mess->body);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(true)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_001.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+http_send_data() NIL-NUM range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=-5
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_content_type('text/plain');
|
||
+http_send_data(str_repeat('123abc', 1000));
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Content-Type: text/plain
|
||
+Accept-Ranges: bytes
|
||
+Content-Range: bytes 5995-5999/6000
|
||
+Content-Length: 5
|
||
+
|
||
+23abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_002.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+http_send_data() NUM-NUM range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=5-6
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_content_type('text/plain');
|
||
+http_send_data(str_repeat('123abc', 1000));
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Content-Type: text/plain
|
||
+Accept-Ranges: bytes
|
||
+Content-Range: bytes 5-6/6000
|
||
+Content-Length: 2
|
||
+
|
||
+c1
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_003.phpt
|
||
@@ -0,0 +1,24 @@
|
||
+--TEST--
|
||
+http_send_data() NUM-NIL range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=5981-
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_content_type('text/plain');
|
||
+http_send_data(str_repeat('123abc', 1000));
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Content-Type: text/plain
|
||
+Accept-Ranges: bytes
|
||
+Content-Range: bytes 5981-5999/6000
|
||
+Content-Length: 19
|
||
+
|
||
+c123abc123abc123abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_004.phpt
|
||
@@ -0,0 +1,22 @@
|
||
+--TEST--
|
||
+http_send_data() syntactically invalid range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin(5);
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=123,-wtf ?
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_content_type('text/plain');
|
||
+http_send_data(str_repeat('123abc', 1000));
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%s
|
||
+Content-Type: text/plain
|
||
+Accept-Ranges: bytes
|
||
+Content-Length: 6000
|
||
+
|
||
+123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_005.phpt
|
||
@@ -0,0 +1,17 @@
|
||
+--TEST--
|
||
+http_send_data() oversized range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=5990-6000
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_content_type('text/plain');
|
||
+http_send_data(str_repeat('123abc', 1000));
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 416%a
|
||
\ No newline at end of file
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_006.phpt
|
||
@@ -0,0 +1,38 @@
|
||
+--TEST--
|
||
+http_send_data() multiple ranges
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=0-3, 4-5,9-11
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_content_type('text/plain');
|
||
+http_send_data(str_repeat('123abc', 1000));
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Type: multipart/byteranges; boundary=%d.%d
|
||
+
|
||
+
|
||
+--%d.%d
|
||
+Content-Type: text/plain
|
||
+Content-Range: bytes 0-3/6000
|
||
+
|
||
+123a
|
||
+--%d.%d
|
||
+Content-Type: text/plain
|
||
+Content-Range: bytes 4-5/6000
|
||
+
|
||
+bc
|
||
+--%d.%d
|
||
+Content-Type: text/plain
|
||
+Content-Range: bytes 9-11/6000
|
||
+
|
||
+abc
|
||
+--%d.%d--
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_010.phpt
|
||
@@ -0,0 +1,20 @@
|
||
+--TEST--
|
||
+http_send_data() HTTP_SENDBUF_SIZE long string
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin(5.1);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+http_throttle(0.01, 1);
|
||
+http_send_data('00000000000000000000');
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Length: 20
|
||
+Content-type: %s
|
||
+
|
||
+00000000000000000000
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_data_011.phpt
|
||
@@ -0,0 +1,22 @@
|
||
+--TEST--
|
||
+http_send_data() last modified caching
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin(5.1);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+http_cache_last_modified(-5);
|
||
+http_send_data("abc\n");
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%s
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+Last-Modified: %s, %d %s %d %d:%d:%d GMT
|
||
+Accept-Ranges: bytes
|
||
+Content-Length: 4
|
||
+Content-type: %s
|
||
+
|
||
+abc
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_failed_precond_001.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+http_send() failed precondition
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkver(5.1);
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=0-1
|
||
+HTTP_IF_UNMODIFIED_SINCE=Thu, 01 Jan 1970 00:16:40 GMT
|
||
+--FILE--
|
||
+<?php
|
||
+http_cache_last_modified();
|
||
+http_send_file(__FILE__);
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 412%s
|
||
+X-Powered-By: %s
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+Last-Modified: %s
|
||
+Accept-Ranges: bytes
|
||
+Content-type: text/html
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_file_005.phpt
|
||
@@ -0,0 +1,38 @@
|
||
+--TEST--
|
||
+http_send_file() multiple ranges
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=0-3, 4-5,9-11
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_content_type('text/plain');
|
||
+http_send_file('data.txt');
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Type: multipart/byteranges; boundary=%d.%d
|
||
+
|
||
+
|
||
+--%d.%d
|
||
+Content-Type: text/plain
|
||
+Content-Range: bytes 0-3/1010
|
||
+
|
||
+0123
|
||
+--%d.%d
|
||
+Content-Type: text/plain
|
||
+Content-Range: bytes 4-5/1010
|
||
+
|
||
+45
|
||
+--%d.%d
|
||
+Content-Type: text/plain
|
||
+Content-Range: bytes 9-11/1010
|
||
+
|
||
+901
|
||
+--%d.%d--
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_file_008.phpt
|
||
@@ -0,0 +1,28 @@
|
||
+--TEST--
|
||
+http_send_file()
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin(5.1);
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_file('data.txt');
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Length: 1010
|
||
+Content-type: %s
|
||
+
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_file_009.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+http_send_file() NUM-NUM range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=5-9
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_file('data.txt');
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Range: bytes 5-9/1010
|
||
+Content-Length: 5
|
||
+Content-type: %s
|
||
+
|
||
+56789
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_file_010.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+http_send_file() NIL-NUM range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=-9
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_file('data.txt');
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Range: bytes 1001-1009/1010
|
||
+Content-Length: 9
|
||
+Content-type: %s
|
||
+
|
||
+23456789
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_file_011.phpt
|
||
@@ -0,0 +1,23 @@
|
||
+--TEST--
|
||
+http_send_file() NUM-NIL range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=1000-
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_file('data.txt');
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Range: bytes 1000-1009/1010
|
||
+Content-Length: 10
|
||
+Content-type: %s
|
||
+
|
||
+123456789
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_file_012.phpt
|
||
@@ -0,0 +1,30 @@
|
||
+--TEST--
|
||
+http_send_file() syntactically invalid range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin(5.1);
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=xxx
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_file('data.txt');
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-Length: 1010
|
||
+Content-type: %s
|
||
+
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_file_013.phpt
|
||
@@ -0,0 +1,19 @@
|
||
+--TEST--
|
||
+http_send_file() oversized range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=-1111
|
||
+--FILE--
|
||
+<?php
|
||
+http_send_file('data.txt');
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 416
|
||
+X-Powered-By: PHP/%s
|
||
+Accept-Ranges: bytes
|
||
+Content-type: %s
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_ifrange_001.phpt
|
||
@@ -0,0 +1,27 @@
|
||
+--TEST--
|
||
+http_send() If-Range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=0-1
|
||
+HTTP_IF_RANGE="abc"
|
||
+--FILE--
|
||
+<?php
|
||
+http_cache_etag('abc');
|
||
+http_send_file(__FILE__);
|
||
+?>
|
||
+--EXPECTF--
|
||
+Status: 206%s
|
||
+X-Powered-By: %s
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+ETag: "abc"
|
||
+Accept-Ranges: bytes
|
||
+Content-Range: bytes 0-1/%d
|
||
+Content-Length: 2
|
||
+Content-type: text/html
|
||
+
|
||
+<?
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/send_ifrange_003.phpt
|
||
@@ -0,0 +1,25 @@
|
||
+--TEST--
|
||
+http_send() If-Range
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkcgi();
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--ENV--
|
||
+HTTP_RANGE=bytes=0-1
|
||
+HTTP_IF_RANGE="abcd"
|
||
+--FILE--
|
||
+<?php
|
||
+http_cache_etag('abc');
|
||
+http_send_file(__FILE__);
|
||
+?>
|
||
+--EXPECTF--
|
||
+X-Powered-By: %s
|
||
+Cache-Control: private, must-revalidate, max-age=0
|
||
+ETag: "abc"
|
||
+Accept-Ranges: bytes
|
||
+Content-Length: %d
|
||
+Content-type: text/html
|
||
+
|
||
+%a
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/skip.inc
|
||
@@ -0,0 +1,15 @@
|
||
+<?php
|
||
+defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
|
||
+if (!function_exists('fprintf')) {
|
||
+ function fprintf(){ $a=func_get_args(); $s=array_shift($a); return fwrite($s, call_user_func_array('sprintf',$a)); }
|
||
+}
|
||
+function skipif($if, $skip) { if ($if) { fprintf(STDOUT, "skip $skip"); exit(); }}
|
||
+function checkcgi() { skipif(!strncasecmp('CLI', PHP_SAPI, 3), 'need CGI SAPI'); }
|
||
+function checkext($ext) { skipif(!extension_loaded($ext), "need ext/$ext"); }
|
||
+function checkmin($ver) { skipif(version_compare(PHP_VERSION, $ver) < 0, sprintf("need PHP >= v%s",$ver)); }
|
||
+function checkmax($ver) { skipif(version_compare(PHP_VERSION, $ver) > 0, sprintf("need PHP <= v%s",$ver)); }
|
||
+function checkurl($url) { skipif(!@fsockopen($url, 80), "$url not responsive"); }
|
||
+function checkcls($cls) { skipif(!class_exists($cls), "need class $cls"); }
|
||
+function checkver($ver) { checkmin($ver); }
|
||
+checkext('http');
|
||
+?>
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/stream_filters_001.phpt
|
||
@@ -0,0 +1,45 @@
|
||
+--TEST--
|
||
+stream filters
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+define('F', 'http.test_stream_filters');
|
||
+
|
||
+$f = fopen(F, 'w');
|
||
+stream_filter_append($f, 'http.chunked_encode');
|
||
+
|
||
+fwrite($f, "Here ");
|
||
+fwrite($f, "we");
|
||
+fwrite($f, " go!\n");
|
||
+fclose($f);
|
||
+
|
||
+var_dump(file_get_contents(F));
|
||
+
|
||
+$f = fopen(F, 'r');
|
||
+stream_filter_append($f, 'http.chunked_decode');
|
||
+var_dump(fread($f, 256));
|
||
+fclose($f);
|
||
+
|
||
+unlink(F);
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+string(30) "5
|
||
+Here
|
||
+2
|
||
+we
|
||
+5
|
||
+ go!
|
||
+
|
||
+0
|
||
+"
|
||
+string(12) "Here we go!
|
||
+"
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/stream_filters_002.phpt
|
||
@@ -0,0 +1,50 @@
|
||
+--TEST--
|
||
+gzip stream filters
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkver(5);
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+
|
||
+echo "-TEST\n";
|
||
+
|
||
+$d = file_get_contents(__FILE__);
|
||
+$n = tempnam(dirname(__FILE__), 'hsf');
|
||
+
|
||
+$f = fopen($n, 'wb');
|
||
+stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_GZIP);
|
||
+fwrite($f, $d);
|
||
+fflush($f);
|
||
+fwrite($f, $d);
|
||
+fclose($f);
|
||
+var_dump($d.$d == http_inflate(file_get_contents($n)));
|
||
+
|
||
+$f = fopen($n, 'wb');
|
||
+stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE);
|
||
+fwrite($f, $d);
|
||
+fflush($f);
|
||
+fwrite($f, $d);
|
||
+fclose($f);
|
||
+var_dump($d.$d == http_inflate(file_get_contents($n)));
|
||
+
|
||
+$f = fopen($n, 'wb');
|
||
+stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_RAW);
|
||
+fwrite($f, $d);
|
||
+fflush($f);
|
||
+fwrite($f, $d);
|
||
+fclose($f);
|
||
+var_dump($d.$d == http_inflate(file_get_contents($n)));
|
||
+
|
||
+unlink($n);
|
||
+
|
||
+echo "Done\n";
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+bool(true)
|
||
+bool(true)
|
||
+bool(true)
|
||
+Done
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/stream_filters_003.phpt
|
||
@@ -0,0 +1,42 @@
|
||
+--TEST--
|
||
+stream filter fun
|
||
+--SKIPIF--
|
||
+<?php
|
||
+include 'skip.inc';
|
||
+checkmin("5.2.5");
|
||
+skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
|
||
+?>
|
||
+--FILE--
|
||
+<?php
|
||
+echo "-TEST\n";
|
||
+
|
||
+define('OUT', fopen('php://output', 'w'));
|
||
+
|
||
+stream_filter_append(OUT, 'http.chunked_encode');
|
||
+stream_filter_append(OUT, 'http.deflate');
|
||
+stream_filter_append(OUT, 'http.chunked_encode');
|
||
+stream_filter_append(OUT, 'http.deflate');
|
||
+stream_filter_append(OUT, 'http.inflate');
|
||
+stream_filter_append(OUT, 'http.chunked_decode');
|
||
+stream_filter_append(OUT, 'http.inflate');
|
||
+stream_filter_append(OUT, 'http.chunked_decode');
|
||
+
|
||
+$text = <<<SOME_TEXT
|
||
+This is some stream filter fun; we'll see if it bails out or not.
|
||
+The text should come out at the other end of the stream exactly like written to it.
|
||
+Go figure!
|
||
+SOME_TEXT;
|
||
+
|
||
+srand(time());
|
||
+foreach (str_split($text, 5) as $part) {
|
||
+ fwrite(OUT, $part);
|
||
+ if (rand(0, 1)) {
|
||
+ fflush(OUT);
|
||
+ }
|
||
+}
|
||
+?>
|
||
+--EXPECTF--
|
||
+%aTEST
|
||
+This is some stream filter fun; we'll see if it bails out or not.
|
||
+The text should come out at the other end of the stream exactly like written to it.
|
||
+Go figure!
|
||
--- /dev/null
|
||
+++ b/ext/http/tests/urls.txt
|
||
@@ -0,0 +1,49 @@
|
||
+http://www.microsoft.com
|
||
+http://www.opensource.org
|
||
+http://www.google.com
|
||
+http://www.yahoo.com
|
||
+http://www.ibm.com
|
||
+http://www.mysql.com
|
||
+http://www.oracle.com
|
||
+http://www.ripe.net
|
||
+http://www.iana.org
|
||
+http://www.amazon.com
|
||
+http://www.netcraft.com
|
||
+http://www.heise.de
|
||
+http://www.chip.de
|
||
+http://www.ca.com
|
||
+http://www.cnet.com
|
||
+http://www.news.com
|
||
+http://www.cnn.com
|
||
+http://www.wikipedia.org
|
||
+http://www.dell.com
|
||
+http://www.hp.com
|
||
+http://www.cert.org
|
||
+http://www.mit.edu
|
||
+http://www.nist.gov
|
||
+http://www.ebay.com
|
||
+http://www.playstation.com
|
||
+http://www.uefa.com
|
||
+http://www.ieee.org
|
||
+http://www.apple.com
|
||
+http://www.sony.com
|
||
+http://www.symantec.com
|
||
+http://www.zdnet.com
|
||
+http://www.fujitsu.com
|
||
+http://www.supermicro.com
|
||
+http://www.hotmail.com
|
||
+http://www.ecma.com
|
||
+http://www.bbc.co.uk
|
||
+http://news.google.com
|
||
+http://www.foxnews.com
|
||
+http://www.msn.com
|
||
+http://www.wired.com
|
||
+http://www.sky.com
|
||
+http://www.usatoday.com
|
||
+http://www.cbs.com
|
||
+http://www.nbc.com
|
||
+http://slashdot.org
|
||
+http://www.bloglines.com
|
||
+http://www.techweb.com
|
||
+http://www.newslink.org
|
||
+http://www.un.org
|
||
\ No newline at end of file
|