4 +HTTP extension for PHP
7 +++ b/ext/http/KnownIssues.txt
11 +$Id: KnownIssues.txt 292753 2009-12-29 12:30:43Z mike $
14 + HttpResponse::getHeader() does not work with Apache2 SAPIs.
15 + Using an encoding stream filter on a stream you read from doesn't work.
18 + If you keep getting "SSL connect error" when trying to issue
19 + requests, try another (newer) libeay32.dll/ssleay32.dll pair.
22 + Our http_urlencode_hash() does not differentiate between prefixes
23 + for numeric or string keys.
24 + Inflating raw deflated data causes a re-initialization of the inflate
25 + stream where the corresponding window bits are modified to tell libz
26 + to not check for zlib header bytes. This is not preventable AFAICS.
27 + LFS dependant parts of libcurl are left out because of off_t,
28 + respectively off64_t confusion.
29 + Persistent handles and "cookiestore" request option do interfere,
30 + as libcurl saves the cookies to the file on curl_easy_destroy(),
31 + cookies are not saved until the CURL handle will be recycled.
32 + Thus one would either need to
33 + * run PHP with http.persistent.handles.limit = 0
34 + * call http_persistent_handles_clean() every request
35 + * call $HttpRequest->flushCookies(), which is available
36 + since libcurl v7.17.1 and does not work with the
38 + Anyway, none of these options is really perfect.
39 + HTTP and Proxy authentication information (username/password) can not be
40 + unset with NULL prior libcurl v7.19.6 and separate options for setting
41 + username and password--which work--are only available since v7.19.6.
43 +++ b/ext/http/LICENSE
45 +Copyright (c) 2004-2010, Michael Wallner <mike@iworks.at>.
48 +Redistribution and use in source and binary forms, with or without
49 +modification, are permitted provided that the following conditions are met:
51 + * Redistributions of source code must retain the above copyright notice,
52 + this list of conditions and the following disclaimer.
53 + * Redistributions in binary form must reproduce the above copyright
54 + notice, this list of conditions and the following disclaimer in the
55 + documentation and/or other materials provided with the distribution.
57 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
58 +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
60 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
61 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
63 +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
64 +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65 +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
66 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 +===============================================================================
70 +The date parser in file http_date_api.c is derived from the implementation
71 +found in the original libcurl source, licensed under the following conditions:
73 +Copyright (c) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>.
76 +Permission to use, copy, modify, and distribute this software for any purpose
77 +with or without fee is hereby granted, provided that the above copyright
78 +notice and this permission notice appear in all copies.
80 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
82 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
83 +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
84 +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
85 +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
86 +OR OTHER DEALINGS IN THE SOFTWARE.
88 +Except as contained in this notice, the name of a copyright holder shall not
89 +be used in advertising or otherwise to promote the sale, use or other dealings
90 +in this Software without prior written authorization of the copyright holder.
93 +++ b/ext/http/Makefile.frag
95 +# vim: noet ts=1 sw=1
97 +phpincludedir=$(prefix)/include/php
99 +install-http: install install-http-headers
101 +install-http-headers:
102 + @echo "Installing HTTP headers: $(INSTALL_ROOT)$(phpincludedir)/ext/http/"
103 + @$(mkinstalldirs) $(INSTALL_ROOT)$(phpincludedir)/ext/http
104 + @for f in $(PHP_HTTP_HEADERS); do \
105 + if test -f "$(top_srcdir)/$$f"; then \
106 + $(INSTALL_DATA) $(top_srcdir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
107 + elif test -f "$(top_builddir)/$$f"; then \
108 + $(INSTALL_DATA) $(top_builddir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
109 + elif test -f "$(top_srcdir)/ext/http/$$f"; then \
110 + $(INSTALL_DATA) $(top_srcdir)/ext/http/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
111 + elif test -f "$(top_builddir)/ext/http/$$f"; then \
112 + $(INSTALL_DATA) $(top_builddir)/ext/http/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \
119 +++ b/ext/http/ThanksTo.txt
123 +$Id: ThanksTo.txt 275653 2009-02-12 13:11:05Z mike $
125 +People who repeatedly reported issues with this extension in a manner
126 +so they could be fixed in a reasonable way, or suggested useful features
127 +to implement, in alphabetical order:
129 + Ilia Alshanetsky (ilia at php dot net)
130 + Petr Czaderna (petr at hroch dot info)
131 + David James (james82 at gmail dot com)
132 + Thomas Landro Johnsen (thomas dot l dot johnsen at gmail dot com)
133 + Clay Loveless (clay at killersoft dot com)
134 + Felipe Pena (felipe at php dot net)
135 + David Sklar (sklar at sklar dot com)
136 + Travis Swicegood (travis at mashery dot com)
137 + Alexey Zakhlestin (indeyets at gmail dot com)
138 + Alexander Zhuravlev (zaa at zaa dot pp dot ru)
142 +++ b/ext/http/config.m4
144 +dnl phpize stub of config9.m4 for pecl/http
145 +dnl $Id: config.m4 214417 2006-06-07 21:05:34Z mike $
146 +dnl vim: noet ts=1 sw=1
148 +sinclude(config9.m4)
150 +++ b/ext/http/config.w32
152 +// config.w32 for pecl/http
153 +// $Id: config.w32 287971 2009-09-02 14:36:08Z pajoye $
155 +ARG_ENABLE("http", "whether to enable extended HTTP support", "no");
157 +function check_for_main_ext(ext, header)
160 + header = "php_"+ ext +".h";
163 + /* When in configure, we're always in the root of PHP source */
164 + var ext_path = "ext\\" + ext;
166 + STDOUT.Write("Checking for ext/"+ ext +" ... ");
168 + if (FSO.FileExists(ext_path + "\\" + header)) {
169 + STDOUT.WriteLine(ext_path);
173 + STDOUT.WriteLine("<not found>");
177 +function check_for_pecl_ext(ext, header)
180 + header = "php_"+ ext +".h";
184 + var s = ext +"\\"+ header;
186 + STDOUT.Write("Checking for pecl/"+ ext +" ... ");
187 + if ( (g = glob(configure_module_dirname +"\\..\\"+ s)) ||
188 + (g = glob(configure_module_dirname +"\\..\\..\\..\\pecl\\"+ s))) {
189 + var f = g[0].substr(0, g[0].length - header.length - 1);
190 + STDOUT.WriteLine(f);
193 + STDOUT.WriteLine("<not found>");
197 +if (PHP_HTTP != "no") {
200 + "missing.c http.c http_functions.c http_exception_object.c "+
201 + "http_util_object.c http_message_object.c http_requestpool_object.c "+
202 + "http_request_object.c http_response_object.c "+
203 + "http_api.c http_cache_api.c http_request_pool_api.c "+
204 + "http_request_api.c http_date_api.c http_headers_api.c "+
205 + "http_message_api.c http_send_api.c http_url_api.c "+
206 + "http_info_api.c http_request_method_api.c http_encoding_api.c "+
207 + "http_filter_api.c http_request_body_api.c http_querystring_object.c "+
208 + "http_deflatestream_object.c http_inflatestream_object.c "+
209 + "http_cookie_api.c http_querystring_api.c http_request_datashare_api.c "+
210 + "http_requestdatashare_object.c http_request_info.c http_persistent_handle_api.c",
212 + "/I\"" + configure_module_dirname + "/phpstr\"");
213 + ADD_SOURCES(configure_module_dirname + "/phpstr", "phpstr.c", "http");
214 + AC_DEFINE("HAVE_HTTP", 1, "Have extended HTTP support");
215 + AC_DEFINE("HTTP_SHARED_DEPS", 1, "Depend on shared extensions");
217 + AC_DEFINE("HAVE_GETHOSTNAME", 1);
218 + AC_DEFINE("HAVE_GETSERVBYPORT", 1);
219 + AC_DEFINE("HAVE_GETSERVBYNAME", 1);
221 + if (PHP_DEBUG != "no") {
222 + ADD_FLAG("CFLAGS_HTTP", "/W3");
225 + if (CHECK_HEADER_ADD_INCLUDE('zlib.h', 'CFLAGS_HTTP', '..\\zlib;' + php_usual_include_suspects)) {
226 + AC_DEFINE('HTTP_HAVE_ZLIB', 1, "Have zlib library");
227 + ADD_FLAG("LDFLAGS_HTTP", "/FORCE:MULTIPLE");
229 + WARNING("zlib encoding functions not enabled; libraries and headers not found");
232 + if (typeof(PHP_HASH) != "undefined" && PHP_HASH != "no") {
235 + if ((f = check_for_pecl_ext("hash")) || (f = check_for_main_ext("hash"))) {
236 + ADD_FLAG("CFLAGS_HTTP", '/I "' + f + '" /DHTTP_HAVE_PHP_HASH_H=1');
237 + ADD_EXTENSION_DEP("http", "hash", true);
241 + if (PHP_SESSION != "no") {
242 + ADD_EXTENSION_DEP("http", "session", true);
245 + if (PHP_ICONV != "no") {
246 + ADD_EXTENSION_DEP("http", "iconv", true);
249 + CURL_LIB="libcurl_a.lib;libcurl.lib;" + (PHP_DEBUG != "no" ? "libcurld.lib":"libcurl.lib");
250 + if (CHECK_HEADER_ADD_INCLUDE("curl/curl.h", "CFLAGS_HTTP") &&
251 + CHECK_HEADER_ADD_INCLUDE("openssl/crypto.h", "CFLAGS_HTTP") &&
252 + CHECK_LIB(CURL_LIB, "http", PHP_HTTP) &&
253 + CHECK_LIB("ssleay32.lib", "http", PHP_HTTP) &&
254 + CHECK_LIB("libeay32.lib", "http", PHP_HTTP) &&
255 + CHECK_LIB("zlib.lib;zlib_a.lib", "http", PHP_HTTP) &&
256 + CHECK_LIB("winmm.lib", "http", PHP_HTTP)) {
257 + AC_DEFINE("HTTP_HAVE_CURL", 1, "Have CURL library");
258 + AC_DEFINE("HTTP_HAVE_SSL", 1, "Have SSL");
259 + AC_DEFINE("HAVE_CURL_MULTI_STRERROR", 1, "");
260 + AC_DEFINE("HAVE_CURL_SHARE_STRERROR", 1, "");
261 + AC_DEFINE("HAVE_CURL_EASY_STRERROR", 1, "");
262 + AC_DEFINE("HAVE_CURL_EASY_RESET", 1, "");
263 + AC_DEFINE("HAVE_CURL_GETFORMDATA", 1, "");
264 + AC_DEFINE("HAVE_CURL_FORMGET", 1, "");
265 + AC_DEFINE("HAVE_CURL_MULTI_SETOPT", 1, "");
266 + AC_DEFINE("HAVE_CURL_MULTI_TIMEOUT", 1, "");
268 + WARNING("curl convenience functions not enabled; libraries and headers not found");
271 +// MAGIC_LIB = PHP_DEBUG != "no" ? "libmagic-staticd.lib":"libmagic-static.lib";
272 +// if (CHECK_HEADER_ADD_INCLUDE("magic.h", "CFLAGS_HTTP") &&
273 +// CHECK_LIB(MAGIC_LIB, "http", PHP_HTTP)) {
274 +// AC_DEFINE("HTTP_HAVE_MAGIC", 1, "Have magic library");
275 +// AC_DEFINE("USE_MAGIC_STATIC", "", "");
277 +// WARNING("content type guessing not enabled; libraries and headers not found");
282 +++ b/ext/http/config9.m4
284 +dnl config.m4 for pecl/http
285 +dnl $Id: config9.m4 242664 2007-09-18 19:13:37Z mike $
286 +dnl vim: noet ts=1 sw=1
288 +PHP_ARG_ENABLE([http], [whether to enable extended HTTP support],
289 +[ --enable-http Enable extended HTTP support])
290 +PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared],
291 +[ --with-http-shared-deps
292 + HTTP: disable to not depend on extensions like hash,
293 + iconv and session (when built shared)], $PHP_HTTP, $PHP_HTTP)
294 +PHP_ARG_WITH([http-curl-requests], [whether to enable cURL HTTP request support],
295 +[ --with-http-curl-requests[=LIBCURLDIR]
296 + HTTP: with cURL request support], $PHP_HTTP, $PHP_HTTP)
297 +PHP_ARG_WITH([http-curl-libevent], [whether to enable libevent support fur cURL],
298 +[ --with-http-curl-libevent[=LIBEVENTDIR]
299 + HTTP: libevent install directory], $PHP_HTTP_CURL_REQUESTS, "")
300 +PHP_ARG_WITH([http-zlib-compression], [whether to enable zlib encodings support],
301 +[ --with-http-zlib-compression[=LIBZDIR]
302 + HTTP: with zlib encodings support], $PHP_HTTP, $PHP_HTTP)
303 +PHP_ARG_WITH([http-magic-mime], [whether to enable response content type guessing],
304 +[ --with-http-magic-mime[=LIBMAGICDIR]
305 + HTTP: with magic mime response content type guessing], "no", "no")
307 +if test "$PHP_HTTP" != "no"; then
309 + ifdef([AC_PROG_EGREP], [
312 + AC_CHECK_PROG(EGREP, egrep, egrep)
314 + ifdef([AC_PROG_SED], [
317 + ifdef([LT_AC_PROG_SED], [
320 + AC_CHECK_PROG(SED, sed, sed)
326 + if test "$PHP_HTTP_SHARED_DEPS" != "no"; then
327 + AC_DEFINE([HTTP_SHARED_DEPS], [1], [ ])
329 + AC_DEFINE([HTTP_SHARED_DEPS], [0], [ ])
333 + dnl HTTP_SHARED_DEP(name[, code-if-yes[, code-if-not]])
335 + AC_DEFUN([HTTP_SHARED_DEP], [
337 + haveext=$[HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)
339 + AC_MSG_CHECKING([whether to add a dependency on ext/$extname])
340 + if test "$PHP_HTTP_SHARED_DEPS" = "no"; then
341 + AC_MSG_RESULT([no])
343 + elif test "$haveext"; then
344 + AC_MSG_RESULT([yes])
345 + ifdef([PHP_ADD_EXTENSION_DEP], [
346 + PHP_ADD_EXTENSION_DEP([http], $1, true)
350 + AC_MSG_RESULT([no])
356 + dnl HTTP_HAVE_PHP_EXT(name[, code-if-yes[, code-if-not]])
358 + AC_DEFUN([HTTP_HAVE_PHP_EXT], [
360 + haveext=$[PHP_]translit($1,a-z_-,A-Z__)
362 + AC_MSG_CHECKING([for ext/$extname support])
363 + if test -x "$PHP_EXECUTABLE"; then
364 + grepext=`$PHP_EXECUTABLE -m | $EGREP ^$extname\$`
365 + if test "$grepext" = "$extname"; then
366 + [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=1
367 + AC_MSG_RESULT([yes])
370 + [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=
371 + AC_MSG_RESULT([no])
374 + elif test "$haveext" != "no" && test "x$haveext" != "x"; then
375 + [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=1
376 + AC_MSG_RESULT([yes])
379 + [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=
380 + AC_MSG_RESULT([no])
388 + if test "x$PHP_LIBDIR" = "x"; then
395 + AC_CHECK_HEADERS([netdb.h unistd.h])
396 + PHP_CHECK_FUNC(gethostname, nsl)
397 + PHP_CHECK_FUNC(getdomainname, nsl)
398 + PHP_CHECK_FUNC(getservbyport, nsl)
399 + PHP_CHECK_FUNC(getservbyname, nsl)
404 + if test "$PHP_HTTP_ZLIB_COMPRESSION" != "no"; then
405 + AC_MSG_CHECKING([for zlib.h])
407 + for i in "$PHP_HTTP_ZLIB_COMPRESSION" "$PHP_ZLIB_DIR" "$PHP_ZLIB" /usr/local /usr /opt; do
408 + if test -f "$i/include/zlib.h"; then
413 + if test "x$ZLIB_DIR" = "x"; then
414 + AC_MSG_RESULT([not found])
415 + AC_MSG_ERROR([could not find zlib.h])
417 + AC_MSG_RESULT([found in $ZLIB_DIR])
418 + AC_MSG_CHECKING([for zlib version >= 1.2.0.4])
419 + ZLIB_VERSION=`$EGREP "define ZLIB_VERSION" $ZLIB_DIR/include/zlib.h | $SED -e 's/[[^0-9\.]]//g'`
420 + AC_MSG_RESULT([$ZLIB_VERSION])
421 + if test `echo $ZLIB_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*1000000 + $2*10000 + $3*100 + $4}'` -lt 1020004; then
422 + AC_MSG_ERROR([libz version greater or equal to 1.2.0.4 required])
424 + PHP_ADD_INCLUDE($ZLIB_DIR/include)
425 + PHP_ADD_LIBRARY_WITH_PATH(z, $ZLIB_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
426 + AC_DEFINE([HTTP_HAVE_ZLIB], [1], [Have zlib support])
434 + if test "$PHP_HTTP_CURL_REQUESTS" != "no"; then
435 + AC_MSG_CHECKING([for curl/curl.h])
437 + for i in "$PHP_HTTP_CURL_REQUESTS" /usr/local /usr /opt; do
438 + if test -f "$i/include/curl/curl.h"; then
443 + if test "x$CURL_DIR" = "x"; then
444 + AC_MSG_RESULT([not found])
445 + AC_MSG_ERROR([could not find curl/curl.h])
447 + AC_MSG_RESULT([found in $CURL_DIR])
450 + AC_MSG_CHECKING([for curl-config])
452 + for i in "$CURL_DIR/bin/curl-config" "$CURL_DIR/curl-config" `which curl-config`; do
453 + if test -x "$i"; then
458 + if test "x$CURL_CONFIG" = "x"; then
459 + AC_MSG_RESULT([not found])
460 + AC_MSG_ERROR([could not find curl-config])
462 + AC_MSG_RESULT([found: $CURL_CONFIG])
465 + dnl Debian stable has currently 7.13.2 (this is not a typo)
466 + AC_MSG_CHECKING([for curl version >= 7.12.3])
467 + CURL_VERSION=`$CURL_CONFIG --version | $SED -e 's/[[^0-9\.]]//g'`
468 + AC_MSG_RESULT([$CURL_VERSION])
469 + if test `echo $CURL_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*10000 + $2*100 + $3}'` -lt 71203; then
470 + AC_MSG_ERROR([libcurl version greater or equal to 7.12.3 required])
477 + save_INCLUDES="$INCLUDES"
481 + save_CFLAGS="$CFLAGS"
482 + CFLAGS=`$CURL_CONFIG --cflags`
483 + save_LDFLAGS="$LDFLAGS"
484 + LDFLAGS=`$CURL_CONFIG --libs`
485 + LDFLAGS="$LDFLAGS $ld_runpath_switch$CURL_DIR/$PHP_LIBDIR"
487 + AC_MSG_CHECKING([for SSL support in libcurl])
488 + CURL_SSL=`$CURL_CONFIG --feature | $EGREP SSL`
489 + if test "$CURL_SSL" = "SSL"; then
490 + AC_MSG_RESULT([yes])
491 + AC_DEFINE([HTTP_HAVE_SSL], [1], [ ])
493 + AC_MSG_CHECKING([for openssl support in libcurl])
495 + #include <curl/curl.h>
496 + int main(int argc, char *argv[]) {
497 + curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
498 + if (data && data->ssl_version && *data->ssl_version) {
499 + const char *ptr = data->ssl_version;
500 + while(*ptr == ' ') ++ptr;
501 + return strncasecmp(ptr, "OpenSSL", sizeof("OpenSSL")-1);
506 + AC_MSG_RESULT([yes])
507 + AC_CHECK_HEADER([openssl/crypto.h], [
508 + AC_DEFINE([HTTP_HAVE_OPENSSL], [1], [ ])
511 + AC_MSG_RESULT([no])
513 + AC_MSG_RESULT([no])
516 + AC_MSG_CHECKING([for gnutls support in libcurl])
518 + #include <curl/curl.h>
519 + int main(int argc, char *argv[]) {
520 + curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
521 + if (data && data->ssl_version && *data->ssl_version) {
522 + const char *ptr = data->ssl_version;
523 + while(*ptr == ' ') ++ptr;
524 + return strncasecmp(ptr, "GnuTLS", sizeof("GnuTLS")-1);
529 + AC_MSG_RESULT([yes])
530 + AC_CHECK_HEADER([gcrypt.h], [
531 + AC_DEFINE([HTTP_HAVE_GNUTLS], [1], [ ])
534 + AC_MSG_RESULT([no])
536 + AC_MSG_RESULT([no])
539 + AC_MSG_RESULT([no])
542 + INCLUDES="$save_INCLUDES"
544 + CFLAGS="$save_CFLAGS"
545 + LDFLAGS="$save_LDFLAGS"
547 + dnl end compile tests
549 + AC_MSG_CHECKING([for bundled SSL CA info])
551 + for i in `$CURL_CONFIG --ca` "/etc/ssl/certs/ca-certificates.crt"; do
552 + if test -f "$i"; then
557 + if test "x$CURL_CAINFO" = "x"; then
558 + AC_MSG_RESULT([not found])
560 + AC_MSG_RESULT([$CURL_CAINFO])
561 + AC_DEFINE_UNQUOTED([HTTP_CURL_CAINFO], ["$CURL_CAINFO"], [path to bundled SSL CA info])
564 + PHP_ADD_INCLUDE($CURL_DIR/include)
565 + PHP_ADD_LIBRARY_WITH_PATH(curl, $CURL_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
566 + PHP_EVAL_LIBLINE(`$CURL_CONFIG --libs`, HTTP_SHARED_LIBADD)
567 + AC_DEFINE([HTTP_HAVE_CURL], [1], [Have cURL support])
569 + PHP_CHECK_LIBRARY(curl, curl_share_strerror,
570 + [AC_DEFINE([HAVE_CURL_SHARE_STRERROR], [1], [ ])], [ ],
571 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
573 + PHP_CHECK_LIBRARY(curl, curl_multi_strerror,
574 + [AC_DEFINE([HAVE_CURL_MULTI_STRERROR], [1], [ ])], [ ],
575 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
577 + PHP_CHECK_LIBRARY(curl, curl_easy_strerror,
578 + [AC_DEFINE([HAVE_CURL_EASY_STRERROR], [1], [ ])], [ ],
579 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
581 + PHP_CHECK_LIBRARY(curl, curl_easy_reset,
582 + [AC_DEFINE([HAVE_CURL_EASY_RESET], [1], [ ])], [ ],
583 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
585 + PHP_CHECK_LIBRARY(curl, curl_formget,
586 + [AC_DEFINE([HAVE_CURL_FORMGET], [1], [ ])], [ ],
587 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
589 + PHP_CHECK_LIBRARY(curl, curl_multi_setopt,
590 + [AC_DEFINE([HAVE_CURL_MULTI_SETOPT], [1], [ ])], [ ],
591 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
593 + PHP_CHECK_LIBRARY(curl, curl_multi_timeout,
594 + [AC_DEFINE([HAVE_CURL_MULTI_TIMEOUT], [1], [ ])], [ ],
595 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
602 + if test "$PHP_HTTP_CURL_LIBEVENT" != "no"; then
603 + HTTP_HAVE_PHP_EXT([event], [
604 + AC_MSG_WARN([event support is incompatible with pecl/event; continuing without libevent support])
606 + AC_MSG_CHECKING([for event.h])
608 + for i in "$PHP_HTTP_CURL_LIBEVENT" /usr/local /usr /opt; do
609 + if test -f "$i/include/event.h"; then
614 + if test "x$EVENT_DIR" = "x"; then
615 + AC_MSG_RESULT([not found])
616 + AC_MSG_WARN([continuing without libevent support])
618 + AC_MSG_RESULT([found in $EVENT_DIR])
620 + AC_MSG_CHECKING([for libevent version, roughly])
621 + EVENT_VER="1.1b or lower"
622 + if test -f "$EVENT_DIR/include/evhttp.h" && test -f "$EVENT_DIR/include/evdns.h"; then
623 + if test -f "$EVENT_DIR/include/evrpc.h"; then
624 + EVENT_VER="1.4 or greater"
626 + EVENT_VER="1.2 or greater"
629 + AC_DEFINE_UNQUOTED([HTTP_EVENT_VERSION], ["$EVENT_VER"], [ ])
630 + AC_MSG_RESULT([$EVENT_VER])
632 + AC_MSG_CHECKING([for libcurl version >= 7.16.0])
633 + AC_MSG_RESULT([$CURL_VERSION])
634 + if test `echo $CURL_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*10000 + $2*100 + $3}'` -lt 71600; then
635 + AC_MSG_WARN([libcurl version greater or equal to 7.16.0 required; continuing without libevent support])
637 + PHP_ADD_INCLUDE($EVENT_DIR/include)
638 + PHP_ADD_LIBRARY_WITH_PATH(event, $EVENT_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
639 + AC_DEFINE([HTTP_HAVE_EVENT], [1], [Have libevent support for cURL])
640 + PHP_CHECK_LIBRARY(curl, curl_multi_socket_action,
641 + [AC_DEFINE([HAVE_CURL_MULTI_SOCKET_ACTION], [1], [ ])], [ ],
642 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
653 + if test "$PHP_HTTP_MAGIC_MIME" != "no"; then
654 + AC_MSG_CHECKING([for magic.h])
656 + for i in "$PHP_HTTP_MAGIC_MIME" /usr/local /usr /opt; do
657 + if test -f "$i/include/magic.h"; then
662 + if test "x$MAGIC_DIR" = "x"; then
663 + AC_MSG_RESULT([not found])
664 + AC_MSG_ERROR([could not find magic.h])
666 + AC_MSG_RESULT([found in $MAGIC_DIR])
669 + PHP_ADD_INCLUDE($MAGIC_DIR/include)
670 + PHP_ADD_LIBRARY_WITH_PATH(magic, $MAGIC_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD)
671 + AC_DEFINE([HTTP_HAVE_MAGIC], [1], [Have magic mime support])
677 + HTTP_HAVE_PHP_EXT([hash], [
678 + AC_MSG_CHECKING([for php_hash.h])
679 + HTTP_EXT_HASH_INCDIR=
680 + for i in `echo $INCLUDES | $SED -e's/-I//g'` $abs_srcdir ../hash; do
681 + if test -d $i; then
682 + if test -f $i/php_hash.h; then
683 + HTTP_EXT_HASH_INCDIR=$i
685 + elif test -f $i/ext/hash/php_hash.h; then
686 + HTTP_EXT_HASH_INCDIR=$i/ext/hash
691 + if test "x$HTTP_EXT_HASH_INCDIR" = "x"; then
692 + AC_MSG_RESULT([not found])
694 + AC_MSG_RESULT([$HTTP_EXT_HASH_INCDIR])
695 + AC_DEFINE([HTTP_HAVE_PHP_HASH_H], [1], [Have ext/hash support])
696 + PHP_ADD_INCLUDE([$HTTP_EXT_HASH_INCDIR])
703 + HTTP_HAVE_PHP_EXT([iconv])
708 + HTTP_HAVE_PHP_EXT([session])
713 + PHP_HTTP_SOURCES="missing.c http.c http_functions.c phpstr/phpstr.c \
714 + http_util_object.c http_message_object.c http_request_object.c http_request_pool_api.c \
715 + http_response_object.c http_exception_object.c http_requestpool_object.c \
716 + http_api.c http_cache_api.c http_request_api.c http_request_info.c http_date_api.c \
717 + http_headers_api.c http_message_api.c http_send_api.c http_url_api.c \
718 + http_info_api.c http_request_method_api.c http_encoding_api.c \
719 + http_filter_api.c http_request_body_api.c http_querystring_object.c \
720 + http_deflatestream_object.c http_inflatestream_object.c http_cookie_api.c \
721 + http_querystring_api.c http_request_datashare_api.c http_requestdatashare_object.c \
722 + http_persistent_handle_api.c"
724 + PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared)
726 + dnl shared extension deps
727 + HTTP_SHARED_DEP([hash])
728 + HTTP_SHARED_DEP([iconv])
729 + HTTP_SHARED_DEP([session])
731 + PHP_ADD_BUILD_DIR($ext_builddir/phpstr, 1)
732 + PHP_SUBST([HTTP_SHARED_LIBADD])
734 + PHP_HTTP_HEADERS="php_http_std_defs.h php_http.h php_http_api.h php_http_cache_api.h \
735 + php_http_date_api.h php_http_headers_api.h php_http_info_api.h php_http_message_api.h \
736 + php_http_request_api.h php_http_request_method_api.h php_http_send_api.h php_http_url_api.h \
737 + php_http_encoding_api.h phpstr/phpstr.h missing.h php_http_request_body_api.h \
738 + php_http_exception_object.h php_http_message_object.h php_http_request_object.h \
739 + php_http_requestpool_object.h php_http_response_object.h php_http_util_object.h \
740 + php_http_querystring_object.h php_http_deflatestream_object.h php_http_inflatestream_object.h \
741 + php_http_cookie_api.h php_http_querystring_api.h php_http_request_datashare_api.h php_http_requestdatashare_object.h \
742 + php_http_persistent_handle_api.h"
743 + ifdef([PHP_INSTALL_HEADERS], [
744 + PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS)
746 + PHP_SUBST([PHP_HTTP_HEADERS])
747 + PHP_ADD_MAKEFILE_FRAGMENT
750 + AC_DEFINE([HAVE_HTTP], [1], [Have extended HTTP support])
753 +++ b/ext/http/docs/examples/tutorial.txt
756 +A Beginners Tutorial
757 +--------------------
763 + The HttpRequest class can be used to execute any HTTP request method.
764 + The following example shows a simple GET request where a few query
765 + parameters are supplied. Additionally potential cookies will be
766 + read from and written to a file.
769 +$r = new HttpRequest('http://www.google.com/search');
771 +// store Googles cookies in a dedicated file
772 +touch('google.txt');
774 + array( 'cookiestore' => 'google.txt',
779 + array( 'q' => '+"pecl_http" -msg -cvs -list',
784 +// HttpRequest::send() returns an HttpMessage object
785 +// of type HttpMessage::TYPE_RESPONSE or throws an exception
787 + print $r->send()->getBody();
788 +} catch (HttpException $e) {
795 + The following example shows an multipart POST request, with two form
796 + fields and an image that's supposed to be uploaded to the server.
797 + It's a bad habit as well as common practice to issue a redirect after
798 + an received POST request, so we'll allow a redirect by enabling the
802 +$r = new HttpRequest('http://dev.iworks.at/.print_request.php', HTTP_METH_POST);
804 +// if redirects is set to true, a single redirect is allowed;
805 +// one can set any reasonable count of allowed redirects
807 + array( 'cookies' => array('MyCookie' => 'has a value'),
808 + 'redirect' => true,
814 + array( 'name' => 'Mike',
815 + 'mail' => 'mike@php.net',
818 +// add the file to post (form name, file name, file type)
819 +touch('profile.jpg');
820 +$r->addPostFile('image', 'profile.jpg', 'image/jpeg');
823 + print $r->send()->getBody();
824 +} catch (HttpException $e) {
831 + It's possible to execute several HttpRequests in parallel with the
832 + HttpRequestPool class. HttpRequests to send, do not need to perform
833 + the same request method, but can only be attached to one HttpRequestPool
838 + $p = new HttpRequestPool;
839 + // if you want to set _any_ options of the HttpRequest object,
840 + // you need to do so *prior attaching* to the request pool!
841 + $p->attach(new HttpRequest('http://pear.php.net', HTTP_METH_HEAD));
842 + $p->attach(new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD));
843 +} catch (HttpException $e) {
850 + // HttpRequestPool implements an iterator over attached HttpRequest objects
851 + foreach ($p as $r) {
852 + echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
854 +} catch (HttpException $e) {
859 +- Parallel Requests?
861 + You can use a more advanced approach by using the protected interface of
862 + the HttpRequestPool class. This allows you to perform some other tasks
863 + while the requests are executed.
866 +class Pool extends HttpRequestPool
868 + public function __construct()
870 + parent::__construct(
871 + new HttpRequest('http://pear.php.net', HTTP_METH_HEAD),
872 + new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD)
875 + // HttpRequestPool methods socketPerform() and socketSelect() are
876 + // protected; one could use this approach to do something else
877 + // while the requests are being executed
878 + print "Executing requests";
879 + for ($i = 0; $this->socketPerform(); $i++) {
880 + $i % 10 or print ".";
881 + if (!$this->socketSelect()) {
882 + throw new HttpException("Socket error!");
890 + foreach (new Pool as $r) {
891 + echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
893 +} catch (HttpException $ex) {
900 + One of the main key features of HttpResponse is HTTP caching. HttpResponse
901 + will calculate an ETag based on the http.etag_mode INI setting as well as
902 + it will determine the last modification time of the sent entity. It uses
903 + those two indicators to decide if the cache entry on the client side is
904 + still valid and will emit an "304 Not Modified" response if applicable.
907 +HttpResponse::setCacheControl('public');
908 +HttpResponse::setCache(true);
909 +HttpResponse::capture();
911 +print "This will be cached until content changes!\n";
912 +print "Note that this approach will only save the clients download time.\n";
915 +- Bandwidth Throttling
917 + HttpResponse supports a basic throttling mechanism, which is enabled by
918 + setting a throttle delay and a buffer size. PHP will sleep the specified
919 + amount of seconds after each sent chunk of specified bytes.
922 +// send 5000 bytes every 0.2 seconds, i.e. max ~25kByte/s
923 +HttpResponse::setThrottleDelay(0.2);
924 +HttpResponse::setBufferSize(5000);
925 +HttpResponse::setCache(true);
926 +HttpResponse::setContentType('application/x-zip');
927 +HttpResponse::setFile('../archive.zip');
928 +HttpResponse::send();
931 +++ b/ext/http/docs/http.ini
933 +; example INI file for pecl/http
934 +; $Id: http.ini 229420 2007-02-09 14:19:40Z mike $
937 +; enable if you want to transform all errors to exceptions (PHP >= 5 only)
938 +;http.only_exceptions = 1
940 +; disable if you don't want php to exit in case of redirects and cache hits;
941 +; a "NULL" output handler will be started instead, which discards all output
942 +;http.force_exit = 0
944 +; disable if you don't want 404 Not found status messages being sent,
945 +; if a file attempted to be sent with http_send_file() etc. cannot be found
946 +;http.send.not_found_404 = 0
948 +; the hashing algorithm with wich ETags are generated (MD5, SHA1, CRC32B);
949 +; if ext/hash is available, this can be set to any hash algorithm ext/hash supports
950 +; MD5 is the default and fallback algorithm
951 +;http.etag.mode = "MD5"
953 +; allowed request methods
954 +; by default PHP ignores unkown request methods
955 +; PHP will exit with a response status of 405 and an Allow header
956 +; if it encounters a request method not contained in the specified list
957 +;http.request.methods.allowed = "HEAD, GET, POST"
959 +; custom request methods
960 +;http.request.methods.custom = "KICK, BANN"
962 +; log file for positive cache hits
965 +; log file for redirects
966 +;http.log.redirect =
968 +; log file for responses with http_send_file() etc. where the file's not been found
969 +;http.log.not_found =
971 +; log file for requests with an unallowed request method
972 +;http.log.allowed_methods =
974 +; composite log file (i.e. log all messages to this file)
975 +;http.log.composite =
977 +; automatically deflate content if requested/supported by client
978 +;http.send.deflate.start_auto = 1
979 +;http.send.deflate.start_flags = HTTP_DEFLATE_LEVEL_DEF
981 +; automatically inflate sent content
982 +;http.send.inflate.start_auto = 0
983 +;http.send.inflate.start_flags =
985 +; global HttpRequestDataShare settings
986 +;http.request.datashare.cookie = 0
987 +;http.request.datashare.dns = 1
989 +; limit of idle persistent handles per provider
990 +;http.persistent.handles.limit = -1
992 +; default ident of persistent handles
993 +;http.persistent.handles.ident = "GLOBAL"
995 +++ b/ext/http/http.c
998 + +--------------------------------------------------------------------+
1000 + +--------------------------------------------------------------------+
1001 + | Redistribution and use in source and binary forms, with or without |
1002 + | modification, are permitted provided that the conditions mentioned |
1003 + | in the accompanying LICENSE file are met. |
1004 + +--------------------------------------------------------------------+
1005 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
1006 + +--------------------------------------------------------------------+
1009 +/* $Id: http.c 300300 2010-06-09 07:29:35Z mike $ */
1011 +#define HTTP_WANT_SAPI
1012 +#define HTTP_WANT_CURL
1013 +#define HTTP_WANT_EVENT
1014 +#define HTTP_WANT_ZLIB
1015 +#define HTTP_WANT_MAGIC
1016 +#include "php_http.h"
1018 +#include "php_ini.h"
1019 +#include "ext/standard/info.h"
1020 +#include "zend_extensions.h"
1022 +#include "php_http_api.h"
1023 +#include "php_http_cache_api.h"
1024 +#include "php_http_cookie_api.h"
1025 +#include "php_http_encoding_api.h"
1026 +#include "php_http_filter_api.h"
1027 +#include "php_http_message_api.h"
1028 +#include "php_http_persistent_handle_api.h"
1029 +#include "php_http_request_api.h"
1030 +#include "php_http_request_datashare_api.h"
1031 +#include "php_http_request_method_api.h"
1032 +#include "php_http_request_pool_api.h"
1033 +#include "php_http_send_api.h"
1034 +#include "php_http_url_api.h"
1036 +#include "php_http_deflatestream_object.h"
1037 +#include "php_http_exception_object.h"
1038 +#include "php_http_inflatestream_object.h"
1039 +#include "php_http_message_object.h"
1040 +#include "php_http_querystring_object.h"
1041 +#include "php_http_request_object.h"
1042 +#include "php_http_requestdatashare_object.h"
1043 +#include "php_http_requestpool_object.h"
1044 +#include "php_http_response_object.h"
1045 +#include "php_http_util_object.h"
1047 +ZEND_DECLARE_MODULE_GLOBALS(http);
1048 +HTTP_DECLARE_ARG_PASS_INFO();
1050 +#ifdef COMPILE_DL_HTTP
1051 +ZEND_GET_MODULE(http)
1054 +/* {{{ http_functions[] */
1055 +zend_function_entry http_functions[] = {
1056 + PHP_FE(http_date, NULL)
1057 + PHP_FE(http_build_url, http_arg_pass_ref_4)
1058 + PHP_FE(http_build_str, NULL)
1059 +#ifndef ZEND_ENGINE_2
1060 + PHP_FALIAS(http_build_query, http_build_str, NULL)
1062 + PHP_FE(http_negotiate_language, http_arg_pass_ref_2)
1063 + PHP_FE(http_negotiate_charset, http_arg_pass_ref_2)
1064 + PHP_FE(http_negotiate_content_type, http_arg_pass_ref_2)
1065 + PHP_FE(http_negotiate, http_arg_pass_ref_3)
1066 + PHP_FE(http_redirect, NULL)
1067 + PHP_FE(http_throttle, NULL)
1068 + PHP_FE(http_send_status, NULL)
1069 + PHP_FE(http_send_last_modified, NULL)
1070 + PHP_FE(http_send_content_type, NULL)
1071 + PHP_FE(http_send_content_disposition, NULL)
1072 + PHP_FE(http_match_modified, NULL)
1073 + PHP_FE(http_match_etag, NULL)
1074 + PHP_FE(http_cache_last_modified, NULL)
1075 + PHP_FE(http_cache_etag, NULL)
1076 + PHP_FE(http_send_data, NULL)
1077 + PHP_FE(http_send_file, NULL)
1078 + PHP_FE(http_send_stream, NULL)
1079 + PHP_FE(http_chunked_decode, NULL)
1080 + PHP_FE(http_parse_message, NULL)
1081 + PHP_FE(http_parse_headers, NULL)
1082 + PHP_FE(http_parse_cookie, NULL)
1083 + PHP_FE(http_build_cookie, NULL)
1084 + PHP_FE(http_parse_params, NULL)
1085 + PHP_FE(http_get_request_headers, NULL)
1086 + PHP_FE(http_get_request_body, NULL)
1087 + PHP_FE(http_get_request_body_stream, NULL)
1088 + PHP_FE(http_match_request_header, NULL)
1089 + PHP_FE(http_persistent_handles_count, NULL)
1090 + PHP_FE(http_persistent_handles_clean, NULL)
1091 + PHP_FE(http_persistent_handles_ident, NULL)
1092 +#ifdef HTTP_HAVE_CURL
1093 + PHP_FE(http_get, http_arg_pass_ref_3)
1094 + PHP_FE(http_head, http_arg_pass_ref_3)
1095 + PHP_FE(http_post_data, http_arg_pass_ref_4)
1096 + PHP_FE(http_post_fields, http_arg_pass_ref_5)
1097 + PHP_FE(http_put_data, http_arg_pass_ref_4)
1098 + PHP_FE(http_put_file, http_arg_pass_ref_4)
1099 + PHP_FE(http_put_stream, http_arg_pass_ref_4)
1100 + PHP_FE(http_request, http_arg_pass_ref_5)
1101 + PHP_FE(http_request_body_encode, NULL)
1103 + PHP_FE(http_request_method_register, NULL)
1104 + PHP_FE(http_request_method_unregister, NULL)
1105 + PHP_FE(http_request_method_exists, NULL)
1106 + PHP_FE(http_request_method_name, NULL)
1107 + PHP_FE(ob_etaghandler, NULL)
1108 +#ifdef HTTP_HAVE_ZLIB
1109 + PHP_FE(http_deflate, NULL)
1110 + PHP_FE(http_inflate, NULL)
1111 + PHP_FE(ob_deflatehandler, NULL)
1112 + PHP_FE(ob_inflatehandler, NULL)
1114 + PHP_FE(http_support, NULL)
1116 + EMPTY_FUNCTION_ENTRY
1120 +PHP_MINIT_FUNCTION(http);
1121 +PHP_MSHUTDOWN_FUNCTION(http);
1122 +PHP_RINIT_FUNCTION(http);
1123 +PHP_RSHUTDOWN_FUNCTION(http);
1124 +PHP_MINFO_FUNCTION(http);
1126 +/* {{{ http_module_dep */
1127 +#if ZEND_EXTENSION_API_NO >= 220050617
1128 +static zend_module_dep http_module_deps[] = {
1129 +# ifdef HTTP_HAVE_SPL
1130 + ZEND_MOD_REQUIRED("spl")
1132 +# ifdef HTTP_HAVE_HASH
1133 + ZEND_MOD_REQUIRED("hash")
1135 +# ifdef HTTP_HAVE_SESSION
1136 + ZEND_MOD_REQUIRED("session")
1138 +# ifdef HTTP_HAVE_ICONV
1139 + ZEND_MOD_REQUIRED("iconv")
1141 +# ifdef HTTP_HAVE_EVENT
1142 + ZEND_MOD_CONFLICTS("event")
1144 + {NULL, NULL, NULL, 0}
1149 +/* {{{ http_module_entry */
1150 +zend_module_entry http_module_entry = {
1151 +#if ZEND_EXTENSION_API_NO >= 220050617
1152 + STANDARD_MODULE_HEADER_EX, NULL,
1155 + STANDARD_MODULE_HEADER,
1160 + PHP_MSHUTDOWN(http),
1162 + PHP_RSHUTDOWN(http),
1165 + STANDARD_MODULE_PROPERTIES
1169 +int http_module_number;
1171 +/* {{{ http_globals */
1172 +static void http_globals_init_once(zend_http_globals *G)
1174 + memset(G, 0, sizeof(zend_http_globals));
1177 +#define http_globals_init(g) _http_globals_init((g) TSRMLS_CC)
1178 +static inline void _http_globals_init(zend_http_globals *G TSRMLS_DC)
1180 +#ifdef HTTP_HAVE_SAPI_RTIME
1181 + G->request.time = sapi_get_request_time(TSRMLS_C);
1183 + G->request.time = time(NULL);
1185 + G->send.buffer_size = 0;
1186 + G->read_post_data = 0;
1189 +#define http_globals_free(g) _http_globals_free((g) TSRMLS_CC)
1190 +static inline void _http_globals_free(zend_http_globals *G TSRMLS_DC)
1192 + if (G->request.headers) {
1193 + zend_hash_destroy(G->request.headers);
1194 + FREE_HASHTABLE(G->request.headers);
1195 + G->request.headers = NULL;
1197 + STR_SET(G->send.content_type, NULL);
1198 + STR_SET(G->send.unquoted_etag, NULL);
1199 + if (G->server_var) {
1200 + zval_ptr_dtor(&G->server_var);
1201 + G->server_var = NULL;
1205 +#if defined(ZTS) && defined(PHP_DEBUG)
1206 +#if ZTS && PHP_DEBUG
1207 +zend_http_globals *http_globals(void)
1216 +/* {{{ static inline void http_check_allowed_methods(char *) */
1217 +#define http_check_allowed_methods(m) _http_check_allowed_methods((m) TSRMLS_CC)
1218 +static inline void _http_check_allowed_methods(const char *methods TSRMLS_DC)
1220 + if (*methods && SG(request_info).request_method) {
1221 + if (SUCCESS != http_check_method_ex(SG(request_info).request_method, methods)) {
1223 + spprintf(&header, 0, "Allow: %s", methods);
1224 + http_exit(405, header);
1231 +PHP_INI_MH(http_update_allowed_methods)
1234 + http_check_allowed_methods(new_value);
1236 + return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
1238 +PHP_INI_MH(http_update_persistent_handle_ident)
1240 + HTTP_G->persistent.handles.ident.h = zend_hash_func(new_value, HTTP_G->persistent.handles.ident.l = new_value_length+1);
1241 + return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
1244 +#ifndef ZEND_ENGINE_2
1245 +# define OnUpdateLong OnUpdateInt
1249 + HTTP_PHP_INI_ENTRY("http.etag.mode", "MD5", PHP_INI_ALL, OnUpdateString, etag.mode)
1250 + HTTP_PHP_INI_ENTRY("http.log.cache", "", PHP_INI_ALL, OnUpdateString, log.cache)
1251 + HTTP_PHP_INI_ENTRY("http.log.redirect", "", PHP_INI_ALL, OnUpdateString, log.redirect)
1252 + HTTP_PHP_INI_ENTRY("http.log.not_found", "", PHP_INI_ALL, OnUpdateString, log.not_found)
1253 + HTTP_PHP_INI_ENTRY("http.log.allowed_methods", "", PHP_INI_ALL, OnUpdateString, log.allowed_methods)
1254 + HTTP_PHP_INI_ENTRY("http.log.composite", "", PHP_INI_ALL, OnUpdateString, log.composite)
1255 + HTTP_PHP_INI_ENTRY("http.request.methods.allowed", "", PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
1256 + HTTP_PHP_INI_ENTRY("http.request.methods.custom", "", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, request.methods.custom)
1257 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
1258 + HTTP_PHP_INI_ENTRY("http.request.datashare.cookie", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.cookie)
1259 + HTTP_PHP_INI_ENTRY("http.request.datashare.dns", "1", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.dns)
1260 + HTTP_PHP_INI_ENTRY("http.request.datashare.ssl", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.ssl)
1261 + HTTP_PHP_INI_ENTRY("http.request.datashare.connect", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.connect)
1263 +#ifdef HTTP_HAVE_ZLIB
1264 + HTTP_PHP_INI_ENTRY("http.send.inflate.start_auto", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, send.inflate.start_auto)
1265 + HTTP_PHP_INI_ENTRY("http.send.inflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.inflate.start_flags)
1266 + HTTP_PHP_INI_ENTRY("http.send.deflate.start_auto", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, send.deflate.start_auto)
1267 + HTTP_PHP_INI_ENTRY("http.send.deflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.deflate.start_flags)
1269 + HTTP_PHP_INI_ENTRY("http.persistent.handles.limit", "-1", PHP_INI_SYSTEM, OnUpdateLong, persistent.handles.limit)
1270 + HTTP_PHP_INI_ENTRY("http.persistent.handles.ident", "GLOBAL", PHP_INI_ALL, http_update_persistent_handle_ident, persistent.handles.ident.s)
1271 + HTTP_PHP_INI_ENTRY("http.send.not_found_404", "1", PHP_INI_ALL, OnUpdateBool, send.not_found_404)
1272 +#ifdef ZEND_ENGINE_2
1273 + HTTP_PHP_INI_ENTRY("http.only_exceptions", "0", PHP_INI_ALL, OnUpdateBool, only_exceptions)
1275 + HTTP_PHP_INI_ENTRY("http.force_exit", "1", PHP_INI_ALL, OnUpdateBool, force_exit)
1279 +/* {{{ PHP_MINIT_FUNCTION */
1280 +PHP_MINIT_FUNCTION(http)
1282 + http_module_number = module_number;
1283 + ZEND_INIT_MODULE_GLOBALS(http, http_globals_init_once, NULL);
1284 + REGISTER_INI_ENTRIES();
1287 + || SUCCESS != PHP_MINIT_CALL(http_persistent_handle) /* first */
1288 + || SUCCESS != PHP_MINIT_CALL(http_cookie)
1289 +#ifdef HTTP_HAVE_ZLIB
1290 + || SUCCESS != PHP_MINIT_CALL(http_encoding)
1292 +#ifdef HTTP_HAVE_CURL
1293 + || SUCCESS != PHP_MINIT_CALL(http_request)
1294 +# ifdef ZEND_ENGINE_2
1297 + || SUCCESS != PHP_MINIT_CALL(http_request_method)
1298 + || SUCCESS != PHP_MINIT_CALL(http_send)
1299 + || SUCCESS != PHP_MINIT_CALL(http_support)
1300 + || SUCCESS != PHP_MINIT_CALL(http_url)
1302 +#ifdef ZEND_ENGINE_2
1303 + || SUCCESS != PHP_MINIT_CALL(http_filter)
1304 + || SUCCESS != PHP_MINIT_CALL(http_exception_object)
1305 +# ifdef HTTP_HAVE_ZLIB
1306 + || SUCCESS != PHP_MINIT_CALL(http_deflatestream_object)
1307 + || SUCCESS != PHP_MINIT_CALL(http_inflatestream_object)
1309 + || SUCCESS != PHP_MINIT_CALL(http_message_object)
1310 + || SUCCESS != PHP_MINIT_CALL(http_querystring_object)
1311 +# ifdef HTTP_HAVE_CURL
1312 + || SUCCESS != PHP_MINIT_CALL(http_request_datashare)
1313 + || SUCCESS != PHP_MINIT_CALL(http_request_pool)
1314 + || SUCCESS != PHP_MINIT_CALL(http_request_object)
1315 + || SUCCESS != PHP_MINIT_CALL(http_requestdatashare_object)
1316 + || SUCCESS != PHP_MINIT_CALL(http_requestpool_object)
1319 + || SUCCESS != PHP_MINIT_CALL(http_response_object)
1321 + || SUCCESS != PHP_MINIT_CALL(http_util_object)
1331 +/* {{{ PHP_MSHUTDOWN_FUNCTION */
1332 +PHP_MSHUTDOWN_FUNCTION(http)
1334 + UNREGISTER_INI_ENTRIES();
1337 +#ifdef HTTP_HAVE_CURL
1338 + || SUCCESS != PHP_MSHUTDOWN_CALL(http_request)
1339 +# ifdef ZEND_ENGINE_2
1340 + || SUCCESS != PHP_MSHUTDOWN_CALL(http_request_datashare)
1343 + || SUCCESS != PHP_MSHUTDOWN_CALL(http_message_object)
1344 + || SUCCESS != PHP_MSHUTDOWN_CALL(http_persistent_handle) /* last */
1353 +/* {{{ PHP_RINIT_FUNCTION */
1354 +PHP_RINIT_FUNCTION(http)
1356 + http_globals_init(HTTP_G);
1358 + if (HTTP_G->request.methods.allowed && *HTTP_G->request.methods.allowed) {
1359 + http_check_allowed_methods(HTTP_G->request.methods.allowed);
1363 +#ifdef HTTP_HAVE_ZLIB
1364 + || SUCCESS != PHP_RINIT_CALL(http_encoding)
1366 +#ifdef HTTP_HAVE_CURL
1367 +# ifdef ZEND_ENGINE_2
1368 +# ifdef HTTP_HAVE_EVENT
1369 + || SUCCESS != PHP_RINIT_CALL(http_request_pool)
1371 + || SUCCESS != PHP_RINIT_CALL(http_request_datashare)
1374 + || SUCCESS != PHP_RINIT_CALL(http_request_method)
1383 +/* {{{ PHP_RSHUTDOWN_FUNCTION */
1384 +PHP_RSHUTDOWN_FUNCTION(http)
1386 + STATUS status = SUCCESS;
1389 +#ifdef HTTP_HAVE_ZLIB
1390 + || SUCCESS != PHP_RSHUTDOWN_CALL(http_encoding)
1392 +#ifdef HTTP_HAVE_CURL
1393 +# ifdef ZEND_ENGINE_2
1394 + || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_datashare)
1397 + || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_method)
1402 + http_globals_free(HTTP_G);
1407 +/* {{{ PHP_MINFO_FUNCTION */
1408 +PHP_MINFO_FUNCTION(http)
1410 + php_info_print_table_start();
1412 + php_info_print_table_header(2, "HTTP Support", "enabled");
1413 + php_info_print_table_row(2, "Extension Version", PHP_HTTP_VERSION);
1414 + php_info_print_table_row(2, "Registered Classes",
1415 +#ifndef ZEND_ENGINE_2
1420 +# ifdef HTTP_HAVE_CURL
1422 + "HttpRequestPool, "
1423 + "HttpRequestDataShare, "
1425 +# ifdef HTTP_HAVE_ZLIB
1426 + "HttpDeflateStream, "
1427 + "HttpInflateStream, "
1435 + php_info_print_table_row(2, "Output Handlers", "ob_deflatehandler, ob_inflatehandler, ob_etaghandler");
1436 + php_info_print_table_row(2, "Stream Filters",
1437 +#ifndef ZEND_ENGINE_2
1440 + "http.chunked_decode, http.chunked_encode, http.deflate, http.inflate"
1444 + php_info_print_table_end();
1446 + php_info_print_table_start();
1447 + php_info_print_table_header(3, "Used Library", "Compiled", "Linked");
1449 +#ifdef HTTP_HAVE_CURL
1450 + curl_version_info_data *cv = curl_version_info(CURLVERSION_NOW);
1451 + php_info_print_table_row(3, "libcurl", LIBCURL_VERSION, cv->version);
1453 + php_info_print_table_row(2, "libcurl", "disabled", "disabled");
1455 +#ifdef HTTP_HAVE_EVENT
1456 + php_info_print_table_row(3, "libevent", HTTP_EVENT_VERSION, event_get_version());
1458 + php_info_print_table_row(3, "libevent", "disabled", "disabled");
1460 +#ifdef HTTP_HAVE_ZLIB
1461 + php_info_print_table_row(3, "libz", ZLIB_VERSION, zlibVersion());
1463 + php_info_print_table_row(3, "libz", "disabled", "disabled");
1465 +#if defined(HTTP_HAVE_MAGIC)
1466 + php_info_print_table_row(3, "libmagic", "unknown", "unknown");
1468 + php_info_print_table_row(3, "libmagic", "disabled", "disabled");
1471 + php_info_print_table_end();
1473 + php_info_print_table_start();
1474 + php_info_print_table_colspan_header(4, "Persistent Handles");
1475 + php_info_print_table_header(4, "Provider", "Ident", "Used", "Free");
1478 + HashPosition pos1, pos2;
1479 + HashKey provider = initHashKey(0), ident = initHashKey(0);
1480 + zval **val, **sub, **zused, **zfree;
1482 + if ((ht = http_persistent_handle_statall()) && zend_hash_num_elements(ht)) {
1483 + FOREACH_HASH_KEYVAL(pos1, ht, provider, val) {
1484 + if (zend_hash_num_elements(Z_ARRVAL_PP(val))) {
1485 + FOREACH_KEYVAL(pos2, *val, ident, sub) {
1486 + if ( SUCCESS == zend_hash_find(Z_ARRVAL_PP(sub), ZEND_STRS("used"), (void *) &zused) &&
1487 + SUCCESS == zend_hash_find(Z_ARRVAL_PP(sub), ZEND_STRS("free"), (void *) &zfree)) {
1488 + zval *used = http_zsep(IS_STRING, *zused);
1489 + zval *free = http_zsep(IS_STRING, *zfree);
1490 + php_info_print_table_row(4, provider.str, ident.str, Z_STRVAL_P(used), Z_STRVAL_P(free));
1491 + zval_ptr_dtor(&used);
1492 + zval_ptr_dtor(&free);
1494 + php_info_print_table_row(4, provider.str, ident.str, "0", "0");
1498 + php_info_print_table_row(4, provider.str, "N/A", "0", "0");
1502 + php_info_print_table_row(4, "N/A", "N/A", "0", "0");
1505 + zend_hash_destroy(ht);
1506 + FREE_HASHTABLE(ht);
1509 + php_info_print_table_end();
1511 + php_info_print_table_start();
1512 + php_info_print_table_colspan_header(2, "Request Methods");
1515 + phpstr *methods = phpstr_new();
1518 + FOREACH_HASH_VAL(pos, &HTTP_G->request.methods.registered, name) {
1520 + phpstr_appendf(methods, "%s, ", *name);
1523 + phpstr_fix(methods);
1524 + php_info_print_table_row(2, "Registered", PHPSTR_VAL(methods));
1525 + php_info_print_table_row(2, "Allowed", *HTTP_G->request.methods.allowed ? HTTP_G->request.methods.allowed : "(ANY)");
1526 + phpstr_free(&methods);
1528 + php_info_print_table_end();
1530 + DISPLAY_INI_ENTRIES();
1535 + * Local variables:
1537 + * c-basic-offset: 4
1539 + * vim600: noet sw=4 ts=4 fdm=marker
1540 + * vim<600: noet sw=4 ts=4
1544 +++ b/ext/http/http.dsp
1546 +# Microsoft Developer Studio Project File - Name="http" - Package Owner=<4>
\r
1547 +# Microsoft Developer Studio Generated Build File, Format Version 6.00
\r
1548 +# ** DO NOT EDIT **
\r
1550 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
\r
1552 +CFG=http - Win32 Release_TS
\r
1553 +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
\r
1554 +!MESSAGE use the Export Makefile command and run
\r
1556 +!MESSAGE NMAKE /f "http.mak".
\r
1558 +!MESSAGE You can specify a configuration when running NMAKE
\r
1559 +!MESSAGE by defining the macro CFG on the command line. For example:
\r
1561 +!MESSAGE NMAKE /f "http.mak" CFG="http - Win32 Release_TS"
\r
1563 +!MESSAGE Possible choices for configuration are:
\r
1565 +!MESSAGE "http - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
\r
1566 +!MESSAGE "http - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
\r
1570 +# PROP AllowPerConfigDependencies 0
\r
1571 +# PROP Scc_ProjName ""
\r
1572 +# PROP Scc_LocalPath ""
\r
1577 +!IF "$(CFG)" == "http - Win32 Release_TS"
\r
1579 +# PROP BASE Use_MFC 0
\r
1580 +# PROP BASE Use_Debug_Libraries 0
\r
1581 +# PROP BASE Output_Dir "Release_TS"
\r
1582 +# PROP BASE Intermediate_Dir "Release_TS"
\r
1583 +# PROP BASE Ignore_Export_Lib 0
\r
1584 +# PROP BASE Target_Dir ""
\r
1586 +# PROP Use_Debug_Libraries 0
\r
1587 +# PROP Output_Dir "Release_TS"
\r
1588 +# PROP Intermediate_Dir "Release_TS"
\r
1589 +# PROP Ignore_Export_Lib 0
\r
1590 +# PROP Target_Dir ""
\r
1591 +# 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
\r
1592 +# 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
\r
1593 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
\r
1594 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
\r
1595 +# ADD BASE RSC /l 0x406 /d "NDEBUG"
\r
1596 +# ADD RSC /l 0x406 /d "NDEBUG"
\r
1597 +BSC32=bscmake.exe
\r
1598 +# ADD BASE BSC32 /nologo
\r
1599 +# ADD BSC32 /nologo
\r
1601 +# 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
\r
1602 +# 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"
\r
1604 +!ELSEIF "$(CFG)" == "http - Win32 Debug_TS"
\r
1606 +# PROP BASE Use_MFC 0
\r
1607 +# PROP BASE Use_Debug_Libraries 0
\r
1608 +# PROP BASE Output_Dir "Debug_TS"
\r
1609 +# PROP BASE Intermediate_Dir "Debug_TS"
\r
1610 +# PROP BASE Ignore_Export_Lib 0
\r
1611 +# PROP BASE Target_Dir ""
\r
1613 +# PROP Use_Debug_Libraries 0
\r
1614 +# PROP Output_Dir "Debug_TS"
\r
1615 +# PROP Intermediate_Dir "Debug_TS"
\r
1616 +# PROP Ignore_Export_Lib 0
\r
1617 +# PROP Target_Dir ""
\r
1618 +# 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
\r
1619 +# 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
\r
1620 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
\r
1621 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
\r
1622 +# ADD BASE RSC /l 0x406 /d "NDEBUG"
\r
1623 +# ADD RSC /l 0x406 /d "NDEBUG"
\r
1624 +BSC32=bscmake.exe
\r
1625 +# ADD BASE BSC32 /nologo
\r
1626 +# ADD BSC32 /nologo
\r
1628 +# 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
\r
1629 +# 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"
\r
1635 +# Name "http - Win32 Release_TS"
\r
1636 +# Name "http - Win32 Debug_TS"
\r
1637 +# Begin Group "Source Files"
\r
1639 +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
\r
1640 +# Begin Source File
\r
1643 +# End Source File
\r
1644 +# Begin Source File
\r
1646 +SOURCE=.\http_api.c
\r
1647 +# End Source File
\r
1648 +# Begin Source File
\r
1650 +SOURCE=.\http_encoding_api.c
\r
1651 +# End Source File
\r
1652 +# Begin Source File
\r
1654 +SOURCE=.\http_request_api.c
\r
1655 +# End Source File
\r
1656 +# Begin Source File
\r
1658 +SOURCE=.\http_request_info.c
\r
1659 +# End Source File
\r
1660 +# Begin Source File
\r
1662 +SOURCE=.\http_request_body_api.c
\r
1663 +# End Source File
\r
1664 +# Begin Source File
\r
1666 +SOURCE=.\http_request_method_api.c
\r
1667 +# End Source File
\r
1668 +# Begin Source File
\r
1670 +SOURCE=.\http_functions.c
\r
1671 +# End Source File
\r
1672 +# Begin Source File
\r
1674 +SOURCE=.\http_persistent_handle_api.c
\r
1675 +# End Source File
\r
1676 +# Begin Source File
\r
1678 +SOURCE=.\http_cache_api.c
\r
1679 +# End Source File
\r
1680 +# Begin Source File
\r
1682 +SOURCE=.\http_cookie_api.c
\r
1683 +# End Source File
\r
1684 +# Begin Source File
\r
1686 +SOURCE=.\http_date_api.c
\r
1687 +# End Source File
\r
1688 +# Begin Source File
\r
1690 +SOURCE=.\http_headers_api.c
\r
1691 +# End Source File
\r
1692 +# Begin Source File
\r
1694 +SOURCE=.\http_message_api.c
\r
1695 +# End Source File
\r
1696 +# Begin Source File
\r
1698 +SOURCE=.\http_send_api.c
\r
1699 +# End Source File
\r
1700 +# Begin Source File
\r
1702 +SOURCE=.\http_url_api.c
\r
1703 +# End Source File
\r
1704 +# Begin Source File
\r
1706 +SOURCE=.\http_querystring_api.c
\r
1707 +# End Source File
\r
1708 +# Begin Source File
\r
1710 +SOURCE=.\http_info_api.c
\r
1711 +# End Source File
\r
1712 +# Begin Source File
\r
1714 +SOURCE=.\phpstr\phpstr.c
\r
1715 +# End Source File
\r
1717 +# Begin Group "Header Files"
\r
1719 +# PROP Default_Filter "h;hpp;hxx;hm;inl"
\r
1720 +# Begin Source File
\r
1722 +SOURCE=.\php_http.h
\r
1723 +# End Source File
\r
1724 +# Begin Source File
\r
1726 +SOURCE=.\php_http_api.h
\r
1727 +# End Source File
\r
1728 +# Begin Source File
\r
1730 +SOURCE=.\php_http_encoding_api.h
\r
1731 +# End Source File
\r
1732 +# Begin Source File
\r
1734 +SOURCE=.\php_http_request_api.h
\r
1735 +# End Source File
\r
1736 +# Begin Source File
\r
1738 +SOURCE=.\php_http_request_int.h
\r
1739 +# End Source File
\r
1740 +# Begin Source File
\r
1742 +SOURCE=.\php_http_request_body_api.h
\r
1743 +# End Source File
\r
1744 +# Begin Source File
\r
1746 +SOURCE=.\php_http_request_method_api.h
\r
1747 +# End Source File
\r
1748 +# Begin Source File
\r
1750 +SOURCE=.\php_http_persistent_handle_api.h
\r
1751 +# End Source File
\r
1752 +# Begin Source File
\r
1754 +SOURCE=.\php_http_cache_api.h
\r
1755 +# End Source File
\r
1756 +# Begin Source File
\r
1758 +SOURCE=.\php_http_cookie_api.h
\r
1759 +# End Source File
\r
1760 +# Begin Source File
\r
1762 +SOURCE=.\php_http_date_api.h
\r
1763 +# End Source File
\r
1764 +# Begin Source File
\r
1766 +SOURCE=.\php_http_message_api.h
\r
1767 +# End Source File
\r
1768 +# Begin Source File
\r
1770 +SOURCE=.\php_http_send_api.h
\r
1771 +# End Source File
\r
1772 +# Begin Source File
\r
1774 +SOURCE=.\php_http_headers_api.h
\r
1775 +# End Source File
\r
1776 +# Begin Source File
\r
1778 +SOURCE=.\php_http_url_api.h
\r
1779 +# End Source File
\r
1780 +# Begin Source File
\r
1782 +SOURCE=.\php_http_querystring_api.h
\r
1783 +# End Source File
\r
1784 +# Begin Source File
\r
1786 +SOURCE=.\php_http_info_api.h
\r
1787 +# End Source File
\r
1788 +# Begin Source File
\r
1790 +SOURCE=.\php_http_std_defs.h
\r
1791 +# End Source File
\r
1792 +# Begin Source File
\r
1794 +SOURCE=.\phpstr\phpstr.h
\r
1795 +# End Source File
\r
1797 +# Begin Group "Resource Files"
\r
1799 +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
\r
1804 +++ b/ext/http/http_api.c
1807 + +--------------------------------------------------------------------+
1809 + +--------------------------------------------------------------------+
1810 + | Redistribution and use in source and binary forms, with or without |
1811 + | modification, are permitted provided that the conditions mentioned |
1812 + | in the accompanying LICENSE file are met. |
1813 + +--------------------------------------------------------------------+
1814 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
1815 + +--------------------------------------------------------------------+
1818 +/* $Id: http_api.c 310302 2011-04-18 08:24:49Z rrichards $ */
1820 +#define HTTP_WANT_SAPI
1821 +#include "php_http.h"
1823 +#include "php_output.h"
1824 +#include "ext/standard/url.h"
1825 +#include "ext/standard/php_lcg.h"
1827 +#include "php_http_api.h"
1828 +#include "php_http_send_api.h"
1830 +#ifdef ZEND_ENGINE_2
1831 +# include "php_http_exception_object.h"
1834 +PHP_MINIT_FUNCTION(http_support)
1836 + HTTP_LONG_CONSTANT("HTTP_SUPPORT", HTTP_SUPPORT);
1837 + HTTP_LONG_CONSTANT("HTTP_SUPPORT_REQUESTS", HTTP_SUPPORT_REQUESTS);
1838 + HTTP_LONG_CONSTANT("HTTP_SUPPORT_MAGICMIME", HTTP_SUPPORT_MAGICMIME);
1839 + HTTP_LONG_CONSTANT("HTTP_SUPPORT_ENCODINGS", HTTP_SUPPORT_ENCODINGS);
1840 + HTTP_LONG_CONSTANT("HTTP_SUPPORT_SSLREQUESTS", HTTP_SUPPORT_SSLREQUESTS);
1841 + HTTP_LONG_CONSTANT("HTTP_SUPPORT_EVENTS", HTTP_SUPPORT_EVENTS);
1843 + HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_COMMA", HTTP_PARAMS_ALLOW_COMMA);
1844 + HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_FAILURE", HTTP_PARAMS_ALLOW_FAILURE);
1845 + HTTP_LONG_CONSTANT("HTTP_PARAMS_RAISE_ERROR", HTTP_PARAMS_RAISE_ERROR);
1846 + HTTP_LONG_CONSTANT("HTTP_PARAMS_DEFAULT", HTTP_PARAMS_DEFAULT);
1851 +PHP_HTTP_API long _http_support(long feature)
1853 + long support = HTTP_SUPPORT;
1855 +#ifdef HTTP_HAVE_CURL
1856 + support |= HTTP_SUPPORT_REQUESTS;
1857 +# ifdef HTTP_HAVE_SSL
1858 + support |= HTTP_SUPPORT_SSLREQUESTS;
1860 +# ifdef HTTP_HAVE_EVENT
1861 + support |= HTTP_SUPPORT_EVENTS;
1864 +#ifdef HTTP_HAVE_MAGIC
1865 + support |= HTTP_SUPPORT_MAGICMIME;
1867 +#ifdef HTTP_HAVE_ZLIB
1868 + support |= HTTP_SUPPORT_ENCODINGS;
1872 + return (feature == (support & feature));
1877 +/* char *pretty_key(char *, size_t, zend_bool, zend_bool) */
1878 +char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
1883 + if (key && key_len) {
1884 + if ((wasalpha = HTTP_IS_CTYPE(alpha, key[0]))) {
1885 + key[0] = (char) (uctitle ? HTTP_TO_CTYPE(upper, key[0]) : HTTP_TO_CTYPE(lower, key[0]));
1887 + for (i = 1; i < key_len; i++) {
1888 + if (HTTP_IS_CTYPE(alpha, key[i])) {
1889 + key[i] = (char) (((!wasalpha) && uctitle) ? HTTP_TO_CTYPE(upper, key[i]) : HTTP_TO_CTYPE(lower, key[i]));
1892 + if (xhyphen && (key[i] == '_')) {
1903 +/* {{{ http_boundary(char *, size_t) */
1904 +size_t _http_boundary(char *buf, size_t buf_len TSRMLS_DC)
1906 + return snprintf(buf, buf_len, "%lu%0.9f", (ulong) HTTP_G->request.time, (float) php_combined_lcg(TSRMLS_C));
1910 +/* {{{ void http_error(long, long, char*) */
1911 +void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...)
1915 + va_start(args, format);
1916 +#ifdef ZEND_ENGINE_2
1917 + if ((type == E_THROW) || (GLOBAL_ERROR_HANDLING == EH_THROW)) {
1919 + zend_class_entry *ce = http_exception_get_for_code(code);
1922 + vspprintf(&message, 0, format, args);
1923 + zend_throw_exception(ce, message, code TSRMLS_CC);
1925 + } http_catch(GLOBAL_EXCEPTION_CLASS ? GLOBAL_EXCEPTION_CLASS : HTTP_EX_DEF_CE);
1928 + php_verror(NULL, "", type, format, args TSRMLS_CC);
1933 +#ifdef ZEND_ENGINE_2
1934 +static inline void copy_bt_args(zval *from, zval *to TSRMLS_DC)
1936 + zval **args, **trace_0, *old_trace_0, *trace = NULL;
1938 + if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), from, "trace", lenof("trace"), 0 TSRMLS_CC))) {
1939 + if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) {
1940 + old_trace_0 = *trace_0;
1941 + if (Z_TYPE_PP(trace_0) == IS_ARRAY && SUCCESS == zend_hash_find(Z_ARRVAL_PP(trace_0), "args", sizeof("args"), (void *) &args)) {
1942 + if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), to, "trace", lenof("trace"), 0 TSRMLS_CC))) {
1943 + if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) {
1944 + ZVAL_ADDREF(*args);
1945 + add_assoc_zval(*trace_0, "args", *args);
1953 +/* {{{ zval *http_exception_wrap(zval *, zval *, zend_class_entry *) */
1954 +zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC)
1958 + zval *sub_exception, *tmp_exception;
1960 + if (!new_exception) {
1961 + MAKE_STD_ZVAL(new_exception);
1962 + object_init_ex(new_exception, ce);
1964 + zend_update_property(ce, new_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC);
1965 + copy_bt_args(old_exception, new_exception TSRMLS_CC);
1967 + sub_exception = old_exception;
1969 + 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) {
1973 + spprintf(&message, 0, "Exception caused by %d inner exception(s)", inner);
1974 + zend_update_property_string(ZEND_EXCEPTION_GET_DEFAULT(), new_exception, "message", lenof("message"), message TSRMLS_CC);
1977 + sub_exception = new_exception;
1978 + tmp_exception = new_exception;
1980 + 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) {
1981 + sub_exception = tmp_exception;
1984 + zend_update_property(Z_OBJCE_P(sub_exception), sub_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC);
1985 + copy_bt_args(old_exception, new_exception TSRMLS_CC);
1986 + copy_bt_args(old_exception, sub_exception TSRMLS_CC);
1988 +#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3
1989 + Z_ADDREF_P(old_exception);
1990 + zend_exception_set_previous(new_exception, old_exception TSRMLS_CC);
1992 + zval_ptr_dtor(&old_exception);
1993 + return new_exception;
1997 +/* {{{ STATUS http_object_new(zend_object_value *, const char *, uint, http_object_new_t, zend_class_entry *, void *, void **) */
1998 +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)
2000 + zend_class_entry *ce = parent_ce;
2002 + if (cname_str && cname_len) {
2003 + if (!(ce = zend_fetch_class(HTTP_ZAPI_CONST_CAST(char *) cname_str, cname_len, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC))) {
2006 + if (!instanceof_function(ce, parent_ce TSRMLS_CC)) {
2007 + http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Class %s does not extend %s", cname_str, parent_ce->name);
2012 + *ov = create(ce, intern_ptr, obj_ptr TSRMLS_CC);
2016 +#endif /* ZEND_ENGINE_2 */
2018 +/* {{{ void http_log(char *, char *, char *) */
2019 +void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC)
2023 + char datetime[20] = {0};
2025 + now = HTTP_G->request.time;
2026 + strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", php_localtime_r(&now, &nowtm));
2028 +#define HTTP_LOG_WRITE(file, type, msg) \
2029 + if (file && *file) { \
2030 + php_stream *log = php_stream_open_wrapper_ex(file, "ab", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT); \
2033 + php_stream_printf(log TSRMLS_CC, "%s\t[%s]\t%s\t<%s>%s", datetime, type, msg, SG(request_info).request_uri, PHP_EOL); \
2034 + php_stream_close(log); \
2039 + HTTP_LOG_WRITE(file, ident, message);
2040 + HTTP_LOG_WRITE(HTTP_G->log.composite, ident, message);
2044 +static void http_ob_blackhole(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
2046 + *handled_output = ecalloc(1,1);
2047 + *handled_output_len = 0;
2050 +/* {{{ STATUS http_exit(int, char*, char*) */
2051 +STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC)
2053 + if ( (send_header && (SUCCESS != http_send_status_header(status, header))) ||
2054 + (status && (SUCCESS != http_send_status(status)))) {
2055 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Failed to exit with status/header: %d - %s", status, STR_PTR(header));
2061 + if (!php_ob_handler_used("zlib output compression") && !php_ob_handler_used("ob_gzhandler") && !OG(ob_lock)) {
2062 + php_end_ob_buffers(0 TSRMLS_CC);
2064 + if ((SUCCESS == sapi_send_headers(TSRMLS_C)) && body) {
2065 + PHPWRITE(body, strlen(body));
2069 + case 301: http_log(HTTP_G->log.redirect, "301-REDIRECT", header); break;
2070 + case 302: http_log(HTTP_G->log.redirect, "302-REDIRECT", header); break;
2071 + case 303: http_log(HTTP_G->log.redirect, "303-REDIRECT", header); break;
2072 + case 305: http_log(HTTP_G->log.redirect, "305-REDIRECT", header); break;
2073 + case 307: http_log(HTTP_G->log.redirect, "307-REDIRECT", header); break;
2074 + case 304: http_log(HTTP_G->log.cache, "304-CACHE", header); break;
2075 + case 404: http_log(HTTP_G->log.not_found, "404-NOTFOUND", NULL); break;
2076 + case 405: http_log(HTTP_G->log.allowed_methods, "405-ALLOWED", header); break;
2077 + default: http_log(NULL, header, body); break;
2083 + if (HTTP_G->force_exit) {
2086 + php_ob_set_internal_handler(http_ob_blackhole, 4096, "blackhole", 0 TSRMLS_CC);
2093 +/* {{{ STATUS http_check_method(char *) */
2094 +STATUS _http_check_method_ex(const char *method, const char *methods)
2096 + const char *found;
2098 + if ( (found = strstr(methods, method)) &&
2099 + (found == method || !HTTP_IS_CTYPE(alpha, found[-1])) &&
2100 + (strlen(found) >= strlen(method) && !HTTP_IS_CTYPE(alpha, found[strlen(method)]))) {
2107 +/* {{{ zval *http_get_server_var_ex(char *, size_t) */
2108 +PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC)
2110 + zval **hsv, **var;
2113 + /* if available, this is a lot faster than accessing $_SERVER */
2114 + if (sapi_module.getenv) {
2115 + if ((!(env = sapi_module.getenv((char *) key, key_len TSRMLS_CC))) || (check && !*env)) {
2118 + if (HTTP_G->server_var) {
2119 + zval_ptr_dtor(&HTTP_G->server_var);
2121 + MAKE_STD_ZVAL(HTTP_G->server_var);
2122 + ZVAL_STRING(HTTP_G->server_var, env, 1);
2123 + return HTTP_G->server_var;
2126 +#ifdef ZEND_ENGINE_2
2127 + zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
2130 + if ((SUCCESS != zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) {
2133 + if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(hsv), HTTP_ZAPI_CONST_CAST(char *) key, key_len + 1, (void *) &var))) {
2136 + if (check && !((Z_TYPE_PP(var) == IS_STRING) && Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
2143 +/* {{{ STATUS http_get_request_body(char **, size_t *) */
2144 +PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC)
2149 + if (SG(request_info).raw_post_data) {
2150 + *length = SG(request_info).raw_post_data_length;
2151 + *body = SG(request_info).raw_post_data;
2154 + *body = estrndup(*body, *length);
2157 + } else if (sapi_module.read_post && !HTTP_G->read_post_data) {
2158 + char *buf = emalloc(4096);
2161 + HTTP_G->read_post_data = 1;
2163 + while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
2164 + SG(read_post_bytes) += len;
2165 + *body = erealloc(*body, *length + len + 1);
2166 + memcpy(*body + *length, buf, len);
2168 + (*body)[*length] = '\0';
2175 + /* check for error */
2182 + SG(request_info).raw_post_data = *body;
2183 + SG(request_info).raw_post_data_length = *length;
2186 + *body = estrndup(*body, *length);
2195 +/* {{{ php_stream *http_get_request_body_stream(void) */
2196 +PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D)
2198 + php_stream *s = NULL;
2200 + if (SG(request_info).raw_post_data) {
2201 + s = php_stream_open_wrapper("php://input", "rb", 0, NULL);
2202 + } else if (sapi_module.read_post && !HTTP_G->read_post_data) {
2203 + HTTP_G->read_post_data = 1;
2205 + if ((s = php_stream_temp_new())) {
2206 + char *buf = emalloc(4096);
2209 + while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
2210 + php_stream_write(s, buf, len);
2218 + php_stream_close(s);
2221 + php_stream_rewind(s);
2230 +/* {{{ void http_parse_params_default_callback(...) */
2231 +PHP_HTTP_API void _http_parse_params_default_callback(void *arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
2235 + HashTable *ht = (HashTable *) arg;
2238 + INIT_ZARR(tmp, ht);
2241 + MAKE_STD_ZVAL(entry);
2242 + array_init(entry);
2244 + kdup = estrndup(key, keylen);
2245 + add_assoc_stringl_ex(entry, kdup, keylen + 1, (char *) val, vallen, 1);
2248 + add_next_index_stringl(entry, (char *) val, vallen, 1);
2250 + add_next_index_zval(&tmp, entry);
2252 + add_next_index_stringl(&tmp, (char *) key, keylen, 1);
2258 +/* {{{ STATUS http_parse_params(const char *, HashTable *) */
2259 +PHP_HTTP_API STATUS _http_parse_params_ex(const char *param, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC)
2264 +#define ST_ASSIGN 4
2267 + int st = ST_KEY, keylen = 0, vallen = 0;
2268 + char *s, *c, *key = NULL, *val = NULL;
2270 + for(c = s = estrdup(param);;) {
2274 + char *tk = NULL, *tv = NULL;
2278 + tk= estrndup(key, keylen);
2280 + tk = ecalloc(1, 7);
2281 + memcpy(tk, key, 3);
2282 + tk[3]='.'; tk[4]='.'; tk[5]='.';
2287 + tv = estrndup(val, vallen);
2289 + tv = ecalloc(1, 7);
2290 + memcpy(tv, val, 3);
2291 + tv[3]='.'; tv[4]='.'; tv[5]='.';
2294 + fprintf(stderr, "[%6s] %c \"%s=%s\"\n",
2296 + st == ST_QUOTE ? "QUOTE" :
2297 + st == ST_VALUE ? "VALUE" :
2298 + st == ST_KEY ? "KEY" :
2299 + st == ST_ASSIGN ? "ASSIGN" :
2300 + st == ST_ADD ? "ADD":
2302 + ), *c?*c:'0', tk, tv
2304 + STR_FREE(tk); STR_FREE(tv);
2311 + if (*(c-1) == '\\') {
2312 + memmove(c-1, c, strlen(c)+1);
2344 + if (flags & HTTP_PARAMS_ALLOW_COMMA) {
2358 + if (flags & HTTP_PARAMS_ALLOW_COMMA) {
2380 + keylen = c-- - key;
2386 + if (!(flags & HTTP_PARAMS_COLON_SEPARATOR)) {
2387 + goto not_separator;
2398 + if (flags & HTTP_PARAMS_COLON_SEPARATOR) {
2399 + goto not_separator;
2421 + } else if (!*c || *c == ';' || ((flags & HTTP_PARAMS_ALLOW_COMMA) && *c == ',')) {
2423 + } else if (*c != ' ') {
2432 + if (st != ST_QUOTE) {
2433 + while (val[vallen-1] == ' ') --vallen;
2440 + cb(cb_arg, key, keylen, val, vallen TSRMLS_CC);
2444 + keylen = vallen = 0;
2449 + } else if (st == ST_ADD) {
2460 + if (flags & HTTP_PARAMS_RAISE_ERROR) {
2461 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Unexpected character (%c) at pos %tu of %zu", *c, c-s, strlen(s));
2463 + if (flags & HTTP_PARAMS_ALLOW_FAILURE) {
2464 + if (st == ST_KEY) {
2481 +/* {{{ array_join */
2482 +int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
2487 + zval **data = NULL, **value = (zval **) pDest;
2489 + dst = va_arg(args, HashTable *);
2490 + flags = va_arg(args, int);
2492 + if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
2493 + if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
2494 + key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
2495 + zend_hash_find(dst, key, hash_key->nKeyLength, (void *) &data);
2497 + zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data);
2500 + ZVAL_ADDREF(*value);
2502 + add_next_index_zval(http_zset(IS_ARRAY, *data), *value);
2504 + zend_hash_add(dst, key, hash_key->nKeyLength, value, sizeof(zval *), NULL);
2506 + zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, value, sizeof(zval *), NULL);
2514 + return ZEND_HASH_APPLY_KEEP;
2517 +int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
2522 + zval **value = (zval **) pDest;
2524 + dst = va_arg(args, HashTable *);
2525 + flags = va_arg(args, int);
2527 + if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
2528 + ZVAL_ADDREF(*value);
2529 + if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
2530 + key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
2531 + zend_hash_update(dst, key, hash_key->nKeyLength, (void *) value, sizeof(zval *), NULL);
2534 + zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) value, sizeof(zval *), NULL);
2538 + return ZEND_HASH_APPLY_KEEP;
2543 + * Local variables:
2545 + * c-basic-offset: 4
2547 + * vim600: noet sw=4 ts=4 fdm=marker
2548 + * vim<600: noet sw=4 ts=4
2552 +++ b/ext/http/http_cache_api.c
2555 + +--------------------------------------------------------------------+
2557 + +--------------------------------------------------------------------+
2558 + | Redistribution and use in source and binary forms, with or without |
2559 + | modification, are permitted provided that the conditions mentioned |
2560 + | in the accompanying LICENSE file are met. |
2561 + +--------------------------------------------------------------------+
2562 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
2563 + +--------------------------------------------------------------------+
2566 +/* $Id: http_cache_api.c 292841 2009-12-31 08:48:57Z mike $ */
2568 +#define HTTP_WANT_SAPI
2569 +#include "php_http.h"
2571 +#include "php_output.h"
2572 +#include "php_streams.h"
2574 +#include "php_http_api.h"
2575 +#include "php_http_cache_api.h"
2576 +#include "php_http_date_api.h"
2577 +#include "php_http_send_api.h"
2579 +/* {{{ char *http_etag(void *, size_t, http_send_mode) */
2580 +PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC)
2582 + void *ctx = http_etag_init();
2584 + if (data_mode == SEND_DATA) {
2585 + http_etag_update(ctx, data_ptr, data_len);
2587 + STATUS ss = FAILURE;
2588 + php_stream_statbuf ssb;
2590 + if (data_mode == SEND_RSRC) {
2591 + ss = php_stream_stat((php_stream *) data_ptr, &ssb);
2593 + ss = php_stream_stat_path((char *) data_ptr, &ssb);
2596 + if (SUCCESS != ss) {
2601 + char ssb_buf[128];
2603 + ssb_len = snprintf(ssb_buf, sizeof(ssb_buf), "%ld=%ld=%ld", (long) ssb.sb.st_mtime,
2604 + (long) ssb.sb.st_ino,
2605 + (long) ssb.sb.st_size);
2606 + http_etag_update(ctx, ssb_buf, ssb_len);
2610 + return http_etag_finish(ctx);
2614 +/* {{{ time_t http_last_modified(void *, http_send_mode) */
2615 +PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC)
2617 + php_stream_statbuf ssb;
2619 + switch (data_mode) {
2620 + case SEND_DATA: return HTTP_G->request.time;
2621 + case SEND_RSRC: return php_stream_stat((php_stream *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime;
2622 + default: return php_stream_stat_path((char *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime;
2627 +/* {{{ zend_bool http_match_last_modified(char *, time_t) */
2628 +PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC)
2632 + char *modified, *chr_ptr;
2634 + if (!(zmodified = http_get_server_var(entry, 1))) {
2635 + return !enforce_presence;
2638 + modified = estrndup(Z_STRVAL_P(zmodified), Z_STRLEN_P(zmodified));
2639 + if ((chr_ptr = strrchr(modified, ';'))) {
2643 + retval = (t <= http_parse_date_ex(modified, 1));
2649 +/* {{{ zend_bool http_match_etag(char *, char *) */
2650 +PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC)
2653 + char *quoted_etag;
2656 + if (!(zetag = http_get_server_var_ex(entry, strlen(entry)+1, 1))) {
2657 + return !enforce_presence;
2660 + if (NULL != strchr(Z_STRVAL_P(zetag), '*')) {
2664 + spprintf("ed_etag, 0, "\"%s\"", etag);
2665 + if (!strchr(Z_STRVAL_P(zetag), ',')) {
2666 + result = !strcmp(Z_STRVAL_P(zetag), quoted_etag);
2668 + result = (NULL != strstr(Z_STRVAL_P(zetag), quoted_etag));
2670 + efree(quoted_etag);
2676 +/* {{{ STATUS http_cache_last_modified(time_t, time_t, char *, size_t) */
2677 +PHP_HTTP_API STATUS _http_cache_last_modified(time_t last_modified,
2678 + time_t send_modified, const char *cache_control, size_t cc_len TSRMLS_DC)
2680 + char *sent_header = NULL;
2682 + if (SG(headers_sent)) {
2686 + if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
2690 + if (SUCCESS != http_send_last_modified_ex(send_modified, &sent_header)) {
2694 + if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", last_modified)) {
2695 + http_exit_ex(304, sent_header, NULL, 0);
2697 + STR_FREE(sent_header);
2704 +/* {{{ STATUS http_cache_etag(char *, size_t, char *, size_t) */
2705 +PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len,
2706 + const char *cache_control, size_t cc_len TSRMLS_DC)
2708 + char *sent_header = NULL;
2710 + if (SG(headers_sent)) {
2714 + if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
2719 + if (SUCCESS != http_send_etag_ex(etag, etag_len, &sent_header)) {
2722 + if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
2723 + http_exit_ex(304, sent_header, NULL, 0);
2725 + STR_FREE(sent_header);
2730 + /* start ob_etaghandler */
2731 + return http_start_ob_etaghandler();
2735 +PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D)
2737 + /* already running? */
2738 + if (php_ob_handler_used("ob_etaghandler" TSRMLS_CC)) {
2739 + http_error(HE_WARNING, HTTP_E_RUNTIME, "ob_etaghandler can only be used once");
2743 + HTTP_G->etag.started = 1;
2744 + return php_start_ob_buffer_named("ob_etaghandler", HTTP_G->send.buffer_size, 0 TSRMLS_CC);
2747 +PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D)
2749 + if (HTTP_G->etag.started) {
2750 + HTTP_G->etag.started = 0;
2751 + if (HTTP_G->etag.ctx) {
2752 + efree(HTTP_G->etag.ctx);
2753 + HTTP_G->etag.ctx = NULL;
2760 +/* {{{ void http_ob_etaghandler(char *, uint, char **, uint *, int) */
2761 +void _http_ob_etaghandler(char *output, uint output_len,
2762 + char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
2765 + *handled_output_len = output_len;
2766 + *handled_output = estrndup(output, output_len);
2768 + /* are we supposed to run? */
2769 + if (HTTP_G->etag.started) {
2770 + /* initialize the etag context */
2771 + if (mode & PHP_OUTPUT_HANDLER_START) {
2772 + HTTP_G->etag.ctx = http_etag_init();
2776 + http_etag_update(HTTP_G->etag.ctx, output, output_len);
2779 + if (mode & PHP_OUTPUT_HANDLER_END) {
2780 + char *sent_header = NULL;
2781 + char *etag = http_etag_finish(HTTP_G->etag.ctx);
2783 + HTTP_G->etag.ctx = NULL;
2785 + http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
2786 + http_send_etag_ex(etag, strlen(etag), &sent_header);
2788 + if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
2789 + /* force exit; ob within ob does not work */
2790 + HTTP_G->force_exit = 1;
2791 + http_exit_ex(304, sent_header, etag, 0);
2794 + STR_FREE(sent_header);
2802 + * Local variables:
2804 + * c-basic-offset: 4
2806 + * vim600: sw=4 ts=4 fdm=marker
2807 + * vim<600: sw=4 ts=4
2811 +++ b/ext/http/http_cookie_api.c
2814 + +--------------------------------------------------------------------+
2816 + +--------------------------------------------------------------------+
2817 + | Redistribution and use in source and binary forms, with or without |
2818 + | modification, are permitted provided that the conditions mentioned |
2819 + | in the accompanying LICENSE file are met. |
2820 + +--------------------------------------------------------------------+
2821 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
2822 + +--------------------------------------------------------------------+
2825 +/* $Id: http_cookie_api.c 298662 2010-04-27 13:42:32Z mike $ */
2827 +#include "php_http.h"
2828 +#include "php_http_api.h"
2829 +#include "php_http_date_api.h"
2830 +#include "php_http_cookie_api.h"
2832 +#include "ext/standard/url.h"
2834 +/* {{{ PHP_MINIT_FUNCTION(http_cookie) */
2835 +PHP_MINIT_FUNCTION(http_cookie)
2837 + HTTP_LONG_CONSTANT("HTTP_COOKIE_PARSE_RAW", HTTP_COOKIE_PARSE_RAW);
2838 + HTTP_LONG_CONSTANT("HTTP_COOKIE_SECURE", HTTP_COOKIE_SECURE);
2839 + HTTP_LONG_CONSTANT("HTTP_COOKIE_HTTPONLY", HTTP_COOKIE_HTTPONLY);
2845 +/* {{{ http_cookie_list *http_cookie_list_init(http_cookie_list *) */
2846 +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)
2849 + list = emalloc_rel(sizeof(http_cookie_list));
2852 + zend_hash_init(&list->cookies, 0, NULL, ZVAL_PTR_DTOR, 0);
2853 + zend_hash_init(&list->extras, 0, NULL, ZVAL_PTR_DTOR, 0);
2855 + list->path = NULL;
2856 + list->domain = NULL;
2857 + list->expires = 0;
2864 +/* {{{ void http_cookie_list_dtor(http_cookie_list *) */
2865 +PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC)
2868 + zend_hash_destroy(&list->cookies);
2869 + zend_hash_destroy(&list->extras);
2871 + STR_SET(list->path, NULL);
2872 + STR_SET(list->domain, NULL);
2877 +/* {{{ void http_cookie_list_free(http_cookie_list **) */
2878 +PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC)
2881 + http_cookie_list_dtor(*list);
2888 +/* {{{ const char *http_cookie_list_get_cookie(http_cookie_list *, const char*, size_t) */
2889 +PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC)
2891 + zval **cookie = NULL;
2892 + if ((SUCCESS != zend_hash_find(&list->cookies, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &cookie)) || (Z_TYPE_PP(cookie) != IS_STRING)) {
2895 + return Z_STRVAL_PP(cookie);
2899 +/* {{{ const char *http_cookie_list_get_extra(http_cookie_list *, const char *, size_t) */
2900 +PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC)
2902 + zval **extra = NULL;
2903 + if ((SUCCESS != zend_hash_find(&list->extras, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &extra)) || (Z_TYPE_PP(extra) != IS_STRING)) {
2906 + return Z_STRVAL_PP(extra);
2910 +/* {{{ void http_cookie_list_add_cookie(http_cookie_list *, const char *, size_t, const char *, size_t) */
2911 +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)
2913 + zval *cookie_value;
2914 + char *key = estrndup(name, name_len);
2915 + MAKE_STD_ZVAL(cookie_value);
2916 + ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
2917 + zend_hash_update(&list->cookies, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
2922 +/* {{{ void http_cookie_list_add_extr(http_cookie_list *, const char *, size_t, const char *, size_t) */
2923 +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)
2925 + zval *cookie_value;
2926 + char *key = estrndup(name, name_len);
2927 + MAKE_STD_ZVAL(cookie_value);
2928 + ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
2929 + zend_hash_update(&list->extras, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
2934 +typedef struct _http_parse_param_cb_arg_t {
2935 + http_cookie_list *list;
2937 + char **allowed_extras;
2938 +} http_parse_param_cb_arg;
2940 +/* {{{ static void http_parse_cookie_callback */
2941 +static void http_parse_cookie_callback(void *ptr, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
2943 + http_parse_param_cb_arg *arg = (http_parse_param_cb_arg *) ptr;
2945 +#define _KEY_IS(s) (keylen == lenof(s) && !strncasecmp(key, (s), keylen))
2946 + if _KEY_IS("path") {
2947 + STR_SET(arg->list->path, estrndup(val, vallen));
2948 + } else if _KEY_IS("domain") {
2949 + STR_SET(arg->list->domain, estrndup(val, vallen));
2950 + } else if _KEY_IS("expires") {
2951 + char *date = estrndup(val, vallen);
2952 + arg->list->expires = http_parse_date(date);
2954 + } else if _KEY_IS("secure") {
2955 + arg->list->flags |= HTTP_COOKIE_SECURE;
2956 + } else if _KEY_IS("httpOnly") {
2957 + arg->list->flags |= HTTP_COOKIE_HTTPONLY;
2959 + /* check for extra */
2960 + if (arg->allowed_extras) {
2961 + char **ae = arg->allowed_extras;
2963 + for (; *ae; ++ae) {
2964 + if ((size_t) keylen == strlen(*ae) && !strncasecmp(key, *ae, keylen)) {
2965 + if (arg->flags & HTTP_COOKIE_PARSE_RAW) {
2966 + http_cookie_list_add_extra(arg->list, key, keylen, val, vallen);
2968 + char *dec = estrndup(val, vallen);
2969 + int declen = php_url_decode(dec, vallen);
2971 + http_cookie_list_add_extra(arg->list, key, keylen, dec, declen);
2979 + if (arg->flags & HTTP_COOKIE_PARSE_RAW) {
2980 + http_cookie_list_add_cookie(arg->list, key, keylen, val, vallen);
2982 + char *dec = estrndup(val, vallen);
2983 + int declen = php_url_decode(dec, vallen);
2985 + http_cookie_list_add_cookie(arg->list, key, keylen, dec, declen);
2992 +/* {{{ http_cookie_list *http_parse_cookie(char *, long) */
2993 +PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list *list, const char *string, long flags, char **allowed_extras TSRMLS_DC)
2995 + int free_list = !list;
2996 + http_parse_param_cb_arg arg;
2998 + list = http_cookie_list_init(list);
3001 + arg.flags = flags;
3002 + arg.allowed_extras = allowed_extras;
3004 + if (SUCCESS != http_parse_params_ex(string, HTTP_PARAMS_RAISE_ERROR, http_parse_cookie_callback, &arg)) {
3006 + http_cookie_list_free(&list);
3008 + http_cookie_list_dtor(list);
3017 +/* {{{ void http_cookie_list_tostruct(http_cookie_list *, zval *) */
3018 +PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC)
3020 + zval array, *cookies, *extras;
3022 + INIT_ZARR(array, HASH_OF(strct));
3024 + MAKE_STD_ZVAL(cookies);
3025 + array_init(cookies);
3026 + zend_hash_copy(Z_ARRVAL_P(cookies), &list->cookies, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3027 + add_assoc_zval(&array, "cookies", cookies);
3029 + MAKE_STD_ZVAL(extras);
3030 + array_init(extras);
3031 + zend_hash_copy(Z_ARRVAL_P(extras), &list->extras, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3032 + add_assoc_zval(&array, "extras", extras);
3034 + add_assoc_long(&array, "flags", list->flags);
3035 + add_assoc_long(&array, "expires", (long) list->expires);
3036 + add_assoc_string(&array, "path", STR_PTR(list->path), 1);
3037 + add_assoc_string(&array, "domain", STR_PTR(list->domain), 1);
3041 +/* {{{ http_cookie_list *http_cookie_list_fromstruct(http_cookie_list *, zval *strct) */
3042 +PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC)
3045 + HashTable *ht = HASH_OF(strct);
3047 + list = http_cookie_list_init(list);
3049 + if (SUCCESS == zend_hash_find(ht, "cookies", sizeof("cookies"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
3050 + zend_hash_copy(&list->cookies, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3052 + if (SUCCESS == zend_hash_find(ht, "extras", sizeof("extras"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
3053 + zend_hash_copy(&list->extras, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3055 + if (SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &tmp)) {
3056 + switch (Z_TYPE_PP(tmp)) {
3058 + list->flags = Z_LVAL_PP(tmp);
3061 + list->flags = (long) Z_DVAL_PP(tmp);
3064 + cpy = http_zsep(IS_LONG, *tmp);
3065 + list->flags = Z_LVAL_P(cpy);
3066 + zval_ptr_dtor(&cpy);
3072 + if (SUCCESS == zend_hash_find(ht, "expires", sizeof("expires"), (void *) &tmp)) {
3073 + switch (Z_TYPE_PP(tmp)) {
3075 + list->expires = Z_LVAL_PP(tmp);
3078 + list->expires = (long) Z_DVAL_PP(tmp);
3081 + cpy = http_zsep(IS_LONG, *tmp);
3082 + if (Z_LVAL_P(cpy)) {
3083 + list->expires = Z_LVAL_P(cpy);
3085 + time_t expires = http_parse_date(Z_STRVAL_PP(tmp));
3086 + if (expires > 0) {
3087 + list->expires = expires;
3090 + zval_ptr_dtor(&cpy);
3096 + if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
3097 + list->path = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3099 + if (SUCCESS == zend_hash_find(ht, "domain", sizeof("domain"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
3100 + list->domain = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3107 +/* {{{ inline append_encoded */
3108 +static inline void append_encoded(phpstr *buf, const char *key, size_t key_len, const char *val, size_t val_len)
3113 + enc_str[0] = php_url_encode(key, key_len, &enc_len[0]);
3114 + enc_str[1] = php_url_encode(val, val_len, &enc_len[1]);
3116 + phpstr_append(buf, enc_str[0], enc_len[0]);
3117 + phpstr_appends(buf, "=");
3118 + phpstr_append(buf, enc_str[1], enc_len[1]);
3119 + phpstr_appends(buf, "; ");
3121 + efree(enc_str[0]);
3122 + efree(enc_str[1]);
3126 +/* {{{ void http_cookie_list_tostring(http_cookie_list *, char **, size_t *) */
3127 +PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC)
3131 + HashKey key = initHashKey(0);
3134 + phpstr_init(&buf);
3136 + FOREACH_HASH_KEYVAL(pos, &list->cookies, key, val) {
3137 + if (key.type == HASH_KEY_IS_STRING && key.len) {
3138 + zval *tmp = http_zsep(IS_STRING, *val);
3139 + append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
3140 + zval_ptr_dtor(&tmp);
3144 + if (list->domain && *list->domain) {
3145 + phpstr_appendf(&buf, "domain=%s; ", list->domain);
3147 + if (list->path && *list->path) {
3148 + phpstr_appendf(&buf, "path=%s; ", list->path);
3150 + if (list->expires) {
3151 + char *date = http_date(list->expires);
3152 + phpstr_appendf(&buf, "expires=%s; ", date);
3156 + FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) {
3157 + if (key.type == HASH_KEY_IS_STRING && key.len) {
3158 + zval *tmp = http_zsep(IS_STRING, *val);
3159 + append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
3163 + if (list->flags & HTTP_COOKIE_SECURE) {
3164 + phpstr_appends(&buf, "secure; ");
3166 + if (list->flags & HTTP_COOKIE_HTTPONLY) {
3167 + phpstr_appends(&buf, "httpOnly; ");
3171 + *str = PHPSTR_VAL(&buf);
3172 + *len = PHPSTR_LEN(&buf);
3177 + * Local variables:
3179 + * c-basic-offset: 4
3181 + * vim600: noet sw=4 ts=4 fdm=marker
3182 + * vim<600: noet sw=4 ts=4
3185 +++ b/ext/http/http_date_api.c
3188 + +--------------------------------------------------------------------+
3190 + +--------------------------------------------------------------------+
3191 + | Redistribution and use in source and binary forms, with or without |
3192 + | modification, are permitted provided that the conditions mentioned |
3193 + | in the accompanying LICENSE file are met. |
3194 + +--------------------------------------------------------------------+
3195 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
3196 + +--------------------------------------------------------------------+
3199 +/* $Id: http_date_api.c 292841 2009-12-31 08:48:57Z mike $ */
3201 +#include "php_http.h"
3203 +#include "php_http_api.h"
3204 +#include "php_http_date_api.h"
3206 +static inline int check_day(const char *day, size_t len);
3207 +static inline int check_month(const char *month);
3208 +static inline int check_tzone(const char *tzone);
3209 +static inline time_t parse_date(const char *month);
3211 +/* {{{ day/month names */
3212 +static const char *days[] = {
3213 + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
3215 +static const char *wkdays[] = {
3216 + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
3218 +static const char *weekdays[] = {
3219 + "Monday", "Tuesday", "Wednesday",
3220 + "Thursday", "Friday", "Saturday", "Sunday"
3222 +static const char *months[] = {
3223 + "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3224 + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3232 +static const struct time_zone {
3236 + {"GMT", 0}, /* Greenwich Mean */
3237 + {"UTC", 0}, /* Universal (Coordinated) */
3238 + {"WET", 0}, /* Western European */
3239 + {"BST", 0 DS}, /* British Summer */
3240 + {"WAT", 60}, /* West Africa */
3241 + {"AST", 240}, /* Atlantic Standard */
3242 + {"ADT", 240 DS},/* Atlantic Daylight */
3243 + {"EST", 300}, /* Eastern Standard */
3244 + {"EDT", 300 DS},/* Eastern Daylight */
3245 + {"CST", 360}, /* Central Standard */
3246 + {"CDT", 360 DS},/* Central Daylight */
3247 + {"MST", 420}, /* Mountain Standard */
3248 + {"MDT", 420 DS},/* Mountain Daylight */
3249 + {"PST", 480}, /* Pacific Standard */
3250 + {"PDT", 480 DS},/* Pacific Daylight */
3251 + {"YST", 540}, /* Yukon Standard */
3252 + {"YDT", 540 DS},/* Yukon Daylight */
3253 + {"HST", 600}, /* Hawaii Standard */
3254 + {"HDT", 600 DS},/* Hawaii Daylight */
3255 + {"CAT", 600}, /* Central Alaska */
3256 + {"AHST", 600}, /* Alaska-Hawaii Standard */
3257 + {"NT", 660}, /* Nome */
3258 + {"IDLW", 720}, /* International Date Line West */
3259 + {"CET", -60}, /* Central European */
3260 + {"MET", -60}, /* Middle European */
3261 + {"MEWT", -60}, /* Middle European Winter */
3262 + {"MEST", -60 DS},/* Middle European Summer */
3263 + {"CEST", -60 DS},/* Central European Summer */
3264 + {"MESZ", -60 DS},/* Middle European Summer */
3265 + {"FWT", -60}, /* French Winter */
3266 + {"FST", -60 DS},/* French Summer */
3267 + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */
3268 + {"WAST", -420}, /* West Australian Standard */
3269 + {"WADT", -420 DS},/* West Australian Daylight */
3270 + {"CCT", -480}, /* China Coast, USSR Zone 7 */
3271 + {"JST", -540}, /* Japan Standard, USSR Zone 8 */
3272 + {"EAST", -600}, /* Eastern Australian Standard */
3273 + {"EADT", -600 DS},/* Eastern Australian Daylight */
3274 + {"GST", -600}, /* Guam Standard, USSR Zone 9 */
3275 + {"NZT", -720}, /* New Zealand */
3276 + {"NZST", -720}, /* New Zealand Standard */
3277 + {"NZDT", -720 DS},/* New Zealand Daylight */
3278 + {"IDLE", -720}, /* International Date Line East */
3282 +/* {{{ Day/Month/TZ checks for http_parse_date()
3283 + Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
3284 +static inline int check_day(const char *day, size_t len)
3287 + const char * const *check = (len > 3) ? &weekdays[0] : &wkdays[0];
3288 + for (i = 0; i < 7; i++) {
3289 + if (!strcmp(day, check[0])) {
3297 +static inline int check_month(const char *month)
3300 + const char * const *check = &months[0];
3301 + for (i = 0; i < 12; i++) {
3302 + if (!strcmp(month, check[0])) {
3310 +/* return the time zone offset between GMT and the input one, in number
3311 + of seconds or -1 if the timezone wasn't found/legal */
3313 +static inline int check_tzone(const char *tzone)
3316 + const struct time_zone *check = time_zones;
3317 + for (i = 0; i < sizeof(time_zones) / sizeof(time_zones[0]); i++) {
3318 + if (!strcmp(tzone, check->name)) {
3319 + return check->offset * 60;
3327 +/* {{{ char *http_date(time_t) */
3328 +PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC)
3330 + char *date = NULL;
3331 + struct tm *gmtime = NULL, tmbuf;
3333 + memset(&tmbuf, 0, sizeof(tmbuf));
3334 + if ((gmtime = php_gmtime_r(&t, &tmbuf))) {
3335 + spprintf(&date, 0,
3336 + "%s, %02d %s %04d %02d:%02d:%02d GMT",
3337 + days[gmtime->tm_wday], gmtime->tm_mday,
3338 + months[gmtime->tm_mon], gmtime->tm_year + 1900,
3339 + gmtime->tm_hour, gmtime->tm_min, gmtime->tm_sec
3347 +/* {{{ time_t http_parse_date(char *) */
3348 +PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC)
3350 + time_t t = parse_date(date);
3352 + if (-1 == t && !silent) {
3353 + http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Could not parse date: %s", date);
3360 +/* time_t parse_date(char *)
3361 + Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
3362 +static inline time_t parse_date(const char *date)
3365 + int tz_offset = -1, year = -1, month = -1, monthday = -1, weekday = -1,
3366 + hours = -1, minutes = -1, seconds = -1;
3368 + enum assume_next dignext = DATE_MDAY;
3369 + const char *indate = date;
3371 + int part = 0; /* max 6 parts */
3373 + while (*date && (part < 6)) {
3376 + while (*date && !HTTP_IS_CTYPE(alnum, *date)) {
3380 + if (HTTP_IS_CTYPE(alpha, *date)) {
3381 + /* a name coming up */
3382 + char buf[32] = "";
3384 + sscanf(date, "%31[A-Za-z]", buf);
3385 + len = strlen(buf);
3387 + if (weekday == -1) {
3388 + weekday = check_day(buf, len);
3389 + if (weekday != -1) {
3394 + if (!found && (month == -1)) {
3395 + month = check_month(buf);
3396 + if (month != -1) {
3401 + if (!found && (tz_offset == -1)) {
3402 + /* this just must be a time zone string */
3403 + tz_offset = check_tzone(buf);
3404 + if (tz_offset != -1) {
3410 + return -1; /* bad string */
3414 + else if (HTTP_IS_CTYPE(digit, *date)) {
3418 + if ((seconds == -1) &&
3419 + (3 == sscanf(date, "%02d:%02d:%02d", &hours, &minutes, &seconds))) {
3425 + val = (int) strtol(date, &end, 10);
3427 + if ((tz_offset == -1) && ((end - date) == 4) && (val < 1300) &&
3428 + (indate < date) && ((date[-1] == '+' || date[-1] == '-'))) {
3429 + /* four digits and a value less than 1300 and it is preceeded with
3430 + a plus or minus. This is a time zone indication. */
3432 + tz_offset = (val / 100 * 60 + val % 100) * 60;
3434 + /* the + and - prefix indicates the local time compared to GMT,
3435 + this we need ther reversed math to get what we want */
3436 + tz_offset = date[-1] == '+' ? -tz_offset : tz_offset;
3439 + if (((end - date) == 8) && (year == -1) && (month == -1) && (monthday == -1)) {
3440 + /* 8 digits, no year, month or day yet. This is YYYYMMDD */
3442 + year = val / 10000;
3443 + month = (val % 10000) / 100 - 1; /* month is 0 - 11 */
3444 + monthday = val % 100;
3447 + if (!found && (dignext == DATE_MDAY) && (monthday == -1)) {
3448 + if ((val > 0) && (val < 32)) {
3452 + dignext = DATE_YEAR;
3455 + if (!found && (dignext == DATE_YEAR) && (year == -1)) {
3458 + if (year < 1900) {
3459 + year += year > 70 ? 1900 : 2000;
3461 + if(monthday == -1) {
3462 + dignext = DATE_MDAY;
3477 + if (-1 == seconds) {
3478 + seconds = minutes = hours = 0; /* no time, make it zero */
3481 + if ((-1 == monthday) || (-1 == month) || (-1 == year)) {
3482 + /* lacks vital info, fail */
3486 + if (sizeof(time_t) < 5) {
3487 + /* 32 bit time_t can only hold dates to the beginning of 2038 */
3488 + if (year > 2037) {
3489 + return 0x7fffffff;
3493 + tm.tm_sec = seconds;
3494 + tm.tm_min = minutes;
3495 + tm.tm_hour = hours;
3496 + tm.tm_mday = monthday;
3497 + tm.tm_mon = month;
3498 + tm.tm_year = year - 1900;
3505 + /* time zone adjust */
3507 + struct tm *gmt, keeptime2;
3511 + if((gmt = php_gmtime_r(&t, &keeptime2))) {
3512 + tm = *gmt; /* MSVC quirks */
3514 + return -1; /* illegal date/time */
3519 + /* Add the time zone diff (between the given timezone and GMT) and the
3520 + diff between the local time zone and GMT. */
3521 + delta = (tz_offset != -1 ? tz_offset : 0) + (t - t2);
3523 + if((delta > 0) && (t + delta < t)) {
3524 + return -1; /* time_t overflow */
3536 + * Local variables:
3538 + * c-basic-offset: 4
3540 + * vim600: sw=4 ts=4 fdm=marker
3541 + * vim<600: sw=4 ts=4
3545 +++ b/ext/http/http_deflatestream_object.c
3548 + +--------------------------------------------------------------------+
3550 + +--------------------------------------------------------------------+
3551 + | Redistribution and use in source and binary forms, with or without |
3552 + | modification, are permitted provided that the conditions mentioned |
3553 + | in the accompanying LICENSE file are met. |
3554 + +--------------------------------------------------------------------+
3555 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
3556 + +--------------------------------------------------------------------+
3559 +/* $Id: http_deflatestream_object.c 300299 2010-06-09 06:23:16Z mike $ */
3561 +#define HTTP_WANT_ZLIB
3562 +#include "php_http.h"
3564 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB)
3566 +#include "php_http_api.h"
3567 +#include "php_http_encoding_api.h"
3568 +#include "php_http_exception_object.h"
3569 +#include "php_http_deflatestream_object.h"
3571 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpDeflateStream, method, 0, req_args)
3572 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpDeflateStream, method, 0)
3573 +#define HTTP_DEFLATE_ME(method, visibility) PHP_ME(HttpDeflateStream, method, HTTP_ARGS(HttpDeflateStream, method), visibility)
3575 +HTTP_BEGIN_ARGS(__construct, 0)
3576 + HTTP_ARG_VAL(flags, 0)
3579 +HTTP_BEGIN_ARGS(factory, 0)
3580 + HTTP_ARG_VAL(flags, 0)
3581 + HTTP_ARG_VAL(class_name, 0)
3584 +HTTP_BEGIN_ARGS(update, 1)
3585 + HTTP_ARG_VAL(data, 0)
3588 +HTTP_BEGIN_ARGS(flush, 0)
3589 + HTTP_ARG_VAL(data, 0)
3592 +HTTP_BEGIN_ARGS(finish, 0)
3593 + HTTP_ARG_VAL(data, 0)
3596 +#define THIS_CE http_deflatestream_object_ce
3597 +zend_class_entry *http_deflatestream_object_ce;
3598 +zend_function_entry http_deflatestream_object_fe[] = {
3599 + HTTP_DEFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
3600 + HTTP_DEFLATE_ME(update, ZEND_ACC_PUBLIC)
3601 + HTTP_DEFLATE_ME(flush, ZEND_ACC_PUBLIC)
3602 + HTTP_DEFLATE_ME(finish, ZEND_ACC_PUBLIC)
3604 + HTTP_DEFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
3606 + EMPTY_FUNCTION_ENTRY
3608 +static zend_object_handlers http_deflatestream_object_handlers;
3610 +PHP_MINIT_FUNCTION(http_deflatestream_object)
3612 + HTTP_REGISTER_CLASS_EX(HttpDeflateStream, http_deflatestream_object, NULL, 0);
3613 + http_deflatestream_object_handlers.clone_obj = _http_deflatestream_object_clone_obj;
3616 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_GZIP")-1, HTTP_DEFLATE_TYPE_GZIP TSRMLS_CC);
3617 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ZLIB")-1, HTTP_DEFLATE_TYPE_ZLIB TSRMLS_CC);
3618 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RAW")-1, HTTP_DEFLATE_TYPE_RAW TSRMLS_CC);
3619 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_DEF")-1, HTTP_DEFLATE_LEVEL_DEF TSRMLS_CC);
3620 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MIN")-1, HTTP_DEFLATE_LEVEL_MIN TSRMLS_CC);
3621 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MAX")-1, HTTP_DEFLATE_LEVEL_MAX TSRMLS_CC);
3622 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_DEF")-1, HTTP_DEFLATE_STRATEGY_DEF TSRMLS_CC);
3623 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FILT")-1, HTTP_DEFLATE_STRATEGY_FILT TSRMLS_CC);
3624 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_HUFF")-1, HTTP_DEFLATE_STRATEGY_HUFF TSRMLS_CC);
3625 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_RLE")-1, HTTP_DEFLATE_STRATEGY_RLE TSRMLS_CC);
3626 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FIXED")-1, HTTP_DEFLATE_STRATEGY_FIXED TSRMLS_CC);
3627 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
3628 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
3629 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
3635 +zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
3637 + return http_deflatestream_object_new_ex(ce, NULL, NULL);
3640 +zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC)
3642 + zend_object_value ov;
3643 + http_deflatestream_object *o;
3645 + o = ecalloc(1, sizeof(http_deflatestream_object));
3656 + ALLOC_HASHTABLE(OBJ_PROP(o));
3657 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
3658 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3660 + ov.handle = putObject(http_deflatestream_object, o);
3661 + ov.handlers = &http_deflatestream_object_handlers;
3666 +zend_object_value _http_deflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
3668 + http_encoding_stream *s;
3669 + zend_object_value new_ov;
3670 + http_deflatestream_object *new_obj = NULL;
3671 + getObject(http_deflatestream_object, old_obj);
3673 + s = ecalloc(1, sizeof(http_encoding_stream));
3674 + s->flags = old_obj->stream->flags;
3675 + deflateCopy(&s->stream, &old_obj->stream->stream);
3676 + s->stream.opaque = phpstr_dup(s->stream.opaque);
3678 + new_ov = http_deflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
3679 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
3684 +void _http_deflatestream_object_free(zend_object *object TSRMLS_DC)
3686 + http_deflatestream_object *o = (http_deflatestream_object *) object;
3689 + http_encoding_deflate_stream_free(&o->stream);
3694 +/* {{{ proto void HttpDeflateStream::__construct([int flags = 0])
3695 + Creates a new HttpDeflateStream object instance. */
3696 +PHP_METHOD(HttpDeflateStream, __construct)
3700 + SET_EH_THROW_HTTP();
3701 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
3702 + getObject(http_deflatestream_object, obj);
3704 + if (!obj->stream) {
3705 + obj->stream = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
3707 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpDeflateStream cannot be initialized twice");
3714 +/* {{{ proto HttpDeflateStream HttpDeflateStream::factory([int flags[, string class = "HttpDeflateStream"]])
3715 + Creates a new HttpDeflateStream object instance. */
3716 +PHP_METHOD(HttpDeflateStream, factory)
3722 + SET_EH_THROW_HTTP();
3723 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
3724 + zend_object_value ov;
3725 + http_encoding_stream *s = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
3727 + if (SUCCESS == http_object_new(&ov, cn, cl, _http_deflatestream_object_new_ex, http_deflatestream_object_ce, s, NULL)) {
3728 + RETVAL_OBJVAL(ov, 0);
3735 +/* {{{ proto string HttpDeflateStream::update(string data)
3736 + Passes more data through the deflate stream. */
3737 +PHP_METHOD(HttpDeflateStream, update)
3740 + size_t encoded_len = 0;
3741 + char *data, *encoded = NULL;
3742 + getObject(http_deflatestream_object, obj);
3744 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
3748 + if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
3752 + if (SUCCESS == http_encoding_deflate_stream_update(obj->stream, data, data_len, &encoded, &encoded_len)) {
3753 + RETURN_STRINGL(encoded, encoded_len, 0);
3760 +/* {{{ proto string HttpDeflateStream::flush([string data])
3761 + Flushes the deflate stream. */
3762 +PHP_METHOD(HttpDeflateStream, flush)
3765 + size_t updated_len = 0, encoded_len = 0;
3766 + char *updated = NULL, *encoded = NULL, *data = NULL;
3767 + getObject(http_deflatestream_object, obj);
3769 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
3773 + if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
3778 + if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
3783 + if (SUCCESS == http_encoding_deflate_stream_flush(obj->stream, &encoded, &encoded_len)) {
3784 + if (updated_len) {
3785 + updated = erealloc(updated, updated_len + encoded_len + 1);
3786 + updated[updated_len + encoded_len] = '\0';
3787 + memcpy(updated + updated_len, encoded, encoded_len);
3788 + STR_FREE(encoded);
3789 + updated_len += encoded_len;
3790 + RETURN_STRINGL(updated, updated_len, 0);
3791 + } else if (encoded) {
3792 + RETVAL_STRINGL(encoded, encoded_len, 0);
3799 + STR_FREE(updated);
3803 +/* {{{ proto string HttpDeflateStream::finish([string data])
3804 + Finalizes the deflate stream. The deflate stream can be reused after finalizing. */
3805 +PHP_METHOD(HttpDeflateStream, finish)
3808 + size_t updated_len = 0, encoded_len = 0;
3809 + char *updated = NULL, *encoded = NULL, *data = NULL;
3810 + getObject(http_deflatestream_object, obj);
3812 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
3816 + if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
3821 + if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
3826 + if (SUCCESS == http_encoding_deflate_stream_finish(obj->stream, &encoded, &encoded_len)) {
3827 + if (updated_len) {
3828 + updated = erealloc(updated, updated_len + encoded_len + 1);
3829 + updated[updated_len + encoded_len] = '\0';
3830 + memcpy(updated + updated_len, encoded, encoded_len);
3831 + STR_FREE(encoded);
3832 + updated_len += encoded_len;
3833 + RETVAL_STRINGL(updated, updated_len, 0);
3835 + STR_FREE(updated);
3836 + RETVAL_STRINGL(encoded, encoded_len, 0);
3839 + STR_FREE(updated);
3843 + http_encoding_deflate_stream_dtor(obj->stream);
3844 + http_encoding_deflate_stream_init(obj->stream, obj->stream->flags);
3848 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
3851 + * Local variables:
3853 + * c-basic-offset: 4
3855 + * vim600: noet sw=4 ts=4 fdm=marker
3856 + * vim<600: noet sw=4 ts=4
3860 +++ b/ext/http/http_encoding_api.c
3863 + +--------------------------------------------------------------------+
3865 + +--------------------------------------------------------------------+
3866 + | Redistribution and use in source and binary forms, with or without |
3867 + | modification, are permitted provided that the conditions mentioned |
3868 + | in the accompanying LICENSE file are met. |
3869 + +--------------------------------------------------------------------+
3870 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
3871 + +--------------------------------------------------------------------+
3874 +/* $Id: http_encoding_api.c 305668 2010-11-22 20:17:41Z iliaa $ */
3876 +#define HTTP_WANT_ZLIB
3877 +#include "php_http.h"
3879 +#include "php_http_api.h"
3880 +#include "php_http_encoding_api.h"
3881 +#include "php_http_send_api.h"
3882 +#include "php_http_headers_api.h"
3885 +#ifdef HTTP_HAVE_ZLIB
3886 +PHP_MINIT_FUNCTION(http_encoding)
3888 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_DEF", HTTP_DEFLATE_LEVEL_DEF);
3889 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MIN", HTTP_DEFLATE_LEVEL_MIN);
3890 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MAX", HTTP_DEFLATE_LEVEL_MAX);
3891 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_ZLIB", HTTP_DEFLATE_TYPE_ZLIB);
3892 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_GZIP", HTTP_DEFLATE_TYPE_GZIP);
3893 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_RAW", HTTP_DEFLATE_TYPE_RAW);
3894 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_DEF", HTTP_DEFLATE_STRATEGY_DEF);
3895 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FILT", HTTP_DEFLATE_STRATEGY_FILT);
3896 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_HUFF", HTTP_DEFLATE_STRATEGY_HUFF);
3897 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_RLE", HTTP_DEFLATE_STRATEGY_RLE);
3898 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FIXED", HTTP_DEFLATE_STRATEGY_FIXED);
3900 + HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_NONE", HTTP_ENCODING_STREAM_FLUSH_NONE);
3901 + HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_SYNC", HTTP_ENCODING_STREAM_FLUSH_SYNC);
3902 + HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_FULL", HTTP_ENCODING_STREAM_FLUSH_FULL);
3907 +PHP_RINIT_FUNCTION(http_encoding)
3909 + if (HTTP_G->send.inflate.start_auto) {
3910 + php_ob_set_internal_handler(_http_ob_inflatehandler, HTTP_INFLATE_BUFFER_SIZE, "http inflate", 0 TSRMLS_CC);
3912 + if (HTTP_G->send.deflate.start_auto) {
3913 + php_ob_set_internal_handler(_http_ob_deflatehandler, HTTP_DEFLATE_BUFFER_SIZE, "http deflate", 0 TSRMLS_CC);
3918 +PHP_RSHUTDOWN_FUNCTION(http_encoding)
3920 + if (HTTP_G->send.deflate.stream) {
3921 + http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream);
3923 + if (HTTP_G->send.inflate.stream) {
3924 + http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream);
3931 +/* {{{ eol_match(char **, int *) */
3932 +static inline int eol_match(char **line, int *eol_len)
3934 + char *ptr = *line;
3936 + while (' ' == *ptr) ++ptr;
3938 + if (ptr == http_locate_eol(*line, eol_len)) {
3947 +/* {{{ char *http_encoding_dechunk(char *, size_t, char **, size_t *) */
3948 +PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
3951 + char *n_ptr = NULL;
3952 + const char *e_ptr = encoded;
3955 + *decoded = ecalloc(1, encoded_len);
3957 + while ((encoded + encoded_len - e_ptr) > 0) {
3958 + ulong chunk_len = 0, rest;
3960 + chunk_len = strtoul(e_ptr, &n_ptr, 16);
3962 + /* we could not read in chunk size */
3963 + if (n_ptr == e_ptr) {
3965 + * if this is the first turn and there doesn't seem to be a chunk
3966 + * size at the begining of the body, do not fail on apparently
3967 + * not encoded data and return a copy
3969 + if (e_ptr == encoded) {
3970 + http_error(HE_NOTICE, HTTP_E_ENCODING, "Data does not seem to be chunked encoded");
3971 + memcpy(*decoded, encoded, encoded_len);
3972 + *decoded_len = encoded_len;
3973 + return encoded + encoded_len;
3976 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected chunk size at pos %tu of %zu but got trash", n_ptr - encoded, encoded_len);
3981 + /* reached the end */
3983 + /* move over '0' chunked encoding terminator */
3984 + while (*e_ptr == '0') ++e_ptr;
3988 + /* there should be CRLF after the chunk size, but we'll ignore SP+ too */
3989 + if (*n_ptr && !eol_match(&n_ptr, &eol_len)) {
3990 + if (eol_len == 2) {
3991 + 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));
3993 + 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);
3998 + /* chunk size pretends more data than we actually got, so it's probably a truncated message */
3999 + if (chunk_len > (rest = encoded + encoded_len - n_ptr)) {
4000 + 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);
4004 + /* copy the chunk */
4005 + memcpy(*decoded + *decoded_len, n_ptr, chunk_len);
4006 + *decoded_len += chunk_len;
4008 + if (chunk_len == rest) {
4009 + e_ptr = n_ptr + chunk_len;
4012 + /* advance to next chunk */
4013 + e_ptr = n_ptr + chunk_len + eol_len;
4021 +/* {{{ int http_encoding_response_start(size_t) */
4022 +PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC)
4024 + int response = HTTP_G->send.deflate.response;
4025 + int ohandler = php_ob_handler_used("ob_gzhandler" TSRMLS_CC) || php_ob_handler_used("zlib output compression" TSRMLS_CC);
4027 + if (!ohandler && !ignore_http_ohandler) {
4028 + ohandler = php_ob_handler_used("ob_deflatehandler" TSRMLS_CC) || php_ob_handler_used("http deflate" TSRMLS_CC);
4031 + if (response && !ohandler) {
4032 +#ifdef HTTP_HAVE_ZLIB
4033 + HashTable *selected;
4036 + HTTP_G->send.deflate.encoding = 0;
4038 + INIT_PZVAL(&zsupported);
4039 + array_init(&zsupported);
4040 + add_next_index_stringl(&zsupported, "gzip", lenof("gzip"), 1);
4041 + add_next_index_stringl(&zsupported, "x-gzip", lenof("x-gzip"), 1);
4042 + add_next_index_stringl(&zsupported, "deflate", lenof("deflate"), 1);
4044 + if ((selected = http_negotiate_encoding(&zsupported))) {
4045 + STATUS hs = FAILURE;
4046 + char *encoding = NULL;
4049 + if (HASH_KEY_IS_STRING == zend_hash_get_current_key(selected, &encoding, &idx, 0) && encoding) {
4050 + if (!strcmp(encoding, "gzip") || !strcmp(encoding, "x-gzip")) {
4051 + if (SUCCESS == (hs = http_send_header_string("Content-Encoding: gzip"))) {
4052 + HTTP_G->send.deflate.encoding = HTTP_ENCODING_GZIP;
4054 + } else if (!strcmp(encoding, "deflate")) {
4055 + if (SUCCESS == (hs = http_send_header_string("Content-Encoding: deflate"))) {
4056 + HTTP_G->send.deflate.encoding = HTTP_ENCODING_DEFLATE;
4059 + if (SUCCESS == hs) {
4060 + http_send_header_string("Vary: Accept-Encoding");
4064 + zend_hash_destroy(selected);
4065 + FREE_HASHTABLE(selected);
4068 + zval_dtor(&zsupported);
4070 + HTTP_G->send.deflate.encoding = 0;
4071 + php_start_ob_buffer_named("ob_gzhandler", 0, 0 TSRMLS_CC);
4072 +#endif /* HTTP_HAVE_ZLIB */
4073 + } else if (content_length && !ohandler) {
4074 + /* emit a content-length header */
4077 + phpstr_init(&header);
4078 + phpstr_appendf(&header, "Content-Length: %zu", content_length);
4079 + phpstr_fix(&header);
4080 + http_send_header_string_ex(PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
4081 + phpstr_dtor(&header);
4083 + HTTP_G->send.deflate.encoding = 0;
4086 + return HTTP_G->send.deflate.encoding;
4090 +#ifdef HTTP_HAVE_ZLIB
4092 +/* {{{ inline int http_inflate_rounds */
4093 +static inline int http_inflate_rounds(z_stream *Z, int flush, char **buf, size_t *len)
4095 + int status = 0, round = 0;
4101 + phpstr_init_ex(&buffer, Z->avail_in, PHPSTR_INIT_PREALLOC);
4104 + if (PHPSTR_NOMEM == phpstr_resize_ex(&buffer, buffer.size, 0, 1)) {
4105 + status = Z_MEM_ERROR;
4107 + Z->avail_out = buffer.free;
4108 + Z->next_out = (Bytef *) buffer.data + buffer.used;
4110 + 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);
4112 + status = inflate(Z, flush);
4114 + buffer.used += buffer.free - Z->avail_out;
4115 + buffer.free = Z->avail_out;
4117 + 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);
4119 + HTTP_INFLATE_BUFFER_SIZE_ALIGN(buffer.size);
4121 + } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < HTTP_INFLATE_ROUNDS);
4123 + if (status == Z_OK || status == Z_STREAM_END) {
4124 + phpstr_shrink(&buffer);
4125 + phpstr_fix(&buffer);
4126 + *buf = buffer.data;
4127 + *len = buffer.used;
4129 + phpstr_dtor(&buffer);
4136 +/* {{{ STATUS http_encoding_deflate(int, char *, size_t, char **, size_t *) */
4137 +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)
4139 + int status, level, wbits, strategy;
4142 + HTTP_DEFLATE_LEVEL_SET(flags, level);
4143 + HTTP_DEFLATE_WBITS_SET(flags, wbits);
4144 + HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
4146 + memset(&Z, 0, sizeof(z_stream));
4150 + status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy);
4151 + if (Z_OK == status) {
4152 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
4153 + *encoded = emalloc_rel(*encoded_len);
4155 + Z.next_in = (Bytef *) data;
4156 + Z.next_out = (Bytef *) *encoded;
4157 + Z.avail_in = data_len;
4158 + Z.avail_out = *encoded_len;
4160 + status = deflate(&Z, Z_FINISH);
4163 + if (Z_STREAM_END == status) {
4164 + /* size buffer down to actual length */
4165 + *encoded = erealloc_rel(*encoded, Z.total_out + 1);
4166 + (*encoded)[*encoded_len = Z.total_out] = '\0';
4169 + STR_SET(*encoded, NULL);
4174 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not deflate data: %s", zError(status));
4179 +/* {{{ STATUS http_encoding_inflate(char *, size_t, char **, size_t) */
4180 +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)
4183 + int status, wbits = HTTP_WINDOW_BITS_ANY;
4185 + memset(&Z, 0, sizeof(z_stream));
4188 + status = inflateInit2(&Z, wbits);
4189 + if (Z_OK == status) {
4190 + Z.next_in = (Bytef *) data;
4191 + Z.avail_in = data_len;
4193 + switch (status = http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) {
4194 + case Z_STREAM_END:
4199 + status = Z_DATA_ERROR;
4202 + case Z_DATA_ERROR:
4203 + /* raw deflated data? */
4204 + if (HTTP_WINDOW_BITS_ANY == wbits) {
4206 + wbits = HTTP_WINDOW_BITS_RAW;
4207 + goto retry_raw_inflate;
4213 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s", zError(status));
4218 +/* {{{ http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *, int) */
4219 +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)
4221 + int status, level, wbits, strategy, free_stream;
4223 + if ((free_stream = !s)) {
4224 + s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));
4226 + memset(s, 0, sizeof(http_encoding_stream));
4229 + HTTP_DEFLATE_LEVEL_SET(flags, level);
4230 + HTTP_DEFLATE_WBITS_SET(flags, wbits);
4231 + HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
4233 + if (Z_OK == (status = deflateInit2(&s->stream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy))) {
4234 + int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
4236 + if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) {
4239 + deflateEnd(&s->stream);
4240 + status = Z_MEM_ERROR;
4243 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize deflate encoding stream: %s", zError(status));
4244 + if (free_stream) {
4251 +/* {{{ http_encoding_stream *http_encoding_inflate_stream_init(http_encoding_stream *, int) */
4252 +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)
4254 + int status, wbits, free_stream;
4256 + if ((free_stream = !s)) {
4257 + s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));
4259 + memset(s, 0, sizeof(http_encoding_stream));
4262 + HTTP_INFLATE_WBITS_SET(flags, wbits);
4264 + if (Z_OK == (status = inflateInit2(&s->stream, wbits))) {
4265 + int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
4267 + if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) {
4270 + inflateEnd(&s->stream);
4271 + status = Z_MEM_ERROR;
4274 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize inflate stream: %s", zError(status));
4275 + if (free_stream) {
4282 +/* {{{ STATUS http_encoding_deflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */
4283 +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)
4287 + /* append input to our buffer */
4288 + phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
4290 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4291 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4294 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
4295 + *encoded = emalloc_rel(*encoded_len);
4296 + s->stream.avail_out = *encoded_len;
4297 + s->stream.next_out = (Bytef *) *encoded;
4299 + switch (status = deflate(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags))) {
4301 + case Z_STREAM_END:
4302 + /* cut processed chunk off the buffer */
4303 + if (s->stream.avail_in) {
4304 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4306 + phpstr_reset(PHPSTR(s->stream.opaque));
4309 + /* size buffer down to actual size */
4310 + *encoded_len -= s->stream.avail_out;
4311 + *encoded = erealloc_rel(*encoded, *encoded_len + 1);
4312 + (*encoded)[*encoded_len] = '\0';
4316 + STR_SET(*encoded, NULL);
4318 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update deflate stream: %s", zError(status));
4323 +/* {{{ STATUS http_encoding_inflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */
4324 +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)
4328 + /* append input to buffer */
4329 + phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
4332 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4333 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4335 + switch (status = http_inflate_rounds(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags), decoded, decoded_len)) {
4337 + case Z_STREAM_END:
4339 + if (s->stream.avail_in) {
4340 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4342 + phpstr_reset(PHPSTR(s->stream.opaque));
4346 + case Z_DATA_ERROR:
4347 + /* raw deflated data ? */
4348 + if (!(s->flags & HTTP_INFLATE_TYPE_RAW) && !s->stream.total_out) {
4349 + inflateEnd(&s->stream);
4350 + s->flags |= HTTP_INFLATE_TYPE_RAW;
4351 + inflateInit2(&s->stream, HTTP_WINDOW_BITS_RAW);
4352 + goto retry_raw_inflate;
4356 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update inflate stream: %s", zError(status));
4361 +/* {{{ STATUS http_encoding_deflate_stream_flush(http_encoding_stream *, char **, size_t *) */
4362 +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)
4366 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE;
4367 + *encoded = emalloc_rel(*encoded_len);
4369 + s->stream.avail_in = 0;
4370 + s->stream.next_in = NULL;
4371 + s->stream.avail_out = *encoded_len;
4372 + s->stream.next_out = (Bytef *) *encoded;
4374 + switch (status = deflate(&s->stream, Z_FULL_FLUSH)) {
4376 + case Z_STREAM_END:
4377 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE - s->stream.avail_out;
4378 + *encoded = erealloc_rel(*encoded, *encoded_len + 1);
4379 + (*encoded)[*encoded_len] = '\0';
4383 + STR_SET(*encoded, NULL);
4385 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to flush deflate stream: %s", zError(status));
4390 +/* {{{ STATUS http_encoding_inflate_straem_flush(http_encoding_stream *, char **, size_t *) */
4391 +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)
4394 + *decoded = estrndup("", *decoded_len = 0);
4399 +/* {{{ STATUS http_encoding_deflate_stream_finish(http_encoding_stream *, char **, size_t *) */
4400 +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)
4404 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE;
4405 + *encoded = emalloc_rel(*encoded_len);
4407 + /* deflate remaining input */
4408 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4409 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4411 + s->stream.avail_out = *encoded_len;
4412 + s->stream.next_out = (Bytef *) *encoded;
4415 + status = deflate(&s->stream, Z_FINISH);
4416 + } while (Z_OK == status);
4418 + if (Z_STREAM_END == status) {
4419 + /* cut processed intp off */
4420 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4423 + *encoded_len -= s->stream.avail_out;
4424 + *encoded = erealloc_rel(*encoded, *encoded_len + 1);
4425 + (*encoded)[*encoded_len] = '\0';
4429 + STR_SET(*encoded, NULL);
4431 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish deflate stream: %s", zError(status));
4436 +/* {{{ STATUS http_encoding_inflate_stream_finish(http_encoding_stream *, char **, size_t *) */
4437 +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)
4441 + if (!PHPSTR_LEN(s->stream.opaque)) {
4447 + *decoded_len = (PHPSTR_LEN(s->stream.opaque) + 1) * HTTP_INFLATE_ROUNDS;
4448 + *decoded = emalloc_rel(*decoded_len);
4450 + /* inflate remaining input */
4451 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4452 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4454 + s->stream.avail_out = *decoded_len;
4455 + s->stream.next_out = (Bytef *) *decoded;
4457 + if (Z_STREAM_END == (status = inflate(&s->stream, Z_FINISH))) {
4458 + /* cut processed input off */
4459 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4462 + *decoded_len -= s->stream.avail_out;
4463 + *decoded = erealloc_rel(*decoded, *decoded_len + 1);
4464 + (*decoded)[*decoded_len] = '\0';
4468 + STR_SET(*decoded, NULL);
4470 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish inflate stream: %s", zError(status));
4475 +/* {{{ void http_encoding_deflate_stream_dtor(http_encoding_stream *) */
4476 +PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
4479 + if (s->stream.opaque) {
4480 + phpstr_free((phpstr **) &s->stream.opaque);
4482 + deflateEnd(&s->stream);
4487 +/* {{{ void http_encoding_inflate_stream_dtor(http_encoding_stream *) */
4488 +PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
4491 + if (s->stream.opaque) {
4492 + phpstr_free((phpstr **) &s->stream.opaque);
4494 + inflateEnd(&s->stream);
4499 +/* {{{ void http_encoding_deflate_stream_free(http_encoding_stream **) */
4500 +PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC)
4503 + http_encoding_deflate_stream_dtor(*s);
4505 + pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
4512 +/* {{{ void http_encoding_inflate_stream_free(http_encoding_stream **) */
4513 +PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC)
4516 + http_encoding_inflate_stream_dtor(*s);
4518 + pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
4525 +/* {{{ void http_ob_deflatehandler(char *, uint, char **, uint *, int) */
4526 +void _http_ob_deflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
4530 + *handled_output = NULL;
4531 + *handled_output_len = 0;
4533 + if (mode & PHP_OUTPUT_HANDLER_START) {
4536 + if (HTTP_G->send.deflate.stream) {
4537 + zend_error(E_ERROR, "ob_deflatehandler() can only be used once");
4541 + HTTP_G->send.deflate.response = 1;
4542 + encoding = http_encoding_response_start(0, 1);
4543 + HTTP_G->send.deflate.response = 0;
4545 + switch (encoding) {
4546 + case HTTP_ENCODING_GZIP:
4547 + flags = HTTP_DEFLATE_TYPE_GZIP;
4550 + case HTTP_ENCODING_DEFLATE:
4551 + flags = HTTP_DEFLATE_TYPE_ZLIB;
4555 + goto deflate_passthru_plain;
4558 + flags |= (HTTP_G->send.deflate.start_flags &~ 0xf0);
4559 + HTTP_G->send.deflate.stream = http_encoding_deflate_stream_init(NULL, flags);
4562 + if (HTTP_G->send.deflate.stream) {
4566 + http_encoding_deflate_stream_update((http_encoding_stream *) HTTP_G->send.deflate.stream, output, output_len, handled_output, &tmp_len);
4567 + *handled_output_len = tmp_len;
4570 + if (mode & PHP_OUTPUT_HANDLER_END) {
4571 + char *remaining = NULL;
4572 + size_t remaining_len = 0;
4574 + http_encoding_deflate_stream_finish((http_encoding_stream *) HTTP_G->send.deflate.stream, &remaining, &remaining_len);
4575 + http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream);
4577 + *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1);
4578 + memcpy(*handled_output + *handled_output_len, remaining, remaining_len);
4579 + (*handled_output)[*handled_output_len += remaining_len] = '\0';
4584 +deflate_passthru_plain:
4585 + *handled_output = estrndup(output, *handled_output_len = output_len);
4590 +/* {{{ void http_ob_inflatehandler(char *, uint, char **, uint *, int) */
4591 +void _http_ob_inflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
4593 + *handled_output = NULL;
4594 + *handled_output_len = 0;
4596 + if (mode & PHP_OUTPUT_HANDLER_START) {
4597 + if (HTTP_G->send.inflate.stream) {
4598 + zend_error(E_ERROR, "ob_inflatehandler() can only be used once");
4601 + HTTP_G->send.inflate.stream = http_encoding_inflate_stream_init(NULL, (HTTP_G->send.inflate.start_flags &~ 0xf0));
4604 + if (HTTP_G->send.inflate.stream) {
4608 + http_encoding_inflate_stream_update((http_encoding_stream *) HTTP_G->send.inflate.stream, output, output_len, handled_output, &tmp_len);
4609 + *handled_output_len = tmp_len;
4612 + if (mode & PHP_OUTPUT_HANDLER_END) {
4613 + char *remaining = NULL;
4614 + size_t remaining_len = 0;
4616 + http_encoding_inflate_stream_finish((http_encoding_stream *) HTTP_G->send.inflate.stream, &remaining, &remaining_len);
4617 + http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream);
4619 + *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1);
4620 + memcpy(*handled_output + *handled_output_len, remaining, remaining_len);
4621 + (*handled_output)[*handled_output_len += remaining_len] = '\0';
4626 + *handled_output = estrndup(output, *handled_output_len = output_len);
4631 +#endif /* HTTP_HAVE_ZLIB */
4634 + * Local variables:
4636 + * c-basic-offset: 4
4638 + * vim600: noet sw=4 ts=4 fdm=marker
4639 + * vim<600: noet sw=4 ts=4
4643 +++ b/ext/http/http_exception_object.c
4646 + +--------------------------------------------------------------------+
4648 + +--------------------------------------------------------------------+
4649 + | Redistribution and use in source and binary forms, with or without |
4650 + | modification, are permitted provided that the conditions mentioned |
4651 + | in the accompanying LICENSE file are met. |
4652 + +--------------------------------------------------------------------+
4653 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
4654 + +--------------------------------------------------------------------+
4657 +/* $Id: http_exception_object.c 292841 2009-12-31 08:48:57Z mike $ */
4659 +#include "php_http.h"
4661 +#ifdef ZEND_ENGINE_2
4663 +#ifndef HTTP_DBG_EXCEPTIONS
4664 +# define HTTP_DBG_EXCEPTIONS 0
4667 +#include "zend_interfaces.h"
4668 +#include "zend_exceptions.h"
4669 +#include "php_http_exception_object.h"
4671 +zend_class_entry *http_exception_object_ce;
4672 +zend_class_entry *HTTP_EX_CE(runtime);
4673 +zend_class_entry *HTTP_EX_CE(header);
4674 +zend_class_entry *HTTP_EX_CE(malformed_headers);
4675 +zend_class_entry *HTTP_EX_CE(request_method);
4676 +zend_class_entry *HTTP_EX_CE(message_type);
4677 +zend_class_entry *HTTP_EX_CE(invalid_param);
4678 +zend_class_entry *HTTP_EX_CE(encoding);
4679 +zend_class_entry *HTTP_EX_CE(request);
4680 +zend_class_entry *HTTP_EX_CE(request_pool);
4681 +zend_class_entry *HTTP_EX_CE(socket);
4682 +zend_class_entry *HTTP_EX_CE(response);
4683 +zend_class_entry *HTTP_EX_CE(url);
4684 +zend_class_entry *HTTP_EX_CE(querystring);
4686 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpException, method, 0)
4687 +#define HTTP_EXCEPTION_ME(method, visibility) PHP_ME(HttpException, method, HTTP_ARGS(HttpException, method), visibility)
4689 +HTTP_EMPTY_ARGS(__toString);
4691 +zend_function_entry http_exception_object_fe[] = {
4692 + HTTP_EXCEPTION_ME(__toString, ZEND_ACC_PUBLIC)
4694 + EMPTY_FUNCTION_ENTRY
4697 +#if HTTP_DBG_EXCEPTIONS
4698 +static void http_exception_hook(zval *ex TSRMLS_DC)
4701 + zval *m = zend_read_property(Z_OBJCE_P(ex), ex, "message", lenof("message"), 0 TSRMLS_CC);
4702 + fprintf(stderr, "*** Threw exception '%s'\n", Z_STRVAL_P(m));
4704 + fprintf(stderr, "*** Threw NULL exception\n");
4709 +PHP_MINIT_FUNCTION(http_exception_object)
4711 + HTTP_REGISTER_CLASS(HttpException, http_exception_object, ZEND_EXCEPTION_GET_DEFAULT(), 0);
4713 + zend_declare_property_null(HTTP_EX_DEF_CE, "innerException", lenof("innerException"), ZEND_ACC_PUBLIC TSRMLS_CC);
4715 + HTTP_REGISTER_EXCEPTION(HttpRuntimeException, HTTP_EX_CE(runtime), HTTP_EX_DEF_CE);
4716 + HTTP_REGISTER_EXCEPTION(HttpInvalidParamException, HTTP_EX_CE(invalid_param), HTTP_EX_DEF_CE);
4717 + HTTP_REGISTER_EXCEPTION(HttpHeaderException, HTTP_EX_CE(header), HTTP_EX_DEF_CE);
4718 + HTTP_REGISTER_EXCEPTION(HttpMalformedHeadersException, HTTP_EX_CE(malformed_headers), HTTP_EX_DEF_CE);
4719 + HTTP_REGISTER_EXCEPTION(HttpRequestMethodException, HTTP_EX_CE(request_method), HTTP_EX_DEF_CE);
4720 + HTTP_REGISTER_EXCEPTION(HttpMessageTypeException, HTTP_EX_CE(message_type), HTTP_EX_DEF_CE);
4721 + HTTP_REGISTER_EXCEPTION(HttpEncodingException, HTTP_EX_CE(encoding), HTTP_EX_DEF_CE);
4722 + HTTP_REGISTER_EXCEPTION(HttpRequestException, HTTP_EX_CE(request), HTTP_EX_DEF_CE);
4724 + zend_declare_property_long(HTTP_EX_CE(request), "curlCode", lenof("curlCode"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
4726 + HTTP_REGISTER_EXCEPTION(HttpRequestPoolException, HTTP_EX_CE(request_pool), HTTP_EX_DEF_CE);
4727 + HTTP_REGISTER_EXCEPTION(HttpSocketException, HTTP_EX_CE(socket), HTTP_EX_DEF_CE);
4728 + HTTP_REGISTER_EXCEPTION(HttpResponseException, HTTP_EX_CE(response), HTTP_EX_DEF_CE);
4729 + HTTP_REGISTER_EXCEPTION(HttpUrlException, HTTP_EX_CE(url), HTTP_EX_DEF_CE);
4730 + HTTP_REGISTER_EXCEPTION(HttpQueryStringException, HTTP_EX_CE(querystring), HTTP_EX_DEF_CE);
4732 + HTTP_LONG_CONSTANT("HTTP_E_RUNTIME", HTTP_E_RUNTIME);
4733 + HTTP_LONG_CONSTANT("HTTP_E_INVALID_PARAM", HTTP_E_INVALID_PARAM);
4734 + HTTP_LONG_CONSTANT("HTTP_E_HEADER", HTTP_E_HEADER);
4735 + HTTP_LONG_CONSTANT("HTTP_E_MALFORMED_HEADERS", HTTP_E_MALFORMED_HEADERS);
4736 + HTTP_LONG_CONSTANT("HTTP_E_REQUEST_METHOD", HTTP_E_REQUEST_METHOD);
4737 + HTTP_LONG_CONSTANT("HTTP_E_MESSAGE_TYPE", HTTP_E_MESSAGE_TYPE);
4738 + HTTP_LONG_CONSTANT("HTTP_E_ENCODING", HTTP_E_ENCODING);
4739 + HTTP_LONG_CONSTANT("HTTP_E_REQUEST", HTTP_E_REQUEST);
4740 + HTTP_LONG_CONSTANT("HTTP_E_REQUEST_POOL", HTTP_E_REQUEST_POOL);
4741 + HTTP_LONG_CONSTANT("HTTP_E_SOCKET", HTTP_E_SOCKET);
4742 + HTTP_LONG_CONSTANT("HTTP_E_RESPONSE", HTTP_E_RESPONSE);
4743 + HTTP_LONG_CONSTANT("HTTP_E_URL", HTTP_E_URL);
4744 + HTTP_LONG_CONSTANT("HTTP_E_QUERYSTRING", HTTP_E_QUERYSTRING);
4746 +#if HTTP_DBG_EXCEPTIONS
4747 + zend_throw_exception_hook=http_exception_hook;
4753 +zend_class_entry *_http_exception_get_default()
4755 + return http_exception_object_ce;
4758 +zend_class_entry *_http_exception_get_for_code(long code)
4760 + zend_class_entry *ex = http_exception_object_ce;
4763 + case HTTP_E_RUNTIME: ex = HTTP_EX_CE(runtime); break;
4764 + case HTTP_E_INVALID_PARAM: ex = HTTP_EX_CE(invalid_param); break;
4765 + case HTTP_E_HEADER: ex = HTTP_EX_CE(header); break;
4766 + case HTTP_E_MALFORMED_HEADERS: ex = HTTP_EX_CE(malformed_headers); break;
4767 + case HTTP_E_REQUEST_METHOD: ex = HTTP_EX_CE(request_method); break;
4768 + case HTTP_E_MESSAGE_TYPE: ex = HTTP_EX_CE(message_type); break;
4769 + case HTTP_E_ENCODING: ex = HTTP_EX_CE(encoding); break;
4770 + case HTTP_E_REQUEST: ex = HTTP_EX_CE(request); break;
4771 + case HTTP_E_REQUEST_POOL: ex = HTTP_EX_CE(request_pool); break;
4772 + case HTTP_E_SOCKET: ex = HTTP_EX_CE(socket); break;
4773 + case HTTP_E_RESPONSE: ex = HTTP_EX_CE(response); break;
4774 + case HTTP_E_URL: ex = HTTP_EX_CE(url); break;
4775 + case HTTP_E_QUERYSTRING: ex = HTTP_EX_CE(querystring); break;
4781 +PHP_METHOD(HttpException, __toString)
4784 + zend_class_entry *ce;
4785 + zval *zobj = getThis(), *retval = NULL, *m, *f, *l;
4787 + phpstr_init(&full_str);
4790 + ce = Z_OBJCE_P(zobj);
4792 + m = zend_read_property(ce, zobj, "message", lenof("message"), 0 TSRMLS_CC);
4793 + f = zend_read_property(ce, zobj, "file", lenof("file"), 0 TSRMLS_CC);
4794 + l = zend_read_property(ce, zobj, "line", lenof("line"), 0 TSRMLS_CC);
4796 + if (m && f && l && Z_TYPE_P(m) == IS_STRING && Z_TYPE_P(f) == IS_STRING && Z_TYPE_P(l) == IS_LONG) {
4797 + if (zobj != getThis()) {
4798 + phpstr_appends(&full_str, " inner ");
4801 + phpstr_appendf(&full_str, "exception '%.*s' with message '%.*s' in %.*s:%ld" PHP_EOL,
4802 + 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)
4808 + zobj = zend_read_property(ce, zobj, "innerException", lenof("innerException"), 0 TSRMLS_CC);
4809 + } while (Z_TYPE_P(zobj) == IS_OBJECT);
4811 + if (zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "gettraceasstring", &retval) && Z_TYPE_P(retval) == IS_STRING) {
4812 + phpstr_appends(&full_str, "Stack trace:" PHP_EOL);
4813 + phpstr_append(&full_str, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
4814 + zval_ptr_dtor(&retval);
4817 + RETURN_PHPSTR_VAL(&full_str);
4823 + * Local variables:
4825 + * c-basic-offset: 4
4827 + * vim600: noet sw=4 ts=4 fdm=marker
4828 + * vim<600: noet sw=4 ts=4
4832 +++ b/ext/http/http_filter_api.c
4835 + +--------------------------------------------------------------------+
4837 + +--------------------------------------------------------------------+
4838 + | Redistribution and use in source and binary forms, with or without |
4839 + | modification, are permitted provided that the conditions mentioned |
4840 + | in the accompanying LICENSE file are met. |
4841 + +--------------------------------------------------------------------+
4842 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
4843 + +--------------------------------------------------------------------+
4846 +/* $Id: http_filter_api.c 292841 2009-12-31 08:48:57Z mike $ */
4848 +#define HTTP_WANT_ZLIB
4849 +#include "php_http.h"
4851 +#ifdef ZEND_ENGINE_2
4853 +#include "php_streams.h"
4854 +#include "php_http_api.h"
4855 +#include "php_http_encoding_api.h"
4856 +#include "php_http_filter_api.h"
4858 +PHP_MINIT_FUNCTION(http_filter)
4860 + php_stream_filter_register_factory("http.*", &http_filter_factory TSRMLS_CC);
4868 +#define HTTP_FILTER_PARAMS \
4869 + php_stream *stream, \
4870 + php_stream_filter *this, \
4871 + php_stream_bucket_brigade *buckets_in, \
4872 + php_stream_bucket_brigade *buckets_out, \
4873 + size_t *bytes_consumed, int flags \
4875 +#define HTTP_FILTER_OP(filter) \
4876 + http_filter_op_ ##filter
4877 +#define HTTP_FILTER_OPS(filter) \
4878 + php_stream_filter_ops HTTP_FILTER_OP(filter)
4879 +#define HTTP_FILTER_DTOR(filter) \
4880 + http_filter_ ##filter## _dtor
4881 +#define HTTP_FILTER_DESTRUCTOR(filter) \
4882 + void HTTP_FILTER_DTOR(filter)(php_stream_filter *this TSRMLS_DC)
4883 +#define HTTP_FILTER_FUNC(filter) \
4884 + http_filter_ ##filter
4885 +#define HTTP_FILTER_FUNCTION(filter) \
4886 + php_stream_filter_status_t HTTP_FILTER_FUNC(filter)(HTTP_FILTER_PARAMS)
4887 +#define HTTP_FILTER_BUFFER(filter) \
4888 + http_filter_ ##filter## _buffer
4890 +#define NEW_BUCKET(data, length) \
4893 + php_stream_bucket *__buck; \
4895 + __data = pemalloc(length, this->is_persistent); \
4897 + return PSFS_ERR_FATAL; \
4899 + memcpy(__data, data, length); \
4901 + __buck = php_stream_bucket_new(stream, __data, length, 1, this->is_persistent TSRMLS_CC); \
4903 + pefree(__data, this->is_persistent); \
4904 + return PSFS_ERR_FATAL; \
4907 + php_stream_bucket_append(buckets_out, __buck TSRMLS_CC); \
4910 +typedef struct _http_chunked_decode_filter_buffer_t {
4913 +} HTTP_FILTER_BUFFER(chunked_decode);
4915 +#ifdef HTTP_HAVE_ZLIB
4916 +typedef http_encoding_stream HTTP_FILTER_BUFFER(deflate);
4917 +typedef http_encoding_stream HTTP_FILTER_BUFFER(inflate);
4918 +#endif /* HTTP_HAVE_ZLIB */
4921 +static HTTP_FILTER_FUNCTION(chunked_decode)
4923 + int out_avail = 0;
4924 + php_stream_bucket *ptr, *nxt;
4925 + HTTP_FILTER_BUFFER(chunked_decode) *buffer = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract);
4927 + if (bytes_consumed) {
4928 + *bytes_consumed = 0;
4931 + /* new data available? */
4932 + if (buckets_in->head) {
4934 + /* fetch available bucket data */
4935 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
4937 + if (bytes_consumed) {
4938 + *bytes_consumed += ptr->buflen;
4941 + if (PHPSTR_NOMEM == phpstr_append(PHPSTR(buffer), ptr->buf, ptr->buflen)) {
4942 + return PSFS_ERR_FATAL;
4945 + php_stream_bucket_unlink(ptr TSRMLS_CC);
4946 + php_stream_bucket_delref(ptr TSRMLS_CC);
4949 + if (!phpstr_fix(PHPSTR(buffer))) {
4950 + return PSFS_ERR_FATAL;
4953 + /* we have data in our buffer */
4954 + while (PHPSTR_LEN(buffer)) {
4956 + /* we already know the size of the chunk and are waiting for data */
4957 + if (buffer->hexlen) {
4959 + /* not enough data buffered */
4960 + if (PHPSTR_LEN(buffer) < buffer->hexlen) {
4962 + /* flush anyway? */
4963 + if (flags & PSFS_FLAG_FLUSH_INC) {
4965 + /* flush all data (should only be chunk data) */
4967 + NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer));
4969 + /* waiting for less data now */
4970 + buffer->hexlen -= PHPSTR_LEN(buffer);
4971 + /* no more buffered data */
4972 + phpstr_reset(PHPSTR(buffer));
4976 + /* we have too less data and don't need to flush */
4982 + /* we seem to have all data of the chunk */
4985 + NEW_BUCKET(PHPSTR_VAL(buffer), buffer->hexlen);
4987 + /* remove outgoing data from the buffer */
4988 + phpstr_cut(PHPSTR(buffer), 0, buffer->hexlen);
4989 + /* reset hexlen */
4990 + buffer->hexlen = 0;
4995 + /* we don't know the length of the chunk yet */
4999 + /* ignore preceeding CRLFs (too loose?) */
5000 + while (off < PHPSTR_LEN(buffer) && (
5001 + PHPSTR_VAL(buffer)[off] == '\n' ||
5002 + PHPSTR_VAL(buffer)[off] == '\r')) {
5006 + phpstr_cut(PHPSTR(buffer), 0, off);
5009 + /* still data there? */
5010 + if (PHPSTR_LEN(buffer)) {
5012 + const char *eolstr;
5014 + /* we need eol, so we can be sure we have all hex digits */
5015 + phpstr_fix(PHPSTR(buffer));
5016 + if ((eolstr = http_locate_eol(PHPSTR_VAL(buffer), &eollen))) {
5017 + char *stop = NULL;
5019 + /* read in chunk size */
5020 + buffer->hexlen = strtoul(PHPSTR_VAL(buffer), &stop, 16);
5022 + /* if strtoul() stops at the beginning of the buffered data
5023 + there's domething oddly wrong, i.e. bad input */
5024 + if (stop == PHPSTR_VAL(buffer)) {
5025 + return PSFS_ERR_FATAL;
5028 + /* cut out <chunk size hex><chunk extension><eol> */
5029 + phpstr_cut(PHPSTR(buffer), 0, eolstr + eollen - PHPSTR_VAL(buffer));
5030 + /* buffer->hexlen is 0 now or contains the size of the next chunk */
5033 + /* we have not enough data buffered to read in chunk size */
5041 + /* flush before close, but only if we are already waiting for more data */
5042 + if ((flags & PSFS_FLAG_FLUSH_CLOSE) && buffer->hexlen && PHPSTR_LEN(buffer)) {
5044 + NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer));
5045 + phpstr_reset(PHPSTR(buffer));
5046 + buffer->hexlen = 0;
5049 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5052 +static HTTP_FILTER_DESTRUCTOR(chunked_decode)
5054 + HTTP_FILTER_BUFFER(chunked_decode) *b = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract);
5056 + phpstr_dtor(PHPSTR(b));
5057 + pefree(b, this->is_persistent);
5060 +static HTTP_FILTER_FUNCTION(chunked_encode)
5062 + int out_avail = 0;
5063 + php_stream_bucket *ptr, *nxt;
5065 + if (bytes_consumed) {
5066 + *bytes_consumed = 0;
5069 + /* new data available? */
5070 + if (buckets_in->head) {
5074 + phpstr_init(&buf);
5076 + /* fetch available bucket data */
5077 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
5079 + if (bytes_consumed) {
5080 + *bytes_consumed += ptr->buflen;
5083 + phpstr_appendf(&buf, "%x" HTTP_CRLF, ptr->buflen);
5084 + phpstr_append(&buf, ptr->buf, ptr->buflen);
5085 + phpstr_appends(&buf, HTTP_CRLF);
5087 + /* pass through */
5088 + NEW_BUCKET(PHPSTR_VAL(&buf), PHPSTR_LEN(&buf));
5090 + phpstr_reset(&buf);
5092 + php_stream_bucket_unlink(ptr TSRMLS_CC);
5093 + php_stream_bucket_delref(ptr TSRMLS_CC);
5097 + phpstr_dtor(&buf);
5100 + /* terminate with "0" */
5101 + if (flags & PSFS_FLAG_FLUSH_CLOSE) {
5103 + NEW_BUCKET("0" HTTP_CRLF, lenof("0" HTTP_CRLF));
5106 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5109 +static HTTP_FILTER_OPS(chunked_decode) = {
5110 + HTTP_FILTER_FUNC(chunked_decode),
5111 + HTTP_FILTER_DTOR(chunked_decode),
5112 + "http.chunked_decode"
5115 +static HTTP_FILTER_OPS(chunked_encode) = {
5116 + HTTP_FILTER_FUNC(chunked_encode),
5118 + "http.chunked_encode"
5121 +#ifdef HTTP_HAVE_ZLIB
5123 +static HTTP_FILTER_FUNCTION(deflate)
5125 + int out_avail = 0;
5126 + php_stream_bucket *ptr, *nxt;
5127 + HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
5129 + if (bytes_consumed) {
5130 + *bytes_consumed = 0;
5133 + /* new data available? */
5134 + if (buckets_in->head) {
5136 + /* fetch available bucket data */
5137 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
5138 + char *encoded = NULL;
5139 + size_t encoded_len = 0;
5142 + if (bytes_consumed) {
5143 + *bytes_consumed += ptr->buflen;
5146 + if (ptr->buflen) {
5147 + http_encoding_deflate_stream_update(buffer, ptr->buf, ptr->buflen, &encoded, &encoded_len);
5149 + if (encoded_len) {
5151 + NEW_BUCKET(encoded, encoded_len);
5157 + php_stream_bucket_unlink(ptr TSRMLS_CC);
5158 + php_stream_bucket_delref(ptr TSRMLS_CC);
5162 + /* flush & close */
5163 + if (flags & PSFS_FLAG_FLUSH_INC) {
5164 + char *encoded = NULL;
5165 + size_t encoded_len = 0;
5167 + http_encoding_deflate_stream_flush(buffer, &encoded, &encoded_len);
5169 + if (encoded_len) {
5171 + NEW_BUCKET(encoded, encoded_len);
5177 + if (flags & PSFS_FLAG_FLUSH_CLOSE) {
5178 + char *encoded = NULL;
5179 + size_t encoded_len = 0;
5181 + http_encoding_deflate_stream_finish(buffer, &encoded, &encoded_len);
5183 + if (encoded_len) {
5185 + NEW_BUCKET(encoded, encoded_len);
5191 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5194 +static HTTP_FILTER_FUNCTION(inflate)
5196 + int out_avail = 0;
5197 + php_stream_bucket *ptr, *nxt;
5198 + HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
5200 + if (bytes_consumed) {
5201 + *bytes_consumed = 0;
5204 + /* new data available? */
5205 + if (buckets_in->head) {
5207 + /* fetch available bucket data */
5208 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
5209 + char *decoded = NULL;
5210 + size_t decoded_len = 0;
5213 + if (bytes_consumed) {
5214 + *bytes_consumed += ptr->buflen;
5217 + if (ptr->buflen) {
5218 + http_encoding_inflate_stream_update(buffer, ptr->buf, ptr->buflen, &decoded, &decoded_len);
5220 + if (decoded_len) {
5222 + NEW_BUCKET(decoded, decoded_len);
5228 + php_stream_bucket_unlink(ptr TSRMLS_CC);
5229 + php_stream_bucket_delref(ptr TSRMLS_CC);
5233 + /* flush & close */
5234 + if (flags & PSFS_FLAG_FLUSH_INC) {
5235 + char *decoded = NULL;
5236 + size_t decoded_len = 0;
5238 + http_encoding_inflate_stream_flush(buffer, &decoded, &decoded_len);
5240 + if (decoded_len) {
5242 + NEW_BUCKET(decoded, decoded_len);
5248 + if (flags & PSFS_FLAG_FLUSH_CLOSE) {
5249 + char *decoded = NULL;
5250 + size_t decoded_len = 0;
5252 + http_encoding_inflate_stream_finish(buffer, &decoded, &decoded_len);
5254 + if (decoded_len) {
5256 + NEW_BUCKET(decoded, decoded_len);
5262 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5265 +static HTTP_FILTER_DESTRUCTOR(deflate)
5267 + HTTP_FILTER_BUFFER(deflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
5268 + http_encoding_deflate_stream_free(&buffer);
5271 +static HTTP_FILTER_DESTRUCTOR(inflate)
5273 + HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
5274 + http_encoding_inflate_stream_free(&buffer);
5277 +static HTTP_FILTER_OPS(deflate) = {
5278 + HTTP_FILTER_FUNC(deflate),
5279 + HTTP_FILTER_DTOR(deflate),
5283 +static HTTP_FILTER_OPS(inflate) = {
5284 + HTTP_FILTER_FUNC(inflate),
5285 + HTTP_FILTER_DTOR(inflate),
5289 +#endif /* HTTP_HAVE_ZLIB */
5291 +static php_stream_filter *http_filter_create(const char *name, zval *params, int p TSRMLS_DC)
5293 + zval **tmp = ¶ms;
5294 + php_stream_filter *f = NULL;
5296 + if (!strcasecmp(name, "http.chunked_decode")) {
5297 + HTTP_FILTER_BUFFER(chunked_decode) *b = NULL;
5299 + if ((b = pecalloc(1, sizeof(HTTP_FILTER_BUFFER(chunked_decode)), p))) {
5300 + phpstr_init_ex(PHPSTR(b), 4096, p ? PHPSTR_INIT_PERSISTENT : 0);
5301 + if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_decode), b, p))) {
5307 + if (!strcasecmp(name, "http.chunked_encode")) {
5308 + f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_encode), NULL, p);
5309 +#ifdef HTTP_HAVE_ZLIB
5312 + if (!strcasecmp(name, "http.inflate")) {
5313 + int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
5314 + HTTP_FILTER_BUFFER(inflate) *b = NULL;
5316 + if ((b = http_encoding_inflate_stream_init(NULL, flags))) {
5317 + if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(inflate), b, p))) {
5318 + http_encoding_inflate_stream_free(&b);
5323 + if (!strcasecmp(name, "http.deflate")) {
5324 + int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
5325 + HTTP_FILTER_BUFFER(deflate) *b = NULL;
5328 + switch (Z_TYPE_P(params)) {
5331 + if (SUCCESS != zend_hash_find(HASH_OF(params), "flags", sizeof("flags"), (void *) &tmp)) {
5336 + zval *num = http_zsep(IS_LONG, *tmp);
5338 + flags |= (Z_LVAL_P(num) & 0x0fffffff);
5339 + zval_ptr_dtor(&num);
5343 + if ((b = http_encoding_deflate_stream_init(NULL, flags))) {
5344 + if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(deflate), b, p))) {
5345 + http_encoding_deflate_stream_free(&b);
5348 +#endif /* HTTP_HAVE_ZLIB */
5354 +php_stream_filter_factory http_filter_factory = {
5355 + http_filter_create
5358 +#endif /* ZEND_ENGINE_2 */
5361 + * Local variables:
5363 + * c-basic-offset: 4
5365 + * vim600: noet sw=4 ts=4 fdm=marker
5366 + * vim<600: noet sw=4 ts=4
5369 +++ b/ext/http/http_functions.c
5372 + +--------------------------------------------------------------------+
5374 + +--------------------------------------------------------------------+
5375 + | Redistribution and use in source and binary forms, with or without |
5376 + | modification, are permitted provided that the conditions mentioned |
5377 + | in the accompanying LICENSE file are met. |
5378 + +--------------------------------------------------------------------+
5379 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
5380 + +--------------------------------------------------------------------+
5383 +/* $Id: http_functions.c 300301 2010-06-09 08:30:34Z mike $ */
5385 +#define HTTP_WANT_SAPI
5386 +#define HTTP_WANT_CURL
5387 +#define HTTP_WANT_ZLIB
5388 +#include "php_http.h"
5390 +#include "php_ini.h"
5391 +#include "ext/standard/php_string.h"
5392 +#include "zend_operators.h"
5394 +#ifdef HTTP_HAVE_SESSION
5395 +# include "ext/session/php_session.h"
5398 +#include "php_http_api.h"
5399 +#include "php_http_cache_api.h"
5400 +#include "php_http_cookie_api.h"
5401 +#include "php_http_date_api.h"
5402 +#include "php_http_encoding_api.h"
5403 +#include "php_http_headers_api.h"
5404 +#include "php_http_message_api.h"
5405 +#include "php_http_request_api.h"
5406 +#include "php_http_request_method_api.h"
5407 +#include "php_http_persistent_handle_api.h"
5408 +#include "php_http_send_api.h"
5409 +#include "php_http_url_api.h"
5411 +/* {{{ proto string http_date([int timestamp])
5412 + Compose a valid HTTP date regarding RFC 1123 looking like: "Wed, 22 Dec 2004 11:34:47 GMT" */
5413 +PHP_FUNCTION(http_date)
5418 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
5423 + t = HTTP_G->request.time;
5426 + if (!(date = http_date(t))) {
5427 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Could not compose date of timestamp %ld", t);
5431 + RETURN_STRING(date, 0);
5435 +/* {{{ proto string http_build_url([mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV[, array &new_url]]]])
5437 +PHP_FUNCTION(http_build_url)
5439 + char *url_str = NULL;
5440 + size_t url_len = 0;
5441 + long flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV;
5442 + zval *z_old_url = NULL, *z_new_url = NULL, *z_composed_url = NULL;
5443 + php_url *old_url = NULL, *new_url = NULL, *composed_url = NULL;
5445 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z!/lz", &z_old_url, &z_new_url, &flags, &z_composed_url) != SUCCESS) {
5450 + if (Z_TYPE_P(z_new_url) == IS_ARRAY || Z_TYPE_P(z_new_url) == IS_OBJECT) {
5451 + new_url = http_url_from_struct(NULL, HASH_OF(z_new_url));
5453 + convert_to_string(z_new_url);
5454 + if (!(new_url = php_url_parse_ex(Z_STRVAL_P(z_new_url), Z_STRLEN_P(z_new_url)))) {
5455 + http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_new_url));
5462 + if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) {
5463 + old_url = http_url_from_struct(NULL, HASH_OF(z_old_url));
5465 + convert_to_string(z_old_url);
5466 + if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) {
5468 + php_url_free(new_url);
5470 + http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_old_url));
5476 + if (z_composed_url) {
5477 + http_build_url(flags, old_url, new_url, &composed_url, &url_str, &url_len);
5478 + http_url_tostruct(composed_url, z_composed_url);
5479 + php_url_free(composed_url);
5481 + http_build_url(flags, old_url, new_url, NULL, &url_str, &url_len);
5485 + php_url_free(new_url);
5488 + php_url_free(old_url);
5491 + RETURN_STRINGL(url_str, url_len, 0);
5495 +/* {{{ proto string http_build_str(array query [, string prefix[, string arg_separator]])
5496 + Opponent to parse_str(). */
5497 +PHP_FUNCTION(http_build_str)
5500 + char *prefix = NULL, *arg_sep = INI_STR("arg_separator.output");
5501 + int prefix_len = 0, arg_sep_len = strlen(arg_sep);
5504 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) {
5508 + if (!arg_sep_len) {
5509 + arg_sep = HTTP_URL_ARGSEP;
5510 + arg_sep_len = lenof(HTTP_URL_ARGSEP);
5513 + phpstr_init(&formstr);
5514 + if (SUCCESS != http_urlencode_hash_recursive(HASH_OF(formdata), &formstr, arg_sep, arg_sep_len, prefix, prefix_len)) {
5518 + if (!formstr.used) {
5519 + phpstr_dtor(&formstr);
5523 + RETURN_PHPSTR_VAL(&formstr);
5527 +#define HTTP_DO_NEGOTIATE_DEFAULT(supported) \
5531 + zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \
5532 + if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void *) &value)) { \
5533 + RETVAL_ZVAL(*value, 1, 0); \
5539 +#define HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array) \
5540 + HTTP_DO_NEGOTIATE_DEFAULT(supported); \
5542 + HashPosition pos; \
5543 + zval **value_ptr; \
5545 + FOREACH_VAL(pos, supported, value_ptr) { \
5546 + zval *value = http_zsep(IS_STRING, *value_ptr); \
5547 + add_assoc_double(rs_array, Z_STRVAL_P(value), 1.0); \
5548 + zval_ptr_dtor(&value); \
5552 +#define HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array) \
5558 + if (zend_hash_num_elements(result) && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \
5559 + RETVAL_STRINGL(key, key_len-1, 0); \
5561 + HTTP_DO_NEGOTIATE_DEFAULT(supported); \
5565 + zend_hash_copy(Z_ARRVAL_P(rs_array), result, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); \
5568 + zend_hash_destroy(result); \
5569 + FREE_HASHTABLE(result); \
5572 +#define HTTP_DO_NEGOTIATE(type, supported, rs_array) \
5574 + HashTable *result; \
5575 + if ((result = http_negotiate_ ##type(supported))) { \
5576 + HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array); \
5578 + HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array); \
5582 +/* {{{ proto string http_negotiate_language(array supported[, array &result])
5583 + Negotiate the clients preferred language. */
5584 +PHP_FUNCTION(http_negotiate_language)
5586 + zval *supported, *rs_array = NULL;
5588 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
5593 + zval_dtor(rs_array);
5594 + array_init(rs_array);
5597 + HTTP_DO_NEGOTIATE(language, supported, rs_array);
5601 +/* {{{ proto string http_negotiate_charset(array supported[, array &result])
5602 + Negotiate the clients preferred charset. */
5603 +PHP_FUNCTION(http_negotiate_charset)
5605 + zval *supported, *rs_array = NULL;
5607 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
5612 + zval_dtor(rs_array);
5613 + array_init(rs_array);
5616 + HTTP_DO_NEGOTIATE(charset, supported, rs_array);
5620 +/* {{{ proto string http_negotiate_content_type(array supported[, array &result])
5621 + Negotiate the clients preferred content type. */
5622 +PHP_FUNCTION(http_negotiate_content_type)
5624 + zval *supported, *rs_array = NULL;
5626 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array)) {
5631 + zval_dtor(rs_array);
5632 + array_init(rs_array);
5635 + HTTP_DO_NEGOTIATE(content_type, supported, rs_array);
5639 +/* {{{ proto string http_negotiate(mixed value, array supported[, array &result])
5640 + Negotiate the user supplied value. */
5641 +PHP_FUNCTION(http_negotiate)
5643 + zval *value, *supported, *rs_array = NULL;
5646 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|z", &value, &supported, &rs_array)) {
5651 + zval_dtor(rs_array);
5652 + array_init(rs_array);
5655 + if ((rs = http_negotiate_z(value, Z_ARRVAL_P(supported), http_negotiate_default_func))) {
5656 + HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs, supported, rs_array);
5658 + HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array);
5663 +/* {{{ proto bool http_send_status(int status)
5664 + Send HTTP status code. */
5665 +PHP_FUNCTION(http_send_status)
5669 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) {
5672 + if (status < 100 || status > 510) {
5673 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
5677 + RETURN_SUCCESS(http_send_status(status));
5681 +/* {{{ proto bool http_send_last_modified([int timestamp])
5682 + Send a "Last-Modified" header with a valid HTTP date. */
5683 +PHP_FUNCTION(http_send_last_modified)
5687 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
5692 + t = HTTP_G->request.time;
5695 + RETURN_SUCCESS(http_send_last_modified(t));
5699 +/* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream'])
5700 + Send the Content-Type of the sent entity. This is particularly important if you use the http_send() API. */
5701 +PHP_FUNCTION(http_send_content_type)
5703 + char *ct = "application/x-octetstream";
5704 + int ct_len = lenof("application/x-octetstream");
5706 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) {
5710 + RETURN_SUCCESS(http_send_content_type(ct, ct_len));
5714 +/* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false])
5715 + Send the Content-Disposition. */
5716 +PHP_FUNCTION(http_send_content_disposition)
5720 + zend_bool send_inline = 0;
5722 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) {
5725 + RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline));
5729 +/* {{{ proto bool http_match_modified([int timestamp[, bool for_range = false]])
5730 + Matches the given unix timestamp against the clients "If-Modified-Since" resp. "If-Unmodified-Since" HTTP headers. */
5731 +PHP_FUNCTION(http_match_modified)
5734 + zend_bool for_range = 0;
5736 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &t, &for_range) != SUCCESS) {
5740 + // current time if not supplied (senseless though)
5742 + t = HTTP_G->request.time;
5746 + RETURN_BOOL(http_match_last_modified("HTTP_IF_UNMODIFIED_SINCE", t));
5748 + RETURN_BOOL(http_match_last_modified("HTTP_IF_MODIFIED_SINCE", t));
5752 +/* {{{ proto bool http_match_etag(string etag[, bool for_range = false])
5753 + Matches the given ETag against the clients "If-Match" resp. "If-None-Match" HTTP headers. */
5754 +PHP_FUNCTION(http_match_etag)
5758 + zend_bool for_range = 0;
5760 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &etag, &etag_len, &for_range) != SUCCESS) {
5765 + RETURN_BOOL(http_match_etag("HTTP_IF_MATCH", etag));
5767 + RETURN_BOOL(http_match_etag("HTTP_IF_NONE_MATCH", etag));
5771 +/* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]])
5772 + Attempts to cache the sent entity by its last modification date. */
5773 +PHP_FUNCTION(http_cache_last_modified)
5775 + long last_modified = 0, send_modified = 0, t;
5778 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
5782 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
5784 + t = HTTP_G->request.time;
5786 + /* 0 or omitted */
5787 + if (!last_modified) {
5788 + /* does the client have? (att: caching "forever") */
5789 + if ((zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE", 1))) {
5790 + last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm));
5791 + /* send current time */
5793 + send_modified = t;
5795 + /* negative value is supposed to be expiration time */
5796 + } else if (last_modified < 0) {
5797 + last_modified += t;
5798 + send_modified = t;
5799 + /* send supplied time explicitly */
5801 + send_modified = last_modified;
5804 + RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
5808 +/* {{{ proto bool http_cache_etag([string etag])
5809 + 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". */
5810 +PHP_FUNCTION(http_cache_etag)
5812 + char *etag = NULL;
5815 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
5819 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
5821 + RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
5825 +/* {{{ proto string ob_etaghandler(string data, int mode)
5826 + For use with ob_start(). Output buffer handler generating an ETag with the hash algorithm specified with the INI setting "http.etag.mode". */
5827 +PHP_FUNCTION(ob_etaghandler)
5833 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
5837 + Z_TYPE_P(return_value) = IS_STRING;
5838 + http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
5842 +/* {{{ proto void http_throttle(double sec[, int bytes = 40960])
5843 + Sets the throttle delay and send buffer size for use with http_send() API. */
5844 +PHP_FUNCTION(http_throttle)
5846 + long chunk_size = HTTP_SENDBUF_SIZE;
5849 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &interval, &chunk_size)) {
5853 + HTTP_G->send.throttle_delay = interval;
5854 + HTTP_G->send.buffer_size = chunk_size;
5858 +/* {{{ proto void http_redirect([string url[, array params[, bool session = false[, int status = 302]]]])
5859 + Redirect to the given url. */
5860 +PHP_FUNCTION(http_redirect)
5863 + size_t query_len = 0;
5864 + zend_bool session = 0, free_params = 0;
5865 + zval *params = NULL;
5866 + long status = HTTP_REDIRECT;
5867 + char *query = NULL, *url = NULL, *URI, *LOC, *RED = NULL;
5869 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bl", &url, &url_len, ¶ms, &session, &status) != SUCCESS) {
5873 +#ifdef HTTP_HAVE_SESSION
5874 + /* append session info */
5878 + MAKE_STD_ZVAL(params);
5879 + array_init(params);
5881 + if (PS(session_status) == php_session_active) {
5882 + if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
5883 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not append session information");
5889 + /* treat params array with http_build_query() */
5891 + if (SUCCESS != http_urlencode_hash_ex(Z_ARRVAL_P(params), 0, NULL, 0, &query, &query_len)) {
5892 + if (free_params) {
5893 + zval_dtor(params);
5894 + FREE_ZVAL(params);
5903 + URI = http_absolute_url_ex(url, HTTP_URL_FROM_ENV);
5906 + spprintf(&LOC, 0, "Location: %s?%s", URI, query);
5907 + if (status != 300) {
5908 + spprintf(&RED, 0, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, query, URI, query);
5911 + spprintf(&LOC, 0, "Location: %s", URI);
5912 + if (status != 300) {
5913 + spprintf(&RED, 0, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
5921 + if (free_params) {
5922 + zval_dtor(params);
5923 + FREE_ZVAL(params);
5928 + RETVAL_SUCCESS(http_send_status_header(status, LOC));
5932 + case HTTP_REDIRECT_PERM:
5933 + case HTTP_REDIRECT_FOUND:
5934 + case HTTP_REDIRECT_POST:
5935 + case HTTP_REDIRECT_PROXY:
5936 + case HTTP_REDIRECT_TEMP:
5941 + http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Unsupported redirection status code: %ld", status);
5942 + case HTTP_REDIRECT:
5943 + if ( SG(request_info).request_method &&
5944 + strcasecmp(SG(request_info).request_method, "HEAD") &&
5945 + strcasecmp(SG(request_info).request_method, "GET")) {
5946 + status = HTTP_REDIRECT_POST;
5948 + status = HTTP_REDIRECT_FOUND;
5953 + RETURN_SUCCESS(http_exit_ex(status, LOC, RED, 1));
5957 +/* {{{ proto bool http_send_data(string data)
5958 + Sends raw data with support for (multiple) range requests. */
5959 +PHP_FUNCTION(http_send_data)
5964 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data_buf, &data_len) != SUCCESS) {
5968 + RETURN_SUCCESS(http_send_data(data_buf, data_len));
5972 +/* {{{ proto bool http_send_file(string file)
5973 + Sends a file with support for (multiple) range requests. */
5974 +PHP_FUNCTION(http_send_file)
5979 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &flen) != SUCCESS) {
5986 + RETURN_SUCCESS(http_send_file(file));
5990 +/* {{{ proto bool http_send_stream(resource stream)
5991 + Sends an already opened stream with support for (multiple) range requests. */
5992 +PHP_FUNCTION(http_send_stream)
5997 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) {
6001 + php_stream_from_zval(file, &zstream);
6002 + RETURN_SUCCESS(http_send_stream(file));
6006 +/* {{{ proto string http_chunked_decode(string encoded)
6007 + Decodes a string that was HTTP-chunked encoded. */
6008 +PHP_FUNCTION(http_chunked_decode)
6010 + char *encoded = NULL, *decoded = NULL;
6011 + size_t decoded_len = 0;
6012 + int encoded_len = 0;
6014 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) {
6018 + if (NULL != http_encoding_dechunk(encoded, encoded_len, &decoded, &decoded_len)) {
6019 + RETURN_STRINGL(decoded, (int) decoded_len, 0);
6026 +/* {{{ proto object http_parse_message(string message)
6027 + Parses (a) http_message(s) into a simple recursive object structure. */
6028 +PHP_FUNCTION(http_parse_message)
6032 + http_message *msg = NULL;
6034 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &message, &message_len)) {
6038 + if ((msg = http_message_parse(message, message_len))) {
6039 + object_init(return_value);
6040 + http_message_tostruct_recursive(msg, return_value);
6041 + http_message_free(&msg);
6048 +/* {{{ proto array http_parse_headers(string header)
6049 + Parses HTTP headers into an associative array. */
6050 +PHP_FUNCTION(http_parse_headers)
6055 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) {
6059 + array_init(return_value);
6060 + if (SUCCESS != http_parse_headers(header, return_value)) {
6061 + zval_dtor(return_value);
6062 + http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse headers");
6068 +/* {{{ proto object http_parse_cookie(string cookie[, int flags[, array allowed_extras]])
6069 + Parses HTTP cookies like sent in a response into a struct. */
6070 +PHP_FUNCTION(http_parse_cookie)
6072 + char *cookie, **allowed_extras = NULL;
6073 + int i = 0, cookie_len;
6075 + zval *allowed_extras_array = NULL, **entry = NULL;
6077 + http_cookie_list list;
6079 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!", &cookie, &cookie_len, &flags, &allowed_extras_array)) {
6083 + if (allowed_extras_array) {
6084 + allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
6085 + FOREACH_VAL(pos, allowed_extras_array, entry) {
6086 + zval *data = http_zsep(IS_STRING, *entry);
6087 + allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
6088 + zval_ptr_dtor(&data);
6092 + if (http_parse_cookie_ex(&list, cookie, flags, allowed_extras)) {
6093 + object_init(return_value);
6094 + http_cookie_list_tostruct(&list, return_value);
6095 + http_cookie_list_dtor(&list);
6100 + if (allowed_extras) {
6101 + for (i = 0; allowed_extras[i]; ++i) {
6102 + efree(allowed_extras[i]);
6104 + efree(allowed_extras);
6109 +/* {{{ proto string http_build_cookie(array cookie)
6110 + Build a cookie string from an array/object like returned by http_parse_cookie(). */
6111 +PHP_FUNCTION(http_build_cookie)
6116 + http_cookie_list list;
6118 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &strct)) {
6122 + http_cookie_list_fromstruct(&list, strct);
6123 + http_cookie_list_tostring(&list, &str, &len);
6124 + http_cookie_list_dtor(&list);
6126 + RETURN_STRINGL(str, len, 0);
6130 +/* {{{ proto object http_parse_params(string param[, int flags = HTTP_PARAMS_DEFAULT])
6131 + Parse parameter list. */
6132 +PHP_FUNCTION(http_parse_params)
6137 + long flags = HTTP_PARAMS_DEFAULT;
6139 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", ¶m, ¶m_len, &flags)) {
6143 + MAKE_STD_ZVAL(params);
6144 + array_init(params);
6145 + if (SUCCESS != http_parse_params(param, flags, Z_ARRVAL_P(params))) {
6146 + zval_ptr_dtor(¶ms);
6150 + object_init(return_value);
6151 + add_property_zval(return_value, "params", params);
6152 +#ifdef ZEND_ENGINE_2
6153 + zval_ptr_dtor(¶ms);
6158 +/* {{{ proto array http_get_request_headers(void)
6159 + Get a list of incoming HTTP headers. */
6160 +PHP_FUNCTION(http_get_request_headers)
6164 + array_init(return_value);
6165 + http_get_request_headers(Z_ARRVAL_P(return_value));
6169 +/* {{{ proto string http_get_request_body(void)
6170 + Get the raw request body (e.g. POST or PUT data). */
6171 +PHP_FUNCTION(http_get_request_body)
6178 + if (SUCCESS == http_get_request_body(&body, &length)) {
6179 + RETURN_STRINGL(body, (int) length, 0);
6186 +/* {{{ proto resource http_get_request_body_stream(void)
6187 + 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. */
6188 +PHP_FUNCTION(http_get_request_body_stream)
6194 + if ((s = http_get_request_body_stream())) {
6195 + php_stream_to_zval(s, return_value);
6197 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Failed to create request body stream");
6203 +/* {{{ proto bool http_match_request_header(string header, string value[, bool match_case = false])
6204 + Match an incoming HTTP header. */
6205 +PHP_FUNCTION(http_match_request_header)
6207 + char *header, *value;
6208 + int header_len, value_len;
6209 + zend_bool match_case = 0;
6211 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &header, &header_len, &value, &value_len, &match_case)) {
6215 + RETURN_BOOL(http_match_request_header_ex(header, value, match_case));
6219 +/* {{{ proto object http_persistent_handles_count() */
6220 +PHP_FUNCTION(http_persistent_handles_count)
6223 + object_init(return_value);
6224 + if (!http_persistent_handle_statall_ex(HASH_OF(return_value))) {
6225 + zval_dtor(return_value);
6231 +/* {{{ proto void http_persistent_handles_clean([string name]) */
6232 +PHP_FUNCTION(http_persistent_handles_clean)
6234 + char *name_str = NULL;
6237 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) {
6238 + http_persistent_handle_cleanup_ex(name_str, name_len, 1);
6243 +/* {{{ proto string http_persistent_handles_ident([string ident]) */
6244 +PHP_FUNCTION(http_persistent_handles_ident)
6246 + char *ident_str = NULL;
6247 + int ident_len = 0;
6249 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ident_str, &ident_len)) {
6250 + RETVAL_STRING(zend_ini_string(ZEND_STRS("http.persistent.handles.ident"), 0), 1);
6251 + if (ident_str && ident_len) {
6252 + zend_alter_ini_entry(ZEND_STRS("http.persistent.handles.ident"), ident_str, ident_len, ZEND_INI_USER, PHP_INI_STAGE_RUNTIME);
6258 +/* {{{ HAVE_CURL */
6259 +#ifdef HTTP_HAVE_CURL
6261 +#define RETVAL_RESPONSE_OR_BODY(request) \
6263 + zval **bodyonly; \
6265 + /* check if only the body should be returned */ \
6266 + if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void *) &bodyonly)) && i_zend_is_true(*bodyonly)) { \
6267 + http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \
6270 + RETVAL_STRINGL(PHPSTR_VAL(&msg->body), PHPSTR_LEN(&msg->body), 1); \
6271 + http_message_free(&msg); \
6274 + RETVAL_STRINGL(request.conv.response.data, request.conv.response.used, 1); \
6278 +/* {{{ proto string http_get(string url[, array options[, array &info]])
6279 + Performs an HTTP GET request on the supplied url. */
6280 +PHP_FUNCTION(http_get)
6282 + zval *options = NULL, *info = NULL;
6285 + http_request request;
6287 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
6298 + http_request_init_ex(&request, NULL, HTTP_GET, URL);
6299 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6300 + http_request_exec(&request);
6302 + http_request_info(&request, Z_ARRVAL_P(info));
6304 + RETVAL_RESPONSE_OR_BODY(request);
6306 + http_request_dtor(&request);
6310 +/* {{{ proto string http_head(string url[, array options[, array &info]])
6311 + Performs an HTTP HEAD request on the supplied url. */
6312 +PHP_FUNCTION(http_head)
6314 + zval *options = NULL, *info = NULL;
6317 + http_request request;
6319 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
6330 + http_request_init_ex(&request, NULL, HTTP_HEAD, URL);
6331 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6332 + http_request_exec(&request);
6334 + http_request_info(&request, Z_ARRVAL_P(info));
6336 + RETVAL_RESPONSE_OR_BODY(request);
6338 + http_request_dtor(&request);
6342 +/* {{{ proto string http_post_data(string url, string data[, array options[, array &info]])
6343 + Performs an HTTP POST request on the supplied url. */
6344 +PHP_FUNCTION(http_post_data)
6346 + zval *options = NULL, *info = NULL;
6347 + char *URL, *postdata;
6348 + int postdata_len, URL_len;
6349 + http_request_body body;
6350 + http_request request;
6352 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
6363 + http_request_init_ex(&request, NULL, HTTP_POST, URL);
6364 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, postdata, postdata_len, 0);
6365 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6366 + http_request_exec(&request);
6368 + http_request_info(&request, Z_ARRVAL_P(info));
6370 + RETVAL_RESPONSE_OR_BODY(request);
6372 + http_request_dtor(&request);
6376 +/* {{{ proto string http_post_fields(string url, array data[, array files[, array options[, array &info]]])
6377 + Performs an HTTP POST request on the supplied url. */
6378 +PHP_FUNCTION(http_post_fields)
6380 + zval *options = NULL, *info = NULL, *fields = NULL, *files = NULL;
6383 + http_request_body body;
6384 + http_request request;
6386 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa!|a!a/!z", &URL, &URL_len, &fields, &files, &options, &info) != SUCCESS) {
6390 + if (!http_request_body_fill(&body, fields ? Z_ARRVAL_P(fields) : NULL, files ? Z_ARRVAL_P(files) : NULL)) {
6401 + http_request_init_ex(&request, NULL, HTTP_POST, URL);
6402 + request.body = &body;
6403 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6404 + http_request_exec(&request);
6406 + http_request_info(&request, Z_ARRVAL_P(info));
6408 + RETVAL_RESPONSE_OR_BODY(request);
6410 + http_request_dtor(&request);
6414 +/* {{{ proto string http_put_file(string url, string file[, array options[, array &info]])
6415 + Performs an HTTP PUT request on the supplied url. */
6416 +PHP_FUNCTION(http_put_file)
6419 + int URL_len, f_len;
6420 + zval *options = NULL, *info = NULL;
6421 + php_stream *stream;
6422 + php_stream_statbuf ssb;
6423 + http_request_body body;
6424 + http_request request;
6426 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &file, &f_len, &options, &info)) {
6430 + if (!(stream = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) {
6433 + if (php_stream_stat(stream, &ssb)) {
6434 + php_stream_close(stream);
6445 + http_request_init_ex(&request, NULL, HTTP_PUT, URL);
6446 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
6447 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6448 + http_request_exec(&request);
6450 + http_request_info(&request, Z_ARRVAL_P(info));
6452 + RETVAL_RESPONSE_OR_BODY(request);
6454 + http_request_dtor(&request);
6458 +/* {{{ proto string http_put_stream(string url, resource stream[, array options[, array &info]])
6459 + Performs an HTTP PUT request on the supplied url. */
6460 +PHP_FUNCTION(http_put_stream)
6462 + zval *resource, *options = NULL, *info = NULL;
6465 + php_stream *stream;
6466 + php_stream_statbuf ssb;
6467 + http_request_body body;
6468 + http_request request;
6470 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) {
6474 + php_stream_from_zval(stream, &resource);
6475 + if (php_stream_stat(stream, &ssb)) {
6486 + http_request_init_ex(&request, NULL, HTTP_PUT, URL);
6487 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 0);
6488 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6489 + http_request_exec(&request);
6491 + http_request_info(&request, Z_ARRVAL_P(info));
6493 + RETVAL_RESPONSE_OR_BODY(request);
6495 + http_request_dtor(&request);
6499 +/* {{{ proto string http_put_data(string url, string data[, array options[, array &info]])
6500 + Performs an HTTP PUT request on the supplied url. */
6501 +PHP_FUNCTION(http_put_data)
6504 + int URL_len, data_len;
6505 + zval *options = NULL, *info = NULL;
6506 + http_request_body body;
6507 + http_request request;
6509 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &data, &data_len, &options, &info)) {
6520 + http_request_init_ex(&request, NULL, HTTP_PUT, URL);
6521 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
6522 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6523 + http_request_exec(&request);
6525 + http_request_info(&request, Z_ARRVAL_P(info));
6527 + RETVAL_RESPONSE_OR_BODY(request);
6529 + http_request_dtor(&request);
6533 +/* {{{ proto string http_request(int method, string url[, string body[, array options[, array &info]]])
6534 + Performs a custom HTTP request on the supplied url. */
6535 +PHP_FUNCTION(http_request)
6538 + char *URL, *data = NULL;
6539 + int URL_len, data_len = 0;
6540 + zval *options = NULL, *info = NULL;
6541 + http_request_body body;
6542 + http_request request;
6544 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|sa/!z", &meth, &URL, &URL_len, &data, &data_len, &options, &info)) {
6555 + http_request_init_ex(&request, NULL, meth, URL);
6556 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
6557 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6558 + http_request_exec(&request);
6560 + http_request_info(&request, Z_ARRVAL_P(info));
6562 + RETVAL_RESPONSE_OR_BODY(request);
6564 + http_request_dtor(&request);
6568 +/* {{{ proto string http_request_body_encode(array fields, array files)
6569 + Generate x-www-form-urlencoded resp. form-data encoded request body. */
6570 +PHP_FUNCTION(http_request_body_encode)
6572 + zval *fields = NULL, *files = NULL;
6573 + HashTable *fields_ht, *files_ht;
6574 + http_request_body body;
6578 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!", &fields, &files)) {
6582 + fields_ht = (fields && Z_TYPE_P(fields) == IS_ARRAY) ? Z_ARRVAL_P(fields) : NULL;
6583 + files_ht = (files && Z_TYPE_P(files) == IS_ARRAY) ? Z_ARRVAL_P(files) : NULL;
6584 + if (http_request_body_fill(&body, fields_ht, files_ht) && (SUCCESS == http_request_body_encode(&body, &buf, &len))) {
6585 + RETVAL_STRINGL(buf, len, 0);
6587 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not encode request body");
6590 + http_request_body_dtor(&body);
6592 +#endif /* HTTP_HAVE_CURL */
6593 +/* }}} HAVE_CURL */
6595 +/* {{{ proto int http_request_method_register(string method)
6596 + Register a custom request method. */
6597 +PHP_FUNCTION(http_request_method_register)
6603 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
6606 + if ((existing = http_request_method_exists(1, 0, method))) {
6607 + RETURN_LONG((long) existing);
6610 + RETVAL_LONG((long) http_request_method_register(method, method_len));
6614 +/* {{{ proto bool http_request_method_unregister(mixed method)
6615 + Unregister a previously registered custom request method. */
6616 +PHP_FUNCTION(http_request_method_unregister)
6620 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
6624 + switch (Z_TYPE_P(method)) {
6626 + convert_to_string(method);
6628 + if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
6629 + convert_to_long(method);
6632 + if (!(mn = http_request_method_exists(1, 0, Z_STRVAL_P(method)))) {
6635 + zval_dtor(method);
6636 + ZVAL_LONG(method, (long)mn);
6639 + RETURN_SUCCESS(http_request_method_unregister(Z_LVAL_P(method)));
6646 +/* {{{ proto int http_request_method_exists(mixed method)
6647 + Check if a request method is registered (or available by default). */
6648 +PHP_FUNCTION(http_request_method_exists)
6650 + if (return_value_used) {
6653 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
6657 + switch (Z_TYPE_P(method)) {
6659 + convert_to_string(method);
6661 + if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
6662 + convert_to_long(method);
6664 + RETURN_LONG((long) http_request_method_exists(1, 0, Z_STRVAL_P(method)));
6667 + RETURN_LONG((long) http_request_method_exists(0, (int) Z_LVAL_P(method), NULL));
6675 +/* {{{ proto string http_request_method_name(int method)
6676 + Get the literal string representation of a standard or registered request method. */
6677 +PHP_FUNCTION(http_request_method_name)
6679 + if (return_value_used) {
6682 + if ((SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method)) || (method < 0)) {
6686 + RETURN_STRING(estrdup(http_request_method_name((int) method)), 0);
6692 +#ifdef HTTP_HAVE_ZLIB
6694 +/* {{{ proto string http_deflate(string data[, int flags = 0])
6695 + Compress data with gzip, zlib AKA deflate or raw deflate encoding. */
6696 +PHP_FUNCTION(http_deflate)
6704 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags)) {
6706 + size_t encoded_len;
6708 + if (SUCCESS == http_encoding_deflate(flags, data, data_len, &encoded, &encoded_len)) {
6709 + RETURN_STRINGL(encoded, (int) encoded_len, 0);
6715 +/* {{{ proto string http_inflate(string data)
6716 + Decompress data compressed with either gzip, deflate AKA zlib or raw deflate encoding. */
6717 +PHP_FUNCTION(http_inflate)
6724 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
6726 + size_t decoded_len;
6728 + if (SUCCESS == http_encoding_inflate(data, data_len, &decoded, &decoded_len)) {
6729 + RETURN_STRINGL(decoded, (int) decoded_len, 0);
6735 +/* {{{ proto string ob_deflatehandler(string data, int mode)
6736 + For use with ob_start(). The deflate output buffer handler can only be used once. */
6737 +PHP_FUNCTION(ob_deflatehandler)
6743 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
6747 + http_ob_deflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
6748 + Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
6752 +/* {{{ proto string ob_inflatehandler(string data, int mode)
6753 + For use with ob_start(). Same restrictions as with ob_deflatehandler apply. */
6754 +PHP_FUNCTION(ob_inflatehandler)
6760 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
6764 + http_ob_inflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
6765 + Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
6769 +#endif /* HTTP_HAVE_ZLIB */
6772 +/* {{{ proto int http_support([int feature = 0])
6773 + Check for feature that require external libraries. */
6774 +PHP_FUNCTION(http_support)
6780 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &feature)) {
6781 + RETVAL_LONG(http_support(feature));
6787 + * Local variables:
6789 + * c-basic-offset: 4
6791 + * vim600: noet sw=4 ts=4 fdm=marker
6792 + * vim<600: noet sw=4 ts=4
6796 +++ b/ext/http/http_headers_api.c
6799 + +--------------------------------------------------------------------+
6801 + +--------------------------------------------------------------------+
6802 + | Redistribution and use in source and binary forms, with or without |
6803 + | modification, are permitted provided that the conditions mentioned |
6804 + | in the accompanying LICENSE file are met. |
6805 + +--------------------------------------------------------------------+
6806 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
6807 + +--------------------------------------------------------------------+
6810 +/* $Id: http_headers_api.c 300300 2010-06-09 07:29:35Z mike $ */
6812 +#define HTTP_WANT_SAPI
6813 +#include "php_http.h"
6815 +#include "ext/standard/url.h"
6816 +#include "ext/standard/php_string.h"
6818 +#include "php_http_api.h"
6819 +#include "php_http_headers_api.h"
6821 +#ifndef HTTP_DBG_NEG
6822 +# define HTTP_DBG_NEG 0
6825 +/* {{{ static void http_grab_response_headers(void *, void *) */
6826 +static void http_grab_response_headers(void *data, void *arg TSRMLS_DC)
6828 + phpstr_appendl(PHPSTR(arg), ((sapi_header_struct *)data)->header);
6829 + phpstr_appends(PHPSTR(arg), HTTP_CRLF);
6833 +/* {{{ static int http_sort_q(const void *, const void *) */
6834 +static int http_sort_q(const void *a, const void *b TSRMLS_DC)
6837 + zval result, *first, *second;
6839 + f = *((Bucket **) a);
6840 + s = *((Bucket **) b);
6842 + first = *((zval **) f->pData);
6843 + second= *((zval **) s->pData);
6845 + if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) {
6848 + return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0));
6852 +/* {{{ char *http_negotiate_language_func */
6853 +char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
6857 + const char *dash_test;
6859 + FOREACH_HASH_VAL(pos, supported, value) {
6861 + fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
6863 + if (!strcasecmp(Z_STRVAL_PP(value), test)) {
6864 + return Z_STRVAL_PP(value);
6868 + /* no distinct match found, so try primaries */
6869 + if ((dash_test = strchr(test, '-'))) {
6870 + FOREACH_HASH_VAL(pos, supported, value) {
6871 + int len = dash_test - test;
6873 + fprintf(stderr, "strncasecmp('%s', '%s', %d)\n", Z_STRVAL_PP(value), test, len);
6875 + if ( (!strncasecmp(Z_STRVAL_PP(value), test, len)) &&
6876 + ( (Z_STRVAL_PP(value)[len] == '\0') ||
6877 + (Z_STRVAL_PP(value)[len] == '-'))) {
6879 + return Z_STRVAL_PP(value);
6888 +/* {{{ char *http_negotiate_default_func */
6889 +char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
6894 + FOREACH_HASH_VAL(pos, supported, value) {
6896 + fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
6898 + if (!strcasecmp(Z_STRVAL_PP(value), test)) {
6899 + return Z_STRVAL_PP(value);
6907 +/* {{{ HashTable *http_negotiate_z(zval *, HashTable *, negotiate_func_t) */
6908 +PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC)
6910 + zval *accept = http_zsep(IS_STRING, value);
6911 + HashTable *result = NULL;
6913 + if (Z_STRLEN_P(accept)) {
6914 + zval ex_arr, ex_del;
6916 + INIT_PZVAL(&ex_del);
6917 + INIT_PZVAL(&ex_arr);
6918 + ZVAL_STRINGL(&ex_del, ",", 1, 0);
6919 + array_init(&ex_arr);
6921 + php_explode(&ex_del, accept, &ex_arr, INT_MAX);
6923 + if (zend_hash_num_elements(Z_ARRVAL(ex_arr)) > 0) {
6926 + zval **entry, array;
6928 + INIT_PZVAL(&array);
6929 + array_init(&array);
6931 + FOREACH_HASH_VAL(pos, Z_ARRVAL(ex_arr), entry) {
6934 + char *selected, *identifier, *freeme;
6935 + const char *separator;
6938 + fprintf(stderr, "Checking %s\n", Z_STRVAL_PP(entry));
6941 + if ((separator = strchr(Z_STRVAL_PP(entry), ';'))) {
6942 + const char *ptr = separator;
6944 + while (*++ptr && !HTTP_IS_CTYPE(digit, *ptr) && '.' != *ptr);
6946 + quality = zend_strtod(ptr, NULL);
6947 + identifier = estrndup(Z_STRVAL_PP(entry), ident_len = separator - Z_STRVAL_PP(entry));
6949 + quality = 1000.0 - i++;
6950 + identifier = estrndup(Z_STRVAL_PP(entry), ident_len = Z_STRLEN_PP(entry));
6952 + freeme = identifier;
6954 + while (HTTP_IS_CTYPE(space, *identifier)) {
6958 + while (ident_len && HTTP_IS_CTYPE(space, identifier[ident_len - 1])) {
6959 + identifier[--ident_len] = '\0';
6962 + if ((selected = neg(identifier, &quality, supported TSRMLS_CC))) {
6963 + /* don't overwrite previously set with higher quality */
6964 + if (!zend_hash_exists(Z_ARRVAL(array), selected, strlen(selected) + 1)) {
6965 + add_assoc_double(&array, selected, quality);
6972 + result = Z_ARRVAL(array);
6973 + zend_hash_sort(result, zend_qsort, http_sort_q, 0 TSRMLS_CC);
6976 + zval_dtor(&ex_arr);
6979 + zval_ptr_dtor(&accept);
6985 +/* {{{ HashTable *http_negotiate_q(const char *, HashTable *, negotiate_func_t) */
6986 +PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC)
6991 + fprintf(stderr, "Reading header %s: ", header);
6993 + if (!(accept = http_get_server_var(header, 1))) {
6997 + fprintf(stderr, "%s\n", Z_STRVAL_P(accept));
7000 + return http_negotiate_z(accept, supported, neg);
7004 +/* {{{ http_range_status http_get_request_ranges(HashTable *ranges, size_t) */
7005 +PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC)
7009 + long begin = -1, end = -1, *ptr;
7011 + if ( !(zrange = http_get_server_var("HTTP_RANGE", 1)) ||
7012 + (size_t) Z_STRLEN_P(zrange) < lenof("bytes=") || strncmp(Z_STRVAL_P(zrange), "bytes=", lenof("bytes="))) {
7015 + range = Z_STRVAL_P(zrange) + lenof("bytes=");
7019 + switch (c = *(range++)) {
7021 + /* allow 000... - shall we? */
7022 + if (*ptr != -10) {
7027 + case '1': case '2': case '3':
7028 + case '4': case '5': case '6':
7029 + case '7': case '8': case '9':
7031 + * If the value of the pointer is already set (non-negative)
7032 + * then multiply its value by ten and add the current value,
7033 + * else initialise the pointers value with the current value
7035 + * This let us recognize empty fields when validating the
7036 + * ranges, i.e. a "-10" for begin and "12345" for the end
7037 + * was the following range request: "Range: bytes=0-12345";
7038 + * While a "-1" for begin and "12345" for the end would
7039 + * have been: "Range: bytes=-12345".
7060 + /* validate ranges */
7075 + if (length <= (size_t) end) {
7085 + /* "-", "-0" or overflow */
7086 + if (end == -1 || end == -10 || length <= (size_t) end) {
7089 + begin = length - end;
7093 + /* "12345-(xxx)" */
7102 + if (length <= (size_t) begin) {
7108 + /* "12345-67890" */
7110 + if ( (length <= (size_t) begin) ||
7111 + (length <= (size_t) end) ||
7122 + MAKE_STD_ZVAL(zentry);
7123 + array_init(zentry);
7124 + add_index_long(zentry, 0, begin);
7125 + add_index_long(zentry, 1, end);
7126 + zend_hash_next_index_insert(ranges, &zentry, sizeof(zval *), NULL);
7143 +/* {{{ STATUS http_parse_headers(char *, HashTable *, zend_bool) */
7144 +PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *headers, zend_bool prettify,
7145 + http_info_callback callback_func, void **callback_data TSRMLS_DC)
7147 + const char *colon = NULL, *line = NULL;
7150 + INIT_ZARR(array, headers);
7152 + /* skip leading ws */
7153 + while (HTTP_IS_CTYPE(space, *header)) ++header;
7156 +#define MORE_HEADERS (*(line-1) && !(*(line-1) == '\n' && (*line == '\n' || *line == '\r')))
7158 + int value_len = 0;
7160 + switch (*line++) {
7168 + --value_len; /* we don't have CR so value length is one char less */
7170 + if ((!*(line - 1)) || ((*line != ' ') && (*line != '\t'))) {
7173 + if (SUCCESS == http_info_parse(header, &i)) {
7174 + /* response/request line */
7175 + callback_func(callback_data, &headers, &i TSRMLS_CC);
7176 + http_info_dtor(&i);
7177 + Z_ARRVAL(array) = headers;
7178 + } else if (colon) {
7179 + /* "header: value" pair */
7180 + if (header != colon) {
7181 + int keylen = colon - header;
7182 + const char *key = header;
7184 + /* skip leading ws */
7185 + while (keylen && HTTP_IS_CTYPE(space, *key)) --keylen, ++key;
7186 + /* skip trailing ws */
7187 + while (keylen && HTTP_IS_CTYPE(space, key[keylen - 1])) --keylen;
7190 + zval **previous = NULL;
7192 + char *keydup = estrndup(key, keylen);
7195 + keydup = pretty_key(keydup, keylen, 1, 1);
7198 + value_len += line - colon - 1;
7200 + /* skip leading ws */
7201 + while (HTTP_IS_CTYPE(space, *(++colon))) --value_len;
7202 + /* skip trailing ws */
7203 + while (HTTP_IS_CTYPE(space, colon[value_len - 1])) --value_len;
7205 + if (value_len > 0) {
7206 + value = estrndup(colon, value_len);
7208 + value = estrdup("");
7212 + /* if we already have got such a header make an array of those */
7213 + if (SUCCESS == zend_hash_find(headers, keydup, keylen + 1, (void *) &previous)) {
7214 + /* convert to array */
7215 + if (Z_TYPE_PP(previous) != IS_ARRAY) {
7216 + convert_to_array(*previous);
7218 + add_next_index_stringl(*previous, value, value_len, 0);
7220 + add_assoc_stringl(&array, keydup, value, value_len, 0);
7224 + /* empty key (" : ...") */
7228 + /* empty key (": ...") */
7231 + } else if (MORE_HEADERS) {
7232 + /* a line without a colon */
7237 + header += line - header;
7241 + } while (MORE_HEADERS);
7247 +/* {{{ void http_get_request_headers(HashTable *) */
7248 +PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC)
7250 + HashKey key = initHashKey(0);
7251 + zval **hsv, **header;
7254 + if (!HTTP_G->request.headers) {
7255 + ALLOC_HASHTABLE(HTTP_G->request.headers);
7256 + zend_hash_init(HTTP_G->request.headers, 0, NULL, ZVAL_PTR_DTOR, 0);
7258 +#ifdef ZEND_ENGINE_2
7259 + zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
7262 + if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) {
7263 + FOREACH_KEY(pos, *hsv, key) {
7264 + if (key.type == HASH_KEY_IS_STRING && key.len > 6 && !strncmp(key.str, "HTTP_", 5)) {
7266 + key.str = pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1);
7268 + zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
7269 + ZVAL_ADDREF(*header);
7270 + zend_hash_add(HTTP_G->request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
7279 + zend_hash_copy(headers, HTTP_G->request.headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
7284 +/* {{{ STATUS http_get_response_headers(HashTable *) */
7285 +PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC)
7290 + phpstr_init(&headers);
7291 + zend_llist_apply_with_argument(&SG(sapi_headers).headers, http_grab_response_headers, &headers TSRMLS_CC);
7292 + phpstr_fix(&headers);
7294 + status = http_parse_headers_ex(PHPSTR_VAL(&headers), headers_ht, 1);
7295 + phpstr_dtor(&headers);
7301 +/* {{{ zend_bool http_match_request_header(char *, char *) */
7302 +PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC)
7305 + uint name_len = strlen(header);
7306 + zend_bool result = 0;
7307 + zval **data, *zvalue;
7309 + http_get_request_headers(NULL);
7310 + name = pretty_key(estrndup(header, name_len), name_len, 1, 1);
7311 + if (SUCCESS == zend_hash_find(HTTP_G->request.headers, name, name_len+1, (void *) &data)) {
7312 + zvalue = http_zsep(IS_STRING, *data);
7313 + result = (match_case ? strcmp(Z_STRVAL_P(zvalue), value) : strcasecmp(Z_STRVAL_P(zvalue), value)) ? 0 : 1;
7314 + zval_ptr_dtor(&zvalue);
7324 + * Local variables:
7326 + * c-basic-offset: 4
7328 + * vim600: noet sw=4 ts=4 fdm=marker
7329 + * vim<600: noet sw=4 ts=4
7333 +++ b/ext/http/http_inflatestream_object.c
7336 + +--------------------------------------------------------------------+
7338 + +--------------------------------------------------------------------+
7339 + | Redistribution and use in source and binary forms, with or without |
7340 + | modification, are permitted provided that the conditions mentioned |
7341 + | in the accompanying LICENSE file are met. |
7342 + +--------------------------------------------------------------------+
7343 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
7344 + +--------------------------------------------------------------------+
7347 +/* $Id: http_inflatestream_object.c 300299 2010-06-09 06:23:16Z mike $ */
7349 +#define HTTP_WANT_ZLIB
7350 +#include "php_http.h"
7352 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB)
7354 +#include "php_http_api.h"
7355 +#include "php_http_encoding_api.h"
7356 +#include "php_http_exception_object.h"
7357 +#include "php_http_inflatestream_object.h"
7359 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpInflateStream, method, 0, req_args)
7360 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpInflateStream, method, 0)
7361 +#define HTTP_INFLATE_ME(method, visibility) PHP_ME(HttpInflateStream, method, HTTP_ARGS(HttpInflateStream, method), visibility)
7363 +HTTP_BEGIN_ARGS(__construct, 0)
7364 + HTTP_ARG_VAL(flags, 0)
7367 +HTTP_BEGIN_ARGS(factory, 0)
7368 + HTTP_ARG_VAL(flags, 0)
7369 + HTTP_ARG_VAL(class_name, 0)
7372 +HTTP_BEGIN_ARGS(update, 1)
7373 + HTTP_ARG_VAL(data, 0)
7376 +HTTP_BEGIN_ARGS(flush, 0)
7377 + HTTP_ARG_VAL(data, 0)
7380 +HTTP_BEGIN_ARGS(finish, 0)
7381 + HTTP_ARG_VAL(data, 0)
7384 +#define THIS_CE http_inflatestream_object_ce
7385 +zend_class_entry *http_inflatestream_object_ce;
7386 +zend_function_entry http_inflatestream_object_fe[] = {
7387 + HTTP_INFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
7388 + HTTP_INFLATE_ME(update, ZEND_ACC_PUBLIC)
7389 + HTTP_INFLATE_ME(flush, ZEND_ACC_PUBLIC)
7390 + HTTP_INFLATE_ME(finish, ZEND_ACC_PUBLIC)
7392 + HTTP_INFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
7394 + EMPTY_FUNCTION_ENTRY
7396 +static zend_object_handlers http_inflatestream_object_handlers;
7398 +PHP_MINIT_FUNCTION(http_inflatestream_object)
7400 + HTTP_REGISTER_CLASS_EX(HttpInflateStream, http_inflatestream_object, NULL, 0);
7401 + http_inflatestream_object_handlers.clone_obj = _http_inflatestream_object_clone_obj;
7404 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
7405 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
7406 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
7412 +zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
7414 + return http_inflatestream_object_new_ex(ce, NULL, NULL);
7417 +zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC)
7419 + zend_object_value ov;
7420 + http_inflatestream_object *o;
7422 + o = ecalloc(1, sizeof(http_inflatestream_object));
7433 + ALLOC_HASHTABLE(OBJ_PROP(o));
7434 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
7435 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
7437 + ov.handle = putObject(http_inflatestream_object, o);
7438 + ov.handlers = &http_inflatestream_object_handlers;
7443 +zend_object_value _http_inflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
7445 + http_encoding_stream *s;
7446 + zend_object_value new_ov;
7447 + http_inflatestream_object *new_obj = NULL;
7448 + getObject(http_inflatestream_object, old_obj);
7450 + s = ecalloc(1, sizeof(http_encoding_stream));
7451 + s->flags = old_obj->stream->flags;
7452 + inflateCopy(&s->stream, &old_obj->stream->stream);
7453 + s->stream.opaque = phpstr_dup(s->stream.opaque);
7455 + new_ov = http_inflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
7456 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
7461 +void _http_inflatestream_object_free(zend_object *object TSRMLS_DC)
7463 + http_inflatestream_object *o = (http_inflatestream_object *) object;
7466 + http_encoding_inflate_stream_free(&o->stream);
7471 +/* {{{ proto void HttpInflateStream::__construct([int flags = 0])
7472 + Creates a new HttpInflateStream object instance. */
7473 +PHP_METHOD(HttpInflateStream, __construct)
7477 + SET_EH_THROW_HTTP();
7478 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
7479 + getObject(http_inflatestream_object, obj);
7481 + if (!obj->stream) {
7482 + obj->stream = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
7484 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpInflateStream cannot be initialized twice");
7491 +/* {{{ proto HttpInflateStream HttpInflateStream::factory([int flags[, string class = "HttpInflateStream"]])
7492 + Creates a new HttpInflateStream object instance. */
7493 +PHP_METHOD(HttpInflateStream, factory)
7499 + SET_EH_THROW_HTTP();
7500 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
7501 + zend_object_value ov;
7502 + http_encoding_stream *s = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
7504 + if (SUCCESS == http_object_new(&ov, cn, cl, _http_inflatestream_object_new_ex, http_inflatestream_object_ce, s, NULL)) {
7505 + RETVAL_OBJVAL(ov, 0);
7512 +/* {{{ proto string HttpInflateStream::update(string data)
7513 + Passes more data through the inflate stream. */
7514 +PHP_METHOD(HttpInflateStream, update)
7517 + size_t decoded_len = 0;
7518 + char *data, *decoded = NULL;
7519 + getObject(http_inflatestream_object, obj);
7521 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
7526 + RETURN_STRING("", 1);
7529 + if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
7533 + if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
7534 + RETURN_STRINGL(decoded, decoded_len, 0);
7541 +/* {{{ proto string HttpInflateStream::flush([string data])
7542 + Flush the inflate stream. */
7543 +PHP_METHOD(HttpInflateStream, flush)
7546 + size_t decoded_len = 0;
7547 + char *decoded = NULL, *data = NULL;
7548 + getObject(http_inflatestream_object, obj);
7550 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
7554 + if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
7558 + /* flushing the inflate stream is a no-op */
7560 + RETURN_STRINGL("", 0, 1);
7561 + } else if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
7562 + RETURN_STRINGL(decoded, decoded_len, 0);
7569 +/* {{{ proto string HttpInflateStream::finish([string data])
7570 + Finalizes the inflate stream. The inflate stream can be reused after finalizing. */
7571 +PHP_METHOD(HttpInflateStream, finish)
7574 + size_t updated_len = 0, decoded_len = 0;
7575 + char *updated = NULL, *decoded = NULL, *data = NULL;
7576 + getObject(http_inflatestream_object, obj);
7578 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
7582 + if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
7587 + if (SUCCESS != http_encoding_inflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
7592 + if (SUCCESS == http_encoding_inflate_stream_finish(obj->stream, &decoded, &decoded_len)) {
7593 + if (updated_len) {
7594 + updated = erealloc(updated, updated_len + decoded_len + 1);
7595 + updated[updated_len + decoded_len] = '\0';
7596 + memcpy(updated + updated_len, decoded, decoded_len);
7597 + STR_FREE(decoded);
7598 + updated_len += decoded_len;
7599 + RETVAL_STRINGL(updated, updated_len, 0);
7600 + } else if (decoded) {
7601 + STR_FREE(updated);
7602 + RETVAL_STRINGL(decoded, decoded_len, 0);
7607 + STR_FREE(updated);
7611 + http_encoding_inflate_stream_dtor(obj->stream);
7612 + http_encoding_inflate_stream_init(obj->stream, obj->stream->flags);
7616 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
7619 + * Local variables:
7621 + * c-basic-offset: 4
7623 + * vim600: noet sw=4 ts=4 fdm=marker
7624 + * vim<600: noet sw=4 ts=4
7628 +++ b/ext/http/http_info_api.c
7631 + +--------------------------------------------------------------------+
7633 + +--------------------------------------------------------------------+
7634 + | Redistribution and use in source and binary forms, with or without |
7635 + | modification, are permitted provided that the conditions mentioned |
7636 + | in the accompanying LICENSE file are met. |
7637 + +--------------------------------------------------------------------+
7638 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
7639 + +--------------------------------------------------------------------+
7642 +/* $Id: http_info_api.c 304921 2010-10-26 15:27:36Z iliaa $ */
7644 +#include "php_http.h"
7646 +#include "php_http_api.h"
7647 +#include "php_http_info_api.h"
7649 +PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC)
7653 + INIT_ZARR(array, *headers);
7655 + switch (info->type) {
7656 + case IS_HTTP_REQUEST:
7657 + add_assoc_string(&array, "Request Method", HTTP_INFO(info).request.method, 1);
7658 + add_assoc_string(&array, "Request Url", HTTP_INFO(info).request.url, 1);
7661 + case IS_HTTP_RESPONSE:
7662 + add_assoc_long(&array, "Response Code", (long) HTTP_INFO(info).response.code);
7663 + if (HTTP_INFO(info).response.status) {
7664 + add_assoc_string(&array, "Response Status", HTTP_INFO(info).response.status, 1);
7670 +PHP_HTTP_API void _http_info_dtor(http_info *i)
7672 + switch (i->type) {
7673 + case IS_HTTP_REQUEST:
7674 + STR_SET(HTTP_INFO(i).request.method, NULL);
7675 + STR_SET(HTTP_INFO(i).request.url, NULL);
7678 + case IS_HTTP_RESPONSE:
7679 + STR_SET(HTTP_INFO(i).response.status, NULL);
7687 +PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info, zend_bool silent TSRMLS_DC)
7689 + const char *end, *http;
7691 + /* sane parameter */
7692 + if ((!pre_header) || (!*pre_header)) {
7696 + /* where's the end of the line */
7697 + if (!(end = http_locate_eol(pre_header, NULL))) {
7698 + end = pre_header + strlen(pre_header);
7701 + /* there must be HTTP/1.x in the line */
7702 + if (!(http = http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) {
7706 + /* and nothing than SPACE or NUL after HTTP/1.x */
7707 + if ( (!HTTP_IS_CTYPE(digit, http[lenof("HTTP/1.")])) ||
7708 + (http[lenof("HTTP/1.1")] && (!HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) {
7710 + http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid HTTP/1.x protocol identification");
7717 + char *line = estrndup(pre_header, end - pre_header);
7718 + fprintf(stderr, "http_parse_info('%s')\n", line);
7723 + info->http.version = zend_strtod(http + lenof("HTTP/"), NULL);
7726 + if (pre_header == http) {
7727 + char *status = NULL;
7728 + const char *code = http + sizeof("HTTP/1.1");
7730 + info->type = IS_HTTP_RESPONSE;
7731 + while (' ' == *code) ++code;
7732 + if (code && end > code) {
7733 + HTTP_INFO(info).response.code = strtol(code, &status, 10);
7735 + HTTP_INFO(info).response.code = 0;
7737 + if (status && end > status) {
7738 + while (' ' == *status) ++status;
7739 + HTTP_INFO(info).response.status = estrndup(status, end - status);
7741 + HTTP_INFO(info).response.status = NULL;
7748 + else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') {
7749 + const char *url = strchr(pre_header, ' ');
7751 + info->type = IS_HTTP_REQUEST;
7752 + if (url && http > url) {
7753 + HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header);
7754 + while (' ' == *url) ++url;
7755 + while (' ' == *(http-1)) --http;
7757 + HTTP_INFO(info).request.url = estrndup(url, http - url);
7759 + efree(HTTP_INFO(info).request.method);
7763 + HTTP_INFO(info).request.method = NULL;
7764 + HTTP_INFO(info).request.url = NULL;
7770 + /* some darn header containing HTTP/1.x */
7777 + * Local variables:
7779 + * c-basic-offset: 4
7781 + * vim600: noet sw=4 ts=4 fdm=marker
7782 + * vim<600: noet sw=4 ts=4
7786 +++ b/ext/http/http_message_api.c
7789 + +--------------------------------------------------------------------+
7791 + +--------------------------------------------------------------------+
7792 + | Redistribution and use in source and binary forms, with or without |
7793 + | modification, are permitted provided that the conditions mentioned |
7794 + | in the accompanying LICENSE file are met. |
7795 + +--------------------------------------------------------------------+
7796 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
7797 + +--------------------------------------------------------------------+
7800 +/* $Id: http_message_api.c 298689 2010-04-28 06:50:06Z mike $ */
7802 +#define HTTP_WANT_SAPI
7803 +#define HTTP_WANT_CURL
7804 +#define HTTP_WANT_ZLIB
7805 +#include "php_http.h"
7807 +#include "php_http_api.h"
7808 +#include "php_http_encoding_api.h"
7809 +#include "php_http_headers_api.h"
7810 +#include "php_http_message_api.h"
7811 +#include "php_http_request_api.h"
7812 +#include "php_http_send_api.h"
7813 +#include "php_http_url_api.h"
7815 +#define http_message_info_callback _http_message_info_callback
7816 +static void _http_message_info_callback(http_message **message, HashTable **headers, http_info *info TSRMLS_DC)
7818 + http_message *old = *message;
7820 + /* advance message */
7821 + if (old->type || zend_hash_num_elements(&old->hdrs) || PHPSTR_LEN(old)) {
7822 + (*message) = http_message_new();
7823 + (*message)->parent = old;
7824 + (*headers) = &((*message)->hdrs);
7827 + http_message_set_info(*message, info);
7830 +#define http_message_init_type _http_message_init_type
7831 +static inline void _http_message_init_type(http_message *message, http_message_type type)
7833 + message->http.version = .0;
7835 + switch (message->type = type) {
7836 + case HTTP_MSG_RESPONSE:
7837 + message->http.info.response.code = 0;
7838 + message->http.info.response.status = NULL;
7841 + case HTTP_MSG_REQUEST:
7842 + message->http.info.request.method = NULL;
7843 + message->http.info.request.url = NULL;
7846 + case HTTP_MSG_NONE:
7852 +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)
7855 + message = ecalloc_rel(1, sizeof(http_message));
7858 + http_message_init_type(message, type);
7859 + message->parent = NULL;
7860 + phpstr_init(&message->body);
7861 + zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0);
7866 +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)
7874 + if ((free_msg = !message)) {
7875 + message = http_message_init_rel(NULL, HTTP_MSG_NONE);
7878 + memset(&inf, 0, sizeof(http_info));
7879 + switch (inf.type = type) {
7880 + case HTTP_MSG_REQUEST:
7881 + if ((sval = http_get_server_var("SERVER_PROTOCOL", 1)) && !strncmp(Z_STRVAL_P(sval), "HTTP/", lenof("HTTP/"))) {
7882 + inf.http.version = zend_strtod(Z_STRVAL_P(sval) + lenof("HTTP/"), NULL);
7884 + inf.http.version = 1.1;
7886 + if ((sval = http_get_server_var("REQUEST_METHOD", 1))) {
7887 + inf.http.info.request.method = estrdup(Z_STRVAL_P(sval));
7889 + if ((sval = http_get_server_var("REQUEST_URI", 1))) {
7890 + inf.http.info.request.url = estrdup(Z_STRVAL_P(sval));
7893 + http_message_set_info(message, &inf);
7894 + http_get_request_headers(&message->hdrs);
7895 + if (SUCCESS == http_get_request_body_ex(&body_str, &body_len, 0)) {
7896 + phpstr_from_string_ex(&message->body, body_str, body_len);
7900 + case HTTP_MSG_RESPONSE:
7901 + if (!SG(sapi_headers).http_status_line || SUCCESS != http_info_parse_ex(SG(sapi_headers).http_status_line, &inf, 0)) {
7902 + inf.http.version = 1.1;
7903 + inf.http.info.response.code = 200;
7904 + inf.http.info.response.status = estrdup("Ok");
7907 + http_message_set_info(message, &inf);
7908 + http_get_response_headers(&message->hdrs);
7909 + if (SUCCESS == php_ob_get_buffer(&tval TSRMLS_CC)) {
7910 + message->body.data = Z_STRVAL(tval);
7911 + message->body.used = Z_STRLEN(tval);
7912 + message->body.free = 1; /* "\0" */
7918 + http_message_free(&message);
7924 + http_info_dtor(&inf);
7929 +PHP_HTTP_API void _http_message_set_type(http_message *message, http_message_type type)
7931 + /* just act if different */
7932 + if (type != message->type) {
7934 + /* free request info */
7935 + switch (message->type) {
7936 + case HTTP_MSG_REQUEST:
7937 + STR_FREE(message->http.info.request.method);
7938 + STR_FREE(message->http.info.request.url);
7941 + case HTTP_MSG_RESPONSE:
7942 + STR_FREE(message->http.info.response.status);
7950 + http_message_init_type(message, type);
7954 +PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info)
7956 + http_message_set_type(message, info->type);
7957 + message->http.version = info->http.version;
7958 + switch (message->type) {
7959 + case IS_HTTP_REQUEST:
7960 + STR_SET(HTTP_INFO(message).request.url, HTTP_INFO(info).request.url ? estrdup(HTTP_INFO(info).request.url) : NULL);
7961 + STR_SET(HTTP_INFO(message).request.method, HTTP_INFO(info).request.method ? estrdup(HTTP_INFO(info).request.method) : NULL);
7964 + case IS_HTTP_RESPONSE:
7965 + HTTP_INFO(message).response.code = HTTP_INFO(info).response.code;
7966 + STR_SET(HTTP_INFO(message).response.status, HTTP_INFO(info).response.status ? estrdup(HTTP_INFO(info).response.status) : NULL);
7974 +#define http_message_body_parse(m, ms, ml, c) _http_message_body_parse((m), (ms), (ml), (c) TSRMLS_CC)
7975 +static inline void _http_message_body_parse(http_message *msg, const char *message, size_t message_length, const char **continue_at TSRMLS_DC)
7981 + *continue_at = NULL;
7982 + if ((body = http_locate_body(message))) {
7983 + remaining = message + message_length - body;
7985 + if ((c = http_message_header(msg, "Transfer-Encoding"))) {
7986 + if (strstr(Z_STRVAL_P(c), "chunked")) {
7987 + /* message has chunked transfer encoding */
7989 + size_t decoded_len;
7991 + /* decode and replace Transfer-Encoding with Content-Length header */
7992 + if ((*continue_at = http_encoding_dechunk(body, message + message_length - body, &decoded, &decoded_len))) {
7997 + tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
7998 + MAKE_STD_ZVAL(len);
7999 + ZVAL_STRINGL(len, tmp, tmp_len, 0);
8002 + zend_hash_update(&msg->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &c, sizeof(zval *), NULL);
8003 + zend_hash_del(&msg->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
8004 + zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length"));
8005 + zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
8007 + phpstr_from_string_ex(PHPSTR(msg), decoded, decoded_len);
8011 + zval_ptr_dtor(&c);
8014 + if (!*continue_at && (c = http_message_header(msg, "Content-Length"))) {
8015 + /* message has content-length header */
8016 + ulong len = strtoul(Z_STRVAL_P(c), NULL, 10);
8017 + if (len > remaining) {
8018 + 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);
8021 + phpstr_from_string_ex(PHPSTR(msg), body, len);
8022 + *continue_at = body + len;
8023 + zval_ptr_dtor(&c);
8026 + if (!*continue_at && (c = http_message_header(msg, "Content-Range"))) {
8027 + /* message has content-range header */
8028 + ulong total = 0, start = 0, end = 0, len = 0;
8030 + if (!strncasecmp(Z_STRVAL_P(c), "bytes", lenof("bytes")) &&
8031 + ( Z_STRVAL_P(c)[lenof("bytes")] == ':' ||
8032 + Z_STRVAL_P(c)[lenof("bytes")] == ' ' ||
8033 + Z_STRVAL_P(c)[lenof("bytes")] == '=')) {
8034 + char *total_at = NULL, *end_at = NULL;
8035 + char *start_at = Z_STRVAL_P(c) + sizeof("bytes");
8037 + start = strtoul(start_at, &end_at, 10);
8039 + end = strtoul(end_at + 1, &total_at, 10);
8040 + if (total_at && strncmp(total_at + 1, "*", 1)) {
8041 + total = strtoul(total_at + 1, NULL, 10);
8043 + if ((len = (end + 1 - start)) > remaining) {
8044 + 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);
8047 + if (end >= start && (!total || end < total)) {
8048 + phpstr_from_string_ex(PHPSTR(msg), body, len);
8049 + *continue_at = body + len;
8054 + if (!*continue_at) {
8055 + http_error_ex(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid Content-Range header: %s", Z_STRVAL_P(c));
8057 + zval_ptr_dtor(&c);
8060 + if (!*continue_at) {
8061 + /* no headers that indicate content length */
8062 + if (HTTP_MSG_TYPE(RESPONSE, msg)) {
8063 + phpstr_from_string_ex(PHPSTR(msg), body, remaining);
8065 + *continue_at = body;
8069 +#ifdef HTTP_HAVE_ZLIB
8070 + /* check for compressed data */
8071 + if ((c = http_message_header(msg, "Content-Encoding"))) {
8072 + char *decoded = NULL;
8073 + size_t decoded_len = 0;
8075 + if ( !strcasecmp(Z_STRVAL_P(c), "gzip") ||
8076 + !strcasecmp(Z_STRVAL_P(c), "x-gzip") ||
8077 + !strcasecmp(Z_STRVAL_P(c), "deflate")) {
8078 + http_encoding_inflate(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len);
8082 + zval *len, **original_len;
8086 + tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
8087 + MAKE_STD_ZVAL(len);
8088 + ZVAL_STRINGL(len, tmp, tmp_len, 0);
8091 + zend_hash_update(&msg->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), (void *) &c, sizeof(zval *), NULL);
8092 + zend_hash_del(&msg->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
8093 + if (SUCCESS == zend_hash_find(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &original_len)) {
8094 + ZVAL_ADDREF(*original_len);
8095 + zend_hash_update(&msg->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) original_len, sizeof(zval *), NULL);
8096 + zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
8098 + zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
8101 + phpstr_dtor(PHPSTR(msg));
8102 + PHPSTR(msg)->data = decoded;
8103 + PHPSTR(msg)->used = decoded_len;
8104 + PHPSTR(msg)->free = 1;
8107 + zval_ptr_dtor(&c);
8109 +#endif /* HTTP_HAVE_ZLIB */
8113 +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)
8115 + const char *continue_at;
8116 + zend_bool free_msg = msg ? 0 : 1;
8118 + if ((!message) || (message_length < HTTP_MSG_MIN_SIZE)) {
8119 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Empty or too short HTTP message: '%s'", message);
8123 + msg = http_message_init_rel(msg, 0);
8125 + if (SUCCESS != http_parse_headers_cb(message, &msg->hdrs, 1, (http_info_callback) http_message_info_callback, (void *) &msg)) {
8127 + http_message_free(&msg);
8129 + http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse message headers");
8133 + http_message_body_parse(msg, message, message_length, &continue_at);
8135 + /* check for following messages */
8136 + if (continue_at && (continue_at < (message + message_length))) {
8137 + while (HTTP_IS_CTYPE(space, *continue_at)) ++continue_at;
8138 + if (continue_at < (message + message_length)) {
8139 + http_message *next = NULL, *most = NULL;
8141 + /* set current message to parent of most parent following messages and return deepest */
8142 + if ((most = next = http_message_parse_rel(NULL, continue_at, message + message_length - continue_at))) {
8143 + while (most->parent) most = most->parent;
8144 + most->parent = msg;
8153 +PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length)
8156 + HashKey key = initHashKey(0);
8159 + HashPosition pos1;
8161 + phpstr_init_ex(&str, 4096, 0);
8163 + switch (msg->type) {
8164 + case HTTP_MSG_REQUEST:
8165 + phpstr_appendf(&str, HTTP_INFO_REQUEST_FMT_ARGS(&msg->http, HTTP_CRLF));
8168 + case HTTP_MSG_RESPONSE:
8169 + phpstr_appendf(&str, HTTP_INFO_RESPONSE_FMT_ARGS(&msg->http, HTTP_CRLF));
8172 + case HTTP_MSG_NONE:
8177 + FOREACH_HASH_KEYVAL(pos1, &msg->hdrs, key, header) {
8178 + if (key.type == HASH_KEY_IS_STRING) {
8179 + HashPosition pos2;
8180 + zval **single_header;
8182 + switch (Z_TYPE_PP(header)) {
8184 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(header)?"true":"false");
8188 + phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(header));
8192 + phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(header));
8196 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(header));
8200 + FOREACH_VAL(pos2, *header, single_header) {
8201 + switch (Z_TYPE_PP(single_header)) {
8203 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(single_header)?"true":"false");
8207 + phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(single_header));
8211 + phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(single_header));
8215 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(single_header));
8224 + if (PHPSTR_LEN(msg)) {
8225 + phpstr_appends(&str, HTTP_CRLF);
8226 + phpstr_append(&str, PHPSTR_VAL(msg), PHPSTR_LEN(msg));
8227 + phpstr_appends(&str, HTTP_CRLF);
8230 + data = phpstr_data(&str, string, length);
8235 + phpstr_dtor(&str);
8238 +PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length)
8244 + phpstr_init(&str);
8247 + http_message_tostring(message, &buf, &len);
8248 + phpstr_prepend(&str, buf, len);
8250 + } while ((message = message->parent));
8252 + buf = phpstr_data(&str, string, length);
8257 + phpstr_dtor(&str);
8260 +PHP_HTTP_API http_message *_http_message_reverse(http_message *msg)
8264 + http_message_count(c, msg);
8267 + http_message *tmp = msg, **arr = ecalloc(c, sizeof(http_message *));
8269 + for (i = 0; i < c; ++i) {
8271 + tmp = tmp->parent;
8273 + arr[0]->parent = NULL;
8274 + for (i = 0; i < c-1; ++i) {
8275 + arr[i+1]->parent = arr[i];
8285 +PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2)
8288 + int i = 0, c1, c2;
8289 + http_message *t1 = m1, *t2 = m2, *p1, *p2;
8291 + http_message_count(c1, m1);
8292 + http_message_count(c2, m2);
8294 + while (i++ < (c1 - c2)) {
8297 + while (i++ <= c1) {
8305 + } else if (!m1 && m2) {
8311 +PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *obj TSRMLS_DC)
8316 + INIT_ZARR(strct, HASH_OF(obj));
8318 + add_assoc_long(&strct, "type", msg->type);
8319 + add_assoc_double(&strct, "httpVersion", msg->http.version);
8320 + switch (msg->type)
8322 + case HTTP_MSG_RESPONSE:
8323 + add_assoc_long(&strct, "responseCode", msg->http.info.response.code);
8324 + add_assoc_string(&strct, "responseStatus", STR_PTR(msg->http.info.response.status), 1);
8327 + case HTTP_MSG_REQUEST:
8328 + add_assoc_string(&strct, "requestMethod", STR_PTR(msg->http.info.request.method), 1);
8329 + add_assoc_string(&strct, "requestUrl", STR_PTR(msg->http.info.request.url), 1);
8332 + case HTTP_MSG_NONE:
8333 + /* avoid compiler warning */
8337 + MAKE_STD_ZVAL(headers);
8338 + array_init(headers);
8339 + zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8340 + add_assoc_zval(&strct, "headers", headers);
8342 + add_assoc_stringl(&strct, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg), 1);
8344 + if (msg->parent) {
8347 + MAKE_STD_ZVAL(parent);
8348 + if (Z_TYPE_P(obj) == IS_ARRAY) {
8349 + array_init(parent);
8351 + object_init(parent);
8353 + add_assoc_zval(&strct, "parentMessage", parent);
8354 + http_message_tostruct_recursive(msg->parent, parent);
8356 + add_assoc_null(&strct, "parentMessage");
8360 +PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC)
8362 + STATUS rs = FAILURE;
8364 + switch (message->type) {
8365 + case HTTP_MSG_RESPONSE:
8367 + HashKey key = initHashKey(0);
8371 + FOREACH_HASH_KEYVAL(pos, &message->hdrs, key, val) {
8372 + if (key.type == HASH_KEY_IS_STRING) {
8373 + http_send_header_zval_ex(key.str, key.len-1, val, 1);
8376 + rs = SUCCESS == http_send_status(message->http.info.response.code) &&
8377 + SUCCESS == http_send_data(PHPSTR_VAL(message), PHPSTR_LEN(message)) ?
8378 + SUCCESS : FAILURE;
8382 + case HTTP_MSG_REQUEST:
8384 +#ifdef HTTP_HAVE_CURL
8386 + http_request request;
8387 + zval **zhost, *options, *headers;
8389 + MAKE_STD_ZVAL(options);
8390 + MAKE_STD_ZVAL(headers);
8391 + array_init(options);
8392 + array_init(headers);
8393 + zend_hash_copy(Z_ARRVAL_P(headers), &message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8394 + add_assoc_zval(options, "headers", headers);
8396 + /* check host header */
8397 + if (SUCCESS == zend_hash_find(&message->hdrs, "Host", sizeof("Host"), (void *) &zhost) && Z_TYPE_PP(zhost) == IS_STRING) {
8398 + char *colon = NULL;
8399 + php_url parts, *url = php_url_parse(message->http.info.request.url);
8401 + memset(&parts, 0, sizeof(php_url));
8403 + /* check for port */
8404 + if ((colon = strchr(Z_STRVAL_PP(zhost), ':'))) {
8405 + parts.port = atoi(colon + 1);
8406 + parts.host = estrndup(Z_STRVAL_PP(zhost), (Z_STRVAL_PP(zhost) - colon - 1));
8408 + parts.host = estrndup(Z_STRVAL_PP(zhost), Z_STRLEN_PP(zhost));
8411 + http_build_url(HTTP_URL_REPLACE, url, &parts, NULL, &uri, NULL);
8412 + php_url_free(url);
8413 + efree(parts.host);
8415 + uri = http_absolute_url(message->http.info.request.url);
8418 + if ((request.meth = http_request_method_exists(1, 0, message->http.info.request.method))) {
8419 + http_request_body body;
8421 + http_request_init_ex(&request, NULL, request.meth, uri);
8422 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, PHPSTR_VAL(message), PHPSTR_LEN(message), 0);
8423 + if (SUCCESS == (rs = http_request_prepare(&request, Z_ARRVAL_P(options)))) {
8424 + http_request_exec(&request);
8426 + http_request_dtor(&request);
8428 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD,
8429 + "Cannot send HttpMessage. Request method %s not supported",
8430 + message->http.info.request.method);
8433 + zval_ptr_dtor(&options);
8435 + http_error(HE_WARNING, HTTP_E_RUNTIME, "HTTP requests not supported - ext/http was not linked against libcurl.");
8440 + case HTTP_MSG_NONE:
8442 + http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HTTP_MSG_REQUEST nor HTTP_MSG_RESPONSE");
8449 +PHP_HTTP_API http_message *_http_message_dup(http_message *orig TSRMLS_DC)
8451 + http_message *temp, *copy = NULL;
8455 + info.type = orig->type;
8456 + info.http = orig->http;
8458 + copy = temp = http_message_new();
8459 + http_message_set_info(temp, &info);
8460 + zend_hash_copy(&temp->hdrs, &orig->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8461 + phpstr_append(&temp->body, orig->body.data, orig->body.used);
8463 + while (orig->parent) {
8464 + info.type = orig->parent->type;
8465 + info.http = orig->parent->http;
8467 + temp->parent = http_message_new();
8468 + http_message_set_info(temp->parent, &info);
8469 + zend_hash_copy(&temp->parent->hdrs, &orig->parent->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8470 + phpstr_append(&temp->parent->body, orig->parent->body.data, orig->parent->body.used);
8472 + temp = temp->parent;
8473 + orig = orig->parent;
8480 +PHP_HTTP_API void _http_message_dtor(http_message *message)
8483 + zend_hash_destroy(&message->hdrs);
8484 + phpstr_dtor(PHPSTR(message));
8486 + switch (message->type) {
8487 + case HTTP_MSG_REQUEST:
8488 + STR_SET(message->http.info.request.method, NULL);
8489 + STR_SET(message->http.info.request.url, NULL);
8492 + case HTTP_MSG_RESPONSE:
8493 + STR_SET(message->http.info.response.status, NULL);
8502 +PHP_HTTP_API void _http_message_free(http_message **message)
8505 + if ((*message)->parent) {
8506 + http_message_free(&(*message)->parent);
8508 + http_message_dtor(*message);
8515 + * Local variables:
8517 + * c-basic-offset: 4
8519 + * vim600: noet sw=4 ts=4 fdm=marker
8520 + * vim<600: noet sw=4 ts=4
8524 +++ b/ext/http/http_message_object.c
8527 + +--------------------------------------------------------------------+
8529 + +--------------------------------------------------------------------+
8530 + | Redistribution and use in source and binary forms, with or without |
8531 + | modification, are permitted provided that the conditions mentioned |
8532 + | in the accompanying LICENSE file are met. |
8533 + +--------------------------------------------------------------------+
8534 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
8535 + +--------------------------------------------------------------------+
8538 +/* $Id: http_message_object.c 309640 2011-03-24 09:26:11Z mike $ */
8540 +#define HTTP_WANT_SAPI
8541 +#define HTTP_WANT_CURL
8542 +#define HTTP_WANT_MAGIC
8543 +#include "php_http.h"
8545 +#ifdef ZEND_ENGINE_2
8547 +#include "zend_interfaces.h"
8548 +#include "ext/standard/url.h"
8549 +#include "php_variables.h"
8551 +#include "php_http_api.h"
8552 +#include "php_http_send_api.h"
8553 +#include "php_http_url_api.h"
8554 +#include "php_http_message_api.h"
8555 +#include "php_http_message_object.h"
8556 +#include "php_http_exception_object.h"
8557 +#include "php_http_response_object.h"
8558 +#include "php_http_request_method_api.h"
8559 +#include "php_http_request_api.h"
8560 +#include "php_http_request_object.h"
8561 +#include "php_http_headers_api.h"
8563 +#if defined(HTTP_HAVE_SPL) && !defined(WONKY)
8564 +/* SPL doesn't install its headers */
8565 +extern PHPAPI zend_class_entry *spl_ce_Countable;
8568 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpMessage, method, 0, req_args)
8569 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpMessage, method, 0)
8570 +#define HTTP_MESSAGE_ME(method, visibility) PHP_ME(HttpMessage, method, HTTP_ARGS(HttpMessage, method), visibility)
8572 +HTTP_BEGIN_ARGS(__construct, 0)
8573 + HTTP_ARG_VAL(message, 0)
8576 +HTTP_BEGIN_ARGS(factory, 0)
8577 + HTTP_ARG_VAL(message, 0)
8578 + HTTP_ARG_VAL(class_name, 0)
8581 +HTTP_BEGIN_ARGS(fromEnv, 1)
8582 + HTTP_ARG_VAL(type, 0)
8583 + HTTP_ARG_VAL(class_name, 0)
8586 +HTTP_EMPTY_ARGS(getBody);
8587 +HTTP_BEGIN_ARGS(setBody, 1)
8588 + HTTP_ARG_VAL(body, 0)
8591 +HTTP_BEGIN_ARGS(getHeader, 1)
8592 + HTTP_ARG_VAL(header, 0)
8595 +HTTP_EMPTY_ARGS(getHeaders);
8596 +HTTP_BEGIN_ARGS(setHeaders, 1)
8597 + HTTP_ARG_VAL(headers, 0)
8600 +HTTP_BEGIN_ARGS(addHeaders, 1)
8601 + HTTP_ARG_VAL(headers, 0)
8602 + HTTP_ARG_VAL(append, 0)
8605 +HTTP_EMPTY_ARGS(getType);
8606 +HTTP_BEGIN_ARGS(setType, 1)
8607 + HTTP_ARG_VAL(type, 0)
8610 +HTTP_EMPTY_ARGS(getInfo);
8611 +HTTP_BEGIN_ARGS(setInfo, 1)
8612 + HTTP_ARG_VAL(http_info, 0)
8615 +HTTP_EMPTY_ARGS(getResponseCode);
8616 +HTTP_BEGIN_ARGS(setResponseCode, 1)
8617 + HTTP_ARG_VAL(response_code, 0)
8620 +HTTP_EMPTY_ARGS(getResponseStatus);
8621 +HTTP_BEGIN_ARGS(setResponseStatus, 1)
8622 + HTTP_ARG_VAL(response_status, 0)
8625 +HTTP_EMPTY_ARGS(getRequestMethod);
8626 +HTTP_BEGIN_ARGS(setRequestMethod, 1)
8627 + HTTP_ARG_VAL(request_method, 0)
8630 +HTTP_EMPTY_ARGS(getRequestUrl);
8631 +HTTP_BEGIN_ARGS(setRequestUrl, 1)
8632 + HTTP_ARG_VAL(url, 0)
8635 +HTTP_EMPTY_ARGS(getHttpVersion);
8636 +HTTP_BEGIN_ARGS(setHttpVersion, 1)
8637 + HTTP_ARG_VAL(http_version, 0)
8640 +HTTP_BEGIN_ARGS(guessContentType, 1)
8641 + HTTP_ARG_VAL(magic_file, 0)
8642 + HTTP_ARG_VAL(magic_mode, 0)
8645 +HTTP_EMPTY_ARGS(getParentMessage);
8646 +HTTP_EMPTY_ARGS(send);
8647 +HTTP_EMPTY_ARGS(__toString);
8648 +HTTP_BEGIN_ARGS(toString, 0)
8649 + HTTP_ARG_VAL(include_parent, 0)
8652 +HTTP_EMPTY_ARGS(toMessageTypeObject);
8654 +HTTP_EMPTY_ARGS(count);
8656 +HTTP_EMPTY_ARGS(serialize);
8657 +HTTP_BEGIN_ARGS(unserialize, 1)
8658 + HTTP_ARG_VAL(serialized, 0)
8661 +HTTP_EMPTY_ARGS(rewind);
8662 +HTTP_EMPTY_ARGS(valid);
8663 +HTTP_EMPTY_ARGS(key);
8664 +HTTP_EMPTY_ARGS(current);
8665 +HTTP_EMPTY_ARGS(next);
8667 +HTTP_EMPTY_ARGS(detach);
8668 +HTTP_BEGIN_ARGS(prepend, 1)
8669 + HTTP_ARG_OBJ(HttpMessage, message, 0)
8671 +HTTP_EMPTY_ARGS(reverse);
8673 +#define http_message_object_read_prop _http_message_object_read_prop
8674 +static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC);
8675 +#define http_message_object_write_prop _http_message_object_write_prop
8676 +static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC);
8677 +#define http_message_object_get_prop_ptr _http_message_object_get_prop_ptr
8678 +static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC);
8679 +#define http_message_object_get_props _http_message_object_get_props
8680 +static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC);
8682 +#define THIS_CE http_message_object_ce
8683 +zend_class_entry *http_message_object_ce;
8684 +zend_function_entry http_message_object_fe[] = {
8685 + HTTP_MESSAGE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
8686 + HTTP_MESSAGE_ME(getBody, ZEND_ACC_PUBLIC)
8687 + HTTP_MESSAGE_ME(setBody, ZEND_ACC_PUBLIC)
8688 + HTTP_MESSAGE_ME(getHeader, ZEND_ACC_PUBLIC)
8689 + HTTP_MESSAGE_ME(getHeaders, ZEND_ACC_PUBLIC)
8690 + HTTP_MESSAGE_ME(setHeaders, ZEND_ACC_PUBLIC)
8691 + HTTP_MESSAGE_ME(addHeaders, ZEND_ACC_PUBLIC)
8692 + HTTP_MESSAGE_ME(getType, ZEND_ACC_PUBLIC)
8693 + HTTP_MESSAGE_ME(setType, ZEND_ACC_PUBLIC)
8694 + HTTP_MESSAGE_ME(getInfo, ZEND_ACC_PUBLIC)
8695 + HTTP_MESSAGE_ME(setInfo, ZEND_ACC_PUBLIC)
8696 + HTTP_MESSAGE_ME(getResponseCode, ZEND_ACC_PUBLIC)
8697 + HTTP_MESSAGE_ME(setResponseCode, ZEND_ACC_PUBLIC)
8698 + HTTP_MESSAGE_ME(getResponseStatus, ZEND_ACC_PUBLIC)
8699 + HTTP_MESSAGE_ME(setResponseStatus, ZEND_ACC_PUBLIC)
8700 + HTTP_MESSAGE_ME(getRequestMethod, ZEND_ACC_PUBLIC)
8701 + HTTP_MESSAGE_ME(setRequestMethod, ZEND_ACC_PUBLIC)
8702 + HTTP_MESSAGE_ME(getRequestUrl, ZEND_ACC_PUBLIC)
8703 + HTTP_MESSAGE_ME(setRequestUrl, ZEND_ACC_PUBLIC)
8704 + HTTP_MESSAGE_ME(getHttpVersion, ZEND_ACC_PUBLIC)
8705 + HTTP_MESSAGE_ME(setHttpVersion, ZEND_ACC_PUBLIC)
8706 + HTTP_MESSAGE_ME(guessContentType, ZEND_ACC_PUBLIC)
8707 + HTTP_MESSAGE_ME(getParentMessage, ZEND_ACC_PUBLIC)
8708 + HTTP_MESSAGE_ME(send, ZEND_ACC_PUBLIC)
8709 + HTTP_MESSAGE_ME(toString, ZEND_ACC_PUBLIC)
8710 + HTTP_MESSAGE_ME(toMessageTypeObject, ZEND_ACC_PUBLIC)
8712 + /* implements Countable */
8713 + HTTP_MESSAGE_ME(count, ZEND_ACC_PUBLIC)
8715 + /* implements Serializable */
8716 + HTTP_MESSAGE_ME(serialize, ZEND_ACC_PUBLIC)
8717 + HTTP_MESSAGE_ME(unserialize, ZEND_ACC_PUBLIC)
8719 + /* implements Iterator */
8720 + HTTP_MESSAGE_ME(rewind, ZEND_ACC_PUBLIC)
8721 + HTTP_MESSAGE_ME(valid, ZEND_ACC_PUBLIC)
8722 + HTTP_MESSAGE_ME(current, ZEND_ACC_PUBLIC)
8723 + HTTP_MESSAGE_ME(key, ZEND_ACC_PUBLIC)
8724 + HTTP_MESSAGE_ME(next, ZEND_ACC_PUBLIC)
8726 + ZEND_MALIAS(HttpMessage, __toString, toString, HTTP_ARGS(HttpMessage, __toString), ZEND_ACC_PUBLIC)
8728 + HTTP_MESSAGE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
8729 + ZEND_MALIAS(HttpMessage, fromString, factory, HTTP_ARGS(HttpMessage, factory), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
8730 + HTTP_MESSAGE_ME(fromEnv, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
8732 + HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC)
8733 + HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC)
8734 + HTTP_MESSAGE_ME(reverse, ZEND_ACC_PUBLIC)
8736 + EMPTY_FUNCTION_ENTRY
8738 +static zend_object_handlers http_message_object_handlers;
8740 +static HashTable http_message_object_prophandlers;
8742 +typedef void (*http_message_object_prophandler_func)(http_message_object *o, zval *v TSRMLS_DC);
8744 +typedef struct _http_message_object_prophandler {
8745 + http_message_object_prophandler_func read;
8746 + http_message_object_prophandler_func write;
8747 +} http_message_object_prophandler;
8749 +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) {
8750 + http_message_object_prophandler h = { read, write };
8751 + return zend_hash_add(&http_message_object_prophandlers, prop_str, prop_len, (void *) &h, sizeof(h), NULL);
8753 +static STATUS http_message_object_get_prophandler(const char *prop_str, size_t prop_len, http_message_object_prophandler **handler) {
8754 + return zend_hash_find(&http_message_object_prophandlers, prop_str, prop_len, (void *) handler);
8756 +static void http_message_object_prophandler_get_type(http_message_object *obj, zval *return_value TSRMLS_DC) {
8757 + RETVAL_LONG(obj->message->type);
8759 +static void http_message_object_prophandler_set_type(http_message_object *obj, zval *value TSRMLS_DC) {
8760 + zval *cpy = http_zsep(IS_LONG, value);
8761 + http_message_set_type(obj->message, Z_LVAL_P(cpy));
8762 + zval_ptr_dtor(&cpy);
8764 +static void http_message_object_prophandler_get_body(http_message_object *obj, zval *return_value TSRMLS_DC) {
8765 + phpstr_fix(PHPSTR(obj->message));
8766 + RETVAL_PHPSTR(PHPSTR(obj->message), 0, 1);
8768 +static void http_message_object_prophandler_set_body(http_message_object *obj, zval *value TSRMLS_DC) {
8769 + zval *cpy = http_zsep(IS_STRING, value);
8770 + phpstr_dtor(PHPSTR(obj->message));
8771 + phpstr_from_string_ex(PHPSTR(obj->message), Z_STRVAL_P(cpy), Z_STRLEN_P(cpy));
8772 + zval_ptr_dtor(&cpy);
8774 +static void http_message_object_prophandler_get_request_method(http_message_object *obj, zval *return_value TSRMLS_DC) {
8775 + if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.method) {
8776 + RETVAL_STRING(obj->message->http.info.request.method, 1);
8781 +static void http_message_object_prophandler_set_request_method(http_message_object *obj, zval *value TSRMLS_DC) {
8782 + if (HTTP_MSG_TYPE(REQUEST, obj->message)) {
8783 + zval *cpy = http_zsep(IS_STRING, value);
8784 + STR_SET(obj->message->http.info.request.method, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
8785 + zval_ptr_dtor(&cpy);
8788 +static void http_message_object_prophandler_get_request_url(http_message_object *obj, zval *return_value TSRMLS_DC) {
8789 + if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.url) {
8790 + RETVAL_STRING(obj->message->http.info.request.url, 1);
8795 +static void http_message_object_prophandler_set_request_url(http_message_object *obj, zval *value TSRMLS_DC) {
8796 + if (HTTP_MSG_TYPE(REQUEST, obj->message)) {
8797 + zval *cpy = http_zsep(IS_STRING, value);
8798 + STR_SET(obj->message->http.info.request.url, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
8799 + zval_ptr_dtor(&cpy);
8802 +static void http_message_object_prophandler_get_response_status(http_message_object *obj, zval *return_value TSRMLS_DC) {
8803 + if (HTTP_MSG_TYPE(RESPONSE, obj->message) && obj->message->http.info.response.status) {
8804 + RETVAL_STRING(obj->message->http.info.response.status, 1);
8809 +static void http_message_object_prophandler_set_response_status(http_message_object *obj, zval *value TSRMLS_DC) {
8810 + if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
8811 + zval *cpy = http_zsep(IS_STRING, value);
8812 + STR_SET(obj->message->http.info.response.status, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
8813 + zval_ptr_dtor(&cpy);
8816 +static void http_message_object_prophandler_get_response_code(http_message_object *obj, zval *return_value TSRMLS_DC) {
8817 + if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
8818 + RETVAL_LONG(obj->message->http.info.response.code);
8823 +static void http_message_object_prophandler_set_response_code(http_message_object *obj, zval *value TSRMLS_DC) {
8824 + if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
8825 + zval *cpy = http_zsep(IS_LONG, value);
8826 + obj->message->http.info.response.code = Z_LVAL_P(cpy);
8827 + zval_ptr_dtor(&cpy);
8830 +static void http_message_object_prophandler_get_http_version(http_message_object *obj, zval *return_value TSRMLS_DC) {
8831 + RETVAL_DOUBLE(obj->message->http.version);
8833 +static void http_message_object_prophandler_set_http_version(http_message_object *obj, zval *value TSRMLS_DC) {
8834 + zval *cpy = http_zsep(IS_DOUBLE, value);
8835 + obj->message->http.version = Z_DVAL_P(cpy);
8836 + zval_ptr_dtor(&cpy);
8838 +static void http_message_object_prophandler_get_headers(http_message_object *obj, zval *return_value TSRMLS_DC) {
8839 + array_init(return_value);
8840 + zend_hash_copy(Z_ARRVAL_P(return_value), &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8842 +static void http_message_object_prophandler_set_headers(http_message_object *obj, zval *value TSRMLS_DC) {
8843 + zval *cpy = http_zsep(IS_ARRAY, value);
8844 + zend_hash_clean(&obj->message->hdrs);
8845 + zend_hash_copy(&obj->message->hdrs, Z_ARRVAL_P(cpy), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8846 + zval_ptr_dtor(&cpy);
8848 +static void http_message_object_prophandler_get_parent_message(http_message_object *obj, zval *return_value TSRMLS_DC) {
8849 + if (obj->message->parent) {
8850 + RETVAL_OBJVAL(obj->parent, 1);
8855 +static void http_message_object_prophandler_set_parent_message(http_message_object *obj, zval *value TSRMLS_DC) {
8856 + if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), http_message_object_ce TSRMLS_CC)) {
8857 + if (obj->message->parent) {
8859 + tmp.value.obj = obj->parent;
8860 + Z_OBJ_DELREF(tmp);
8862 + Z_OBJ_ADDREF_P(value);
8863 + obj->parent = value->value.obj;
8867 +PHP_MINIT_FUNCTION(http_message_object)
8869 + HTTP_REGISTER_CLASS_EX(HttpMessage, http_message_object, NULL, 0);
8872 +# ifdef HTTP_HAVE_SPL
8873 + zend_class_implements(http_message_object_ce TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator);
8875 + zend_class_implements(http_message_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_iterator);
8878 + zend_class_implements(http_message_object_ce TSRMLS_CC, 1, zend_ce_iterator);
8881 + http_message_object_handlers.clone_obj = _http_message_object_clone_obj;
8882 + http_message_object_handlers.read_property = http_message_object_read_prop;
8883 + http_message_object_handlers.write_property = http_message_object_write_prop;
8884 + http_message_object_handlers.get_properties = http_message_object_get_props;
8885 + http_message_object_handlers.get_property_ptr_ptr = http_message_object_get_prop_ptr;
8887 + zend_hash_init(&http_message_object_prophandlers, 9, NULL, NULL, 1);
8888 + zend_declare_property_long(THIS_CE, ZEND_STRS("type")-1, HTTP_MSG_NONE, ZEND_ACC_PROTECTED TSRMLS_CC);
8889 + http_message_object_add_prophandler(ZEND_STRS("type")-1, http_message_object_prophandler_get_type, http_message_object_prophandler_set_type);
8890 + zend_declare_property_string(THIS_CE, ZEND_STRS("body")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8891 + http_message_object_add_prophandler(ZEND_STRS("body")-1, http_message_object_prophandler_get_body, http_message_object_prophandler_set_body);
8892 + zend_declare_property_string(THIS_CE, ZEND_STRS("requestMethod")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8893 + http_message_object_add_prophandler(ZEND_STRS("requestMethod")-1, http_message_object_prophandler_get_request_method, http_message_object_prophandler_set_request_method);
8894 + zend_declare_property_string(THIS_CE, ZEND_STRS("requestUrl")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8895 + http_message_object_add_prophandler(ZEND_STRS("requestUrl")-1, http_message_object_prophandler_get_request_url, http_message_object_prophandler_set_request_url);
8896 + zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8897 + http_message_object_add_prophandler(ZEND_STRS("responseStatus")-1, http_message_object_prophandler_get_response_status, http_message_object_prophandler_set_response_status);
8898 + zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC);
8899 + http_message_object_add_prophandler(ZEND_STRS("responseCode")-1, http_message_object_prophandler_get_response_code, http_message_object_prophandler_set_response_code);
8900 + zend_declare_property_null(THIS_CE, ZEND_STRS("httpVersion")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
8901 + http_message_object_add_prophandler(ZEND_STRS("httpVersion")-1, http_message_object_prophandler_get_http_version, http_message_object_prophandler_set_http_version);
8902 + zend_declare_property_null(THIS_CE, ZEND_STRS("headers")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
8903 + http_message_object_add_prophandler(ZEND_STRS("headers")-1, http_message_object_prophandler_get_headers, http_message_object_prophandler_set_headers);
8904 + zend_declare_property_null(THIS_CE, ZEND_STRS("parentMessage")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
8905 + http_message_object_add_prophandler(ZEND_STRS("parentMessage")-1, http_message_object_prophandler_get_parent_message, http_message_object_prophandler_set_parent_message);
8908 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_NONE")-1, HTTP_MSG_NONE TSRMLS_CC);
8909 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_REQUEST")-1, HTTP_MSG_REQUEST TSRMLS_CC);
8910 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RESPONSE")-1, HTTP_MSG_RESPONSE TSRMLS_CC);
8913 + HTTP_LONG_CONSTANT("HTTP_MSG_NONE", HTTP_MSG_NONE);
8914 + HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST);
8915 + HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE);
8920 +PHP_MSHUTDOWN_FUNCTION(http_message_object)
8922 + zend_hash_destroy(&http_message_object_prophandlers);
8927 +void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC)
8930 + getObject(http_message_object, obj);
8933 + http_message_count(i, obj->message);
8937 + zend_object_value *ovalues = NULL;
8938 + http_message_object **objects = NULL;
8941 + objects = ecalloc(i, sizeof(http_message_object *));
8942 + ovalues = ecalloc(i, sizeof(zend_object_value));
8944 + /* we are the first message */
8946 + ovalues[0] = getThis()->value.obj;
8948 + /* fetch parents */
8950 + o.type = IS_OBJECT;
8951 + for (i = 1; obj->parent.handle; ++i) {
8952 + o.value.obj = obj->parent;
8953 + ovalues[i] = o.value.obj;
8954 + objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC);
8957 + /* reorder parents */
8958 + for (last = --i; i; --i) {
8959 + objects[i]->message->parent = objects[i-1]->message;
8960 + objects[i]->parent = ovalues[i-1];
8962 + objects[0]->message->parent = NULL;
8963 + objects[0]->parent.handle = 0;
8964 + objects[0]->parent.handlers = NULL;
8966 + /* add ref (why?) */
8967 + Z_OBJ_ADDREF_P(getThis());
8968 + RETVAL_OBJVAL(ovalues[last], 1);
8973 + RETURN_ZVAL(getThis(), 1, 0);
8977 +void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC)
8980 + http_message *save_parent_msg = NULL;
8981 + zend_object_value save_parent_obj = {0, NULL};
8982 + getObject(http_message_object, obj);
8983 + getObjectEx(http_message_object, prepend_obj, prepend);
8986 + m.type = IS_OBJECT;
8989 + save_parent_obj = obj->parent;
8990 + save_parent_msg = obj->message->parent;
8992 + /* iterate to the most parent object */
8993 + while (obj->parent.handle) {
8994 + m.value.obj = obj->parent;
8995 + obj = zend_object_store_get_object(&m TSRMLS_CC);
9000 + obj->parent = prepend->value.obj;
9001 + obj->message->parent = prepend_obj->message;
9004 + zend_objects_store_add_ref(prepend TSRMLS_CC);
9005 + while (prepend_obj->parent.handle) {
9006 + m.value.obj = prepend_obj->parent;
9007 + zend_objects_store_add_ref(&m TSRMLS_CC);
9008 + prepend_obj = zend_object_store_get_object(&m TSRMLS_CC);
9012 + prepend_obj->parent = save_parent_obj;
9013 + prepend_obj->message->parent = save_parent_msg;
9017 +zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC)
9019 + return http_message_object_new_ex(ce, NULL, NULL);
9022 +zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC)
9024 + zend_object_value ov;
9025 + http_message_object *o;
9027 + o = ecalloc(1, sizeof(http_message_object));
9036 + if (msg->parent) {
9037 + o->parent = http_message_object_new_ex(ce, msg->parent, NULL);
9041 + ALLOC_HASHTABLE(OBJ_PROP(o));
9042 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
9043 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
9045 + ov.handle = putObject(http_message_object, o);
9046 + ov.handlers = &http_message_object_handlers;
9051 +zend_object_value _http_message_object_clone_obj(zval *this_ptr TSRMLS_DC)
9053 + zend_object_value new_ov;
9054 + http_message_object *new_obj = NULL;
9055 + getObject(http_message_object, old_obj);
9057 + new_ov = http_message_object_new_ex(old_obj->zo.ce, http_message_dup(old_obj->message), &new_obj);
9058 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
9063 +void _http_message_object_free(zend_object *object TSRMLS_DC)
9065 + http_message_object *o = (http_message_object *) object;
9067 + if (o->iterator) {
9068 + zval_ptr_dtor(&o->iterator);
9069 + o->iterator = NULL;
9072 + http_message_dtor(o->message);
9073 + efree(o->message);
9075 + if (o->parent.handle) {
9079 + p.type = IS_OBJECT;
9080 + p.value.obj = o->parent;
9081 + zend_objects_store_del_ref(&p TSRMLS_CC);
9086 +static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC) {
9087 + getObjectEx(http_message_object, obj, object);
9088 + http_message_object_prophandler *handler;
9090 + if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
9091 + zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index");
9095 + return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member ZEND_LITERAL_KEY_CC TSRMLS_CC);
9098 +static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC)
9100 + getObjectEx(http_message_object, obj, object);
9101 + http_message_object_prophandler *handler;
9102 + zval *return_value;
9104 + if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
9105 + if (type == BP_VAR_W) {
9106 + zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index");
9110 + ALLOC_ZVAL(return_value);
9111 +#ifdef Z_SET_REFCOUNT
9112 + Z_SET_REFCOUNT_P(return_value, 0);
9113 + Z_UNSET_ISREF_P(return_value);
9115 + return_value->refcount = 0;
9116 + return_value->is_ref = 0;
9119 + handler->read(obj, return_value TSRMLS_CC);
9122 + return_value = zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC);
9125 + return return_value;
9128 +static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC)
9130 + getObjectEx(http_message_object, obj, object);
9131 + http_message_object_prophandler *handler;
9133 + if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
9134 + handler->write(obj, value TSRMLS_CC);
9136 + zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC);
9140 +static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC)
9143 + getObjectEx(http_message_object, obj, object);
9144 + http_message *msg = obj->message;
9145 + HashTable *props = OBJ_PROP(obj);
9146 + zval array, *parent;
9148 + INIT_ZARR(array, props);
9150 +#define ASSOC_PROP(array, ptype, name, val) \
9152 + char *m_prop_name; \
9154 + zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
9155 + add_assoc_ ##ptype## _ex(&array, m_prop_name, sizeof(name)+3, val); \
9156 + efree(m_prop_name); \
9158 +#define ASSOC_STRING(array, name, val) ASSOC_STRINGL(array, name, val, strlen(val))
9159 +#define ASSOC_STRINGL(array, name, val, len) \
9161 + char *m_prop_name; \
9163 + zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
9164 + add_assoc_stringl_ex(&array, m_prop_name, sizeof(name)+3, val, len, 1); \
9165 + efree(m_prop_name); \
9168 + ASSOC_PROP(array, long, "type", msg->type);
9169 + ASSOC_PROP(array, double, "httpVersion", msg->http.version);
9171 + switch (msg->type) {
9172 + case HTTP_MSG_REQUEST:
9173 + ASSOC_PROP(array, long, "responseCode", 0);
9174 + ASSOC_STRINGL(array, "responseStatus", "", 0);
9175 + ASSOC_STRING(array, "requestMethod", STR_PTR(msg->http.info.request.method));
9176 + ASSOC_STRING(array, "requestUrl", STR_PTR(msg->http.info.request.url));
9179 + case HTTP_MSG_RESPONSE:
9180 + ASSOC_PROP(array, long, "responseCode", msg->http.info.response.code);
9181 + ASSOC_STRING(array, "responseStatus", STR_PTR(msg->http.info.response.status));
9182 + ASSOC_STRINGL(array, "requestMethod", "", 0);
9183 + ASSOC_STRINGL(array, "requestUrl", "", 0);
9186 + case HTTP_MSG_NONE:
9188 + ASSOC_PROP(array, long, "responseCode", 0);
9189 + ASSOC_STRINGL(array, "responseStatus", "", 0);
9190 + ASSOC_STRINGL(array, "requestMethod", "", 0);
9191 + ASSOC_STRINGL(array, "requestUrl", "", 0);
9195 + MAKE_STD_ZVAL(headers);
9196 + array_init(headers);
9197 + zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
9198 + ASSOC_PROP(array, zval, "headers", headers);
9199 + ASSOC_STRINGL(array, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg));
9201 + MAKE_STD_ZVAL(parent);
9202 + if (msg->parent) {
9203 + ZVAL_OBJVAL(parent, obj->parent, 1);
9205 + ZVAL_NULL(parent);
9207 + ASSOC_PROP(array, zval, "parentMessage", parent);
9209 + return OBJ_PROP(obj);
9212 +/* ### USERLAND ### */
9214 +/* {{{ proto void HttpMessage::__construct([string message])
9215 + Create a new HttpMessage object instance. */
9216 +PHP_METHOD(HttpMessage, __construct)
9219 + char *message = NULL;
9221 + getObject(http_message_object, obj);
9223 + SET_EH_THROW_HTTP();
9224 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) {
9225 + http_message *msg = obj->message;
9227 + http_message_dtor(msg);
9228 + if ((obj->message = http_message_parse_ex(msg, message, length))) {
9229 + if (obj->message->parent) {
9230 + obj->parent = http_message_object_new_ex(Z_OBJCE_P(getThis()), obj->message->parent, NULL);
9233 + obj->message = http_message_init(msg);
9236 + if (!obj->message) {
9237 + obj->message = http_message_new();
9243 +/* {{{ proto static HttpMessage HttpMessage::factory([string raw_message[, string class_name = "HttpMessage"]])
9244 + Create a new HttpMessage object instance. */
9245 +PHP_METHOD(HttpMessage, factory)
9247 + char *string = NULL, *cn = NULL;
9248 + int length = 0, cl = 0;
9249 + http_message *msg = NULL;
9250 + zend_object_value ov;
9251 + http_message_object *obj = NULL;
9255 + SET_EH_THROW_HTTP();
9256 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &string, &length, &cn, &cl)) {
9258 + msg = http_message_parse(string, length);
9260 + if ((msg || !length) && SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, msg, &obj)) {
9261 + RETVAL_OBJVAL(ov, 0);
9263 + if (obj && !obj->message) {
9264 + obj->message = http_message_new();
9271 +/* {{{ proto static HttpMessage HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"])
9272 + Create a new HttpMessage object from environment representing either current request or response */
9273 +PHP_METHOD(HttpMessage, fromEnv)
9278 + http_message_object *obj = NULL;
9279 + zend_object_value ov;
9282 + SET_EH_THROW_HTTP();
9283 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &type, &cn, &cl)) {
9284 + if (SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, http_message_init_env(NULL, type), &obj)) {
9285 + RETVAL_OBJVAL(ov, 0);
9287 + if (obj && !obj->message) {
9288 + obj->message = http_message_new();
9295 +/* {{{ proto string HttpMessage::getBody()
9296 + Get the body of the parsed HttpMessage. */
9297 +PHP_METHOD(HttpMessage, getBody)
9301 + if (return_value_used) {
9302 + getObject(http_message_object, obj);
9303 + RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
9308 +/* {{{ proto void HttpMessage::setBody(string body)
9309 + Set the body of the HttpMessage. NOTE: Don't forget to update any headers accordingly. */
9310 +PHP_METHOD(HttpMessage, setBody)
9314 + getObject(http_message_object, obj);
9316 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &body, &len)) {
9317 + phpstr_dtor(PHPSTR(obj->message));
9318 + phpstr_from_string_ex(PHPSTR(obj->message), body, len);
9323 +/* {{{ proto string HttpMessage::getHeader(string header)
9324 + Get message header. */
9325 +PHP_METHOD(HttpMessage, getHeader)
9328 + char *orig_header, *nice_header;
9330 + getObject(http_message_object, obj);
9332 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &orig_header, &header_len)) {
9336 + nice_header = pretty_key(estrndup(orig_header, header_len), header_len, 1, 1);
9337 + if ((header = http_message_header_ex(obj->message, nice_header, header_len + 1, 0))) {
9338 + RETVAL_ZVAL(header, 1, 1);
9340 + efree(nice_header);
9344 +/* {{{ proto array HttpMessage::getHeaders()
9345 + Get Message Headers. */
9346 +PHP_METHOD(HttpMessage, getHeaders)
9350 + if (return_value_used) {
9351 + getObject(http_message_object, obj);
9353 + array_init(return_value);
9354 + array_copy(&obj->message->hdrs, Z_ARRVAL_P(return_value));
9359 +/* {{{ proto void HttpMessage::setHeaders(array headers)
9360 + Sets new headers. */
9361 +PHP_METHOD(HttpMessage, setHeaders)
9363 + zval *new_headers = NULL;
9364 + getObject(http_message_object, obj);
9366 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &new_headers)) {
9370 + zend_hash_clean(&obj->message->hdrs);
9371 + if (new_headers) {
9372 + array_copy(Z_ARRVAL_P(new_headers), &obj->message->hdrs);
9377 +/* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
9378 + Add headers. If append is true, headers with the same name will be separated, else overwritten. */
9379 +PHP_METHOD(HttpMessage, addHeaders)
9381 + zval *new_headers;
9382 + zend_bool append = 0;
9383 + getObject(http_message_object, obj);
9385 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
9389 + array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY);
9393 +/* {{{ proto int HttpMessage::getType()
9394 + Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
9395 +PHP_METHOD(HttpMessage, getType)
9399 + if (return_value_used) {
9400 + getObject(http_message_object, obj);
9401 + RETURN_LONG(obj->message->type);
9406 +/* {{{ proto void HttpMessage::setType(int type)
9407 + Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
9408 +PHP_METHOD(HttpMessage, setType)
9411 + getObject(http_message_object, obj);
9413 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
9416 + http_message_set_type(obj->message, type);
9420 +/* {{{ proto string HttpMessage::getInfo(void)
9421 + Get the HTTP request/response line */
9422 +PHP_METHOD(HttpMessage, getInfo)
9426 + if (return_value_used) {
9427 + getObject(http_message_object, obj);
9429 + switch (obj->message->type) {
9430 + case HTTP_MSG_REQUEST:
9431 + Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_REQUEST_FMT_ARGS(&obj->message->http, ""));
9433 + case HTTP_MSG_RESPONSE:
9434 + Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_RESPONSE_FMT_ARGS(&obj->message->http, ""));
9440 + Z_TYPE_P(return_value) = IS_STRING;
9445 +/* {{{ proto bool HttpMessage::setInfo(string http_info)
9446 + Set type and request or response info with a standard HTTP request or response line */
9447 +PHP_METHOD(HttpMessage, setInfo)
9453 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) && SUCCESS == http_info_parse_ex(str, &inf, 0)) {
9454 + getObject(http_message_object, obj);
9456 + http_message_set_info(obj->message, &inf);
9457 + http_info_dtor(&inf);
9464 +/* {{{ proto int HttpMessage::getResponseCode()
9465 + Get the Response Code of the Message. */
9466 +PHP_METHOD(HttpMessage, getResponseCode)
9470 + if (return_value_used) {
9471 + getObject(http_message_object, obj);
9472 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9473 + RETURN_LONG(obj->message->http.info.response.code);
9478 +/* {{{ proto bool HttpMessage::setResponseCode(int code)
9479 + Set the response code of an HTTP Response Message. */
9480 +PHP_METHOD(HttpMessage, setResponseCode)
9483 + getObject(http_message_object, obj);
9485 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9487 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
9490 + if (code < 100 || code > 599) {
9491 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid response code (100-599): %ld", code);
9495 + obj->message->http.info.response.code = code;
9500 +/* {{{ proto string HttpMessage::getResponseStatus()
9501 + Get the Response Status of the message (i.e. the string following the response code). */
9502 +PHP_METHOD(HttpMessage, getResponseStatus)
9506 + if (return_value_used) {
9507 + getObject(http_message_object, obj);
9508 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9509 + if (obj->message->http.info.response.status) {
9510 + RETURN_STRING(obj->message->http.info.response.status, 1);
9512 + RETURN_EMPTY_STRING();
9518 +/* {{{ proto bool HttpMessage::setResponseStatus(string status)
9519 + Set the Response Status of the HTTP message (i.e. the string following the response code). */
9520 +PHP_METHOD(HttpMessage, setResponseStatus)
9524 + getObject(http_message_object, obj);
9526 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9528 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &status, &status_len)) {
9531 + STR_SET(obj->message->http.info.response.status, estrndup(status, status_len));
9536 +/* {{{ proto string HttpMessage::getRequestMethod()
9537 + Get the Request Method of the Message. */
9538 +PHP_METHOD(HttpMessage, getRequestMethod)
9542 + if (return_value_used) {
9543 + getObject(http_message_object, obj);
9544 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9545 + if (obj->message->http.info.request.method) {
9546 + RETURN_STRING(obj->message->http.info.request.method, 1);
9548 + RETURN_EMPTY_STRING();
9554 +/* {{{ proto bool HttpMessage::setRequestMethod(string method)
9555 + Set the Request Method of the HTTP Message. */
9556 +PHP_METHOD(HttpMessage, setRequestMethod)
9560 + getObject(http_message_object, obj);
9562 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9564 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
9567 + if (method_len < 1) {
9568 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
9571 + if (!http_request_method_exists(1, 0, method)) {
9572 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unknown request method: %s", method);
9576 + STR_SET(obj->message->http.info.request.method, estrndup(method, method_len));
9581 +/* {{{ proto string HttpMessage::getRequestUrl()
9582 + Get the Request URL of the Message. */
9583 +PHP_METHOD(HttpMessage, getRequestUrl)
9587 + if (return_value_used) {
9588 + getObject(http_message_object, obj);
9589 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9590 + if (obj->message->http.info.request.url) {
9591 + RETURN_STRING(obj->message->http.info.request.url, 1);
9593 + RETURN_EMPTY_STRING();
9599 +/* {{{ proto bool HttpMessage::setRequestUrl(string url)
9600 + Set the Request URL of the HTTP Message. */
9601 +PHP_METHOD(HttpMessage, setRequestUrl)
9605 + getObject(http_message_object, obj);
9607 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) {
9610 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9612 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestUrl to an empty string");
9616 + STR_SET(obj->message->http.info.request.url, estrndup(URI, URIlen));
9621 +/* {{{ proto string HttpMessage::getHttpVersion()
9622 + Get the HTTP Protocol Version of the Message. */
9623 +PHP_METHOD(HttpMessage, getHttpVersion)
9627 + if (return_value_used) {
9629 + getObject(http_message_object, obj);
9631 + spprintf(&version, 0, "%1.1F", obj->message->http.version);
9632 + RETURN_STRING(version, 0);
9637 +/* {{{ proto bool HttpMessage::setHttpVersion(string version)
9638 + Set the HTTP Protocol version of the Message. */
9639 +PHP_METHOD(HttpMessage, setHttpVersion)
9643 + getObject(http_message_object, obj);
9645 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) {
9649 + convert_to_double(zv);
9650 + spprintf(&version, 0, "%1.1F", Z_DVAL_P(zv));
9651 + if (strcmp(version, "1.0") && strcmp(version, "1.1")) {
9653 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %g", Z_DVAL_P(zv));
9657 + obj->message->http.version = Z_DVAL_P(zv);
9662 +/* {{{ proto string HttpMessage::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
9663 + Attempts to guess the content type of supplied payload through libmagic. */
9664 +PHP_METHOD(HttpMessage, guessContentType)
9666 +#ifdef HTTP_HAVE_MAGIC
9667 + char *magic_file, *ct = NULL;
9668 + int magic_file_len;
9669 + long magic_mode = MAGIC_MIME;
9672 + SET_EH_THROW_HTTP();
9673 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
9674 + getObject(http_message_object, obj);
9675 + if ((ct = http_guess_content_type(magic_file, magic_mode, PHPSTR_VAL(&obj->message->body), PHPSTR_LEN(&obj->message->body), SEND_DATA))) {
9676 + RETVAL_STRING(ct, 0);
9681 + http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
9687 +/* {{{ proto HttpMessage HttpMessage::getParentMessage()
9688 + Get parent Message. */
9689 +PHP_METHOD(HttpMessage, getParentMessage)
9691 + SET_EH_THROW_HTTP();
9693 + getObject(http_message_object, obj);
9695 + if (obj->message->parent) {
9696 + RETVAL_OBJVAL(obj->parent, 1);
9698 + http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpMessage does not have a parent message");
9705 +/* {{{ proto bool HttpMessage::send()
9706 + Send the Message according to its type as Response or Request. */
9707 +PHP_METHOD(HttpMessage, send)
9709 + getObject(http_message_object, obj);
9713 + RETURN_SUCCESS(http_message_send(obj->message));
9717 +/* {{{ proto string HttpMessage::toString([bool include_parent = false])
9718 + Get the string representation of the Message. */
9719 +PHP_METHOD(HttpMessage, toString)
9721 + if (return_value_used) {
9724 + zend_bool include_parent = 0;
9725 + getObject(http_message_object, obj);
9727 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
9731 + if (include_parent) {
9732 + http_message_serialize(obj->message, &string, &length);
9734 + http_message_tostring(obj->message, &string, &length);
9736 + RETURN_STRINGL(string, length, 0);
9741 +/* {{{ proto HttpRequest|HttpResponse HttpMessage::toMessageTypeObject(void)
9742 + Creates an object regarding to the type of the message. Returns either an HttpRequest or HttpResponse object on success, or NULL on failure. */
9743 +PHP_METHOD(HttpMessage, toMessageTypeObject)
9745 + SET_EH_THROW_HTTP();
9749 + if (return_value_used) {
9750 + getObject(http_message_object, obj);
9752 + switch (obj->message->type) {
9753 + case HTTP_MSG_REQUEST:
9755 +#ifdef HTTP_HAVE_CURL
9758 + zval post, body, *array, *headers, *host = http_message_header(obj->message, "Host");
9759 + php_url hurl, *purl = php_url_parse(STR_PTR(obj->message->http.info.request.url));
9761 + MAKE_STD_ZVAL(array);
9762 + array_init(array);
9764 + memset(&hurl, 0, sizeof(php_url));
9766 + hurl.host = Z_STRVAL_P(host);
9767 + zval_ptr_dtor(&host);
9769 + http_build_url(HTTP_URL_REPLACE, purl, &hurl, NULL, &url, NULL);
9770 + php_url_free(purl);
9771 + add_assoc_string(array, "url", url, 0);
9773 + if ( obj->message->http.info.request.method &&
9774 + ((method = http_request_method_exists(1, 0, obj->message->http.info.request.method)) ||
9775 + (method = http_request_method_register(obj->message->http.info.request.method, strlen(obj->message->http.info.request.method))))) {
9776 + add_assoc_long(array, "method", method);
9779 + if (10 == (int) (obj->message->http.version * 10)) {
9780 + add_assoc_long(array, "protocol", CURL_HTTP_VERSION_1_0);
9783 + MAKE_STD_ZVAL(headers);
9784 + array_init(headers);
9785 + array_copy(&obj->message->hdrs, Z_ARRVAL_P(headers));
9786 + add_assoc_zval(array, "headers", headers);
9788 + object_init_ex(return_value, http_request_object_ce);
9789 + zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setoptions", NULL, array);
9790 + zval_ptr_dtor(&array);
9792 + if (PHPSTR_VAL(obj->message) && PHPSTR_LEN(obj->message)) {
9793 + phpstr_fix(PHPSTR(obj->message));
9794 + INIT_PZVAL(&body);
9795 + ZVAL_STRINGL(&body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 0);
9796 + if (method != HTTP_POST) {
9797 + zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setbody", NULL, &body);
9799 + INIT_PZVAL(&post);
9800 + array_init(&post);
9802 + zval_copy_ctor(&body);
9803 + sapi_module.treat_data(PARSE_STRING, Z_STRVAL(body), &post TSRMLS_CC);
9804 + zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setpostfields", NULL, &post);
9809 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpRequest (missing curl support)");
9814 + case HTTP_MSG_RESPONSE:
9817 + HashPosition pos1, pos2;
9818 + HashKey key = initHashKey(0);
9819 + zval **header, **h, *body;
9821 + if (obj->message->http.info.response.code) {
9822 + http_send_status(obj->message->http.info.response.code);
9825 + object_init_ex(return_value, http_response_object_ce);
9827 + FOREACH_HASH_KEYVAL(pos1, &obj->message->hdrs, key, header) {
9828 + if (key.type == HASH_KEY_IS_STRING) {
9831 + MAKE_STD_ZVAL(zkey);
9832 + ZVAL_STRINGL(zkey, key.str, key.len - 1, 1);
9834 + switch (Z_TYPE_PP(header)) {
9837 + FOREACH_HASH_VAL(pos2, HASH_OF(*header), h) {
9839 + zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *h);
9845 + ZVAL_ADDREF(*header);
9846 + zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *header);
9847 + zval_ptr_dtor(header);
9850 + zval_ptr_dtor(&zkey);
9854 + MAKE_STD_ZVAL(body);
9855 + ZVAL_STRINGL(body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 1);
9856 + zend_call_method_with_1_params(&return_value, http_response_object_ce, NULL, "setdata", NULL, body);
9857 + zval_ptr_dtor(&body);
9859 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpResponse (need PHP 5.1+)");
9865 + http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HttpMessage::TYPE_REQUEST nor HttpMessage::TYPE_RESPONSE");
9873 +/* {{{ proto int HttpMessage::count()
9874 + Implements Countable::count(). Returns the number of parent messages + 1. */
9875 +PHP_METHOD(HttpMessage, count)
9879 + getObject(http_message_object, obj);
9881 + http_message_count(i, obj->message);
9887 +/* {{{ proto string HttpMessage::serialize()
9888 + Implements Serializable::serialize(). Returns the serialized representation of the HttpMessage. */
9889 +PHP_METHOD(HttpMessage, serialize)
9894 + getObject(http_message_object, obj);
9896 + http_message_serialize(obj->message, &string, &length);
9897 + RETURN_STRINGL(string, length, 0);
9902 +/* {{{ proto void HttpMessage::unserialize(string serialized)
9903 + Implements Serializable::unserialize(). Re-constructs the HttpMessage based upon the serialized string. */
9904 +PHP_METHOD(HttpMessage, unserialize)
9908 + getObject(http_message_object, obj);
9910 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &length)) {
9911 + http_message *msg;
9913 + http_message_dtor(obj->message);
9914 + if ((msg = http_message_parse_ex(obj->message, serialized, (size_t) length))) {
9915 + obj->message = msg;
9917 + http_message_init(obj->message);
9918 + http_error(HE_ERROR, HTTP_E_RUNTIME, "Could not unserialize HttpMessage");
9924 +/* {{{ proto HttpMessage HttpMessage::detach(void)
9925 + Returns a clone of an HttpMessage object detached from any parent messages. */
9926 +PHP_METHOD(HttpMessage, detach)
9929 + http_message *msg;
9930 + getObject(http_message_object, obj);
9934 + info.type = obj->message->type;
9935 + memcpy(&HTTP_INFO(&info), &HTTP_INFO(obj->message), sizeof(struct http_info));
9937 + msg = http_message_new();
9938 + http_message_set_info(msg, &info);
9940 + zend_hash_copy(&msg->hdrs, &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
9941 + phpstr_append(&msg->body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message));
9943 + RETVAL_OBJVAL(http_message_object_new_ex(Z_OBJCE_P(getThis()), msg, NULL), 0);
9947 +/* {{{ proto void HttpMessage::prepend(HttpMessage message[, bool top = true])
9948 + Prepends message(s) to the HTTP message. Throws HttpInvalidParamException if the message is located within the same message chain. */
9949 +PHP_METHOD(HttpMessage, prepend)
9952 + zend_bool top = 1;
9954 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, http_message_object_ce, &top)) {
9955 + http_message *msg[2];
9956 + getObject(http_message_object, obj);
9957 + getObjectEx(http_message_object, prepend_obj, prepend);
9959 + /* safety check */
9960 + for (msg[0] = obj->message; msg[0]; msg[0] = msg[0]->parent) {
9961 + for (msg[1] = prepend_obj->message; msg[1]; msg[1] = msg[1]->parent) {
9962 + if (msg[0] == msg[1]) {
9963 + http_error(HE_THROW, HTTP_E_INVALID_PARAM, "Cannot prepend a message located within the same message chain");
9969 + http_message_object_prepend_ex(getThis(), prepend, top);
9974 +/* {{{ proto HttpMessage HttpMessage::reverse()
9975 + Reorders the message chain in reverse order. Returns the most parent HttpMessage object. */
9976 +PHP_METHOD(HttpMessage, reverse)
9979 + http_message_object_reverse(getThis(), return_value);
9984 +/* {{{ proto void HttpMessage::rewind(void)
9985 + Implements Iterator::rewind(). */
9986 +PHP_METHOD(HttpMessage, rewind)
9989 + getObject(http_message_object, obj);
9991 + if (obj->iterator) {
9992 + zval_ptr_dtor(&obj->iterator);
9994 + ZVAL_ADDREF(getThis());
9995 + obj->iterator = getThis();
10000 +/* {{{ proto bool HttpMessage::valid(void)
10001 + Implements Iterator::valid(). */
10002 +PHP_METHOD(HttpMessage, valid)
10005 + getObject(http_message_object, obj);
10007 + RETURN_BOOL(obj->iterator != NULL);
10012 +/* {{{ proto void HttpMessage::next(void)
10013 + Implements Iterator::next(). */
10014 +PHP_METHOD(HttpMessage, next)
10017 + getObject(http_message_object, obj);
10018 + if (obj->iterator) {
10019 + getObjectEx(http_message_object, itr, obj->iterator);
10021 + if (itr && itr->parent.handle) {
10022 + zval *old = obj->iterator;
10023 + MAKE_STD_ZVAL(obj->iterator);
10024 + ZVAL_OBJVAL(obj->iterator, itr->parent, 1);
10025 + zval_ptr_dtor(&old);
10027 + zval_ptr_dtor(&obj->iterator);
10028 + obj->iterator = NULL;
10035 +/* {{{ proto int HttpMessage::key(void)
10036 + Implements Iterator::key(). */
10037 +PHP_METHOD(HttpMessage, key)
10040 + getObject(http_message_object, obj);
10042 + RETURN_LONG(obj->iterator ? obj->iterator->value.obj.handle:0);
10047 +/* {{{ proto HttpMessage HttpMessage::current(void)
10048 + Implements Iterator::current(). */
10049 +PHP_METHOD(HttpMessage, current)
10052 + getObject(http_message_object, obj);
10054 + if (obj->iterator) {
10055 + RETURN_ZVAL(obj->iterator, 1, 0);
10061 +#endif /* ZEND_ENGINE_2 */
10064 + * Local variables:
10066 + * c-basic-offset: 4
10068 + * vim600: noet sw=4 ts=4 fdm=marker
10069 + * vim<600: noet sw=4 ts=4
10073 +++ b/ext/http/http_persistent_handle_api.c
10076 + +--------------------------------------------------------------------+
10078 + +--------------------------------------------------------------------+
10079 + | Redistribution and use in source and binary forms, with or without |
10080 + | modification, are permitted provided that the conditions mentioned |
10081 + | in the accompanying LICENSE file are met. |
10082 + +--------------------------------------------------------------------+
10083 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10084 + +--------------------------------------------------------------------+
10087 +/* $Id: http_persistent_handle_api.c 292841 2009-12-31 08:48:57Z mike $ */
10089 +#include "php_http.h"
10090 +#include "php_http_api.h"
10092 +#include "php_http_persistent_handle_api.h"
10094 +#ifndef HTTP_DEBUG_PHANDLES
10095 +# define HTTP_DEBUG_PHANDLES 0
10097 +#if HTTP_DEBUG_PHANDLES
10102 +static HashTable http_persistent_handles_hash;
10104 +# define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
10105 +# define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
10106 +static MUTEX_T http_persistent_handles_lock;
10112 +typedef struct _http_persistent_handle_list_t {
10115 +} http_persistent_handle_list;
10117 +typedef struct _http_persistent_handle_provider_t {
10118 + http_persistent_handle_list list; /* "ident" => array(handles) entries */
10119 + http_persistent_handle_ctor ctor;
10120 + http_persistent_handle_dtor dtor;
10121 + http_persistent_handle_copy copy;
10122 +} http_persistent_handle_provider;
10124 +static inline http_persistent_handle_list *http_persistent_handle_list_init(http_persistent_handle_list *list)
10128 + if ((free_list = !list)) {
10129 + list = pemalloc(sizeof(http_persistent_handle_list), 1);
10134 + if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) {
10144 +static inline void http_persistent_handle_list_dtor(http_persistent_handle_list *list, http_persistent_handle_dtor dtor)
10146 + HashPosition pos;
10149 +#if HTTP_DEBUG_PHANDLES
10150 + fprintf(stderr, "LSTDTOR: %p\n", list);
10152 + FOREACH_HASH_VAL(pos, &list->free, handle) {
10153 +#if HTTP_DEBUG_PHANDLES
10154 + fprintf(stderr, "DESTROY: %p\n", *handle);
10159 + zend_hash_destroy(&list->free);
10162 +static inline void http_persistent_handle_list_free(http_persistent_handle_list **list, http_persistent_handle_dtor dtor)
10164 + http_persistent_handle_list_dtor(*list, dtor);
10165 +#if HTTP_DEBUG_PHANDLES
10166 + fprintf(stderr, "LSTFREE: %p\n", *list);
10168 + pefree(*list, 1);
10172 +static inline http_persistent_handle_list *http_persistent_handle_list_find(http_persistent_handle_provider *provider TSRMLS_DC)
10174 + http_persistent_handle_list **list, *new_list;
10176 + 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)) {
10177 +#if HTTP_DEBUG_PHANDLES
10178 + fprintf(stderr, "LSTFIND: %p\n", *list);
10183 + if ((new_list = http_persistent_handle_list_init(NULL))) {
10184 + 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)) {
10185 +#if HTTP_DEBUG_PHANDLES
10186 + fprintf(stderr, "LSTFIND: %p (new)\n", *list);
10190 + http_persistent_handle_list_free(&new_list, provider->dtor);
10196 +static inline STATUS http_persistent_handle_do_acquire(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)
10199 + void **handle_ptr;
10200 + http_persistent_handle_list *list;
10202 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10203 + zend_hash_internal_pointer_end(&list->free);
10204 + 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)) {
10205 + *handle = *handle_ptr;
10206 + zend_hash_index_del(&list->free, index);
10208 + *handle = provider->ctor();
10212 + ++provider->list.used;
10223 +static inline STATUS http_persistent_handle_do_release(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)
10225 + http_persistent_handle_list *list;
10227 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10228 + if (provider->list.used >= HTTP_G->persistent.handles.limit) {
10229 + provider->dtor(*handle);
10231 + if (SUCCESS != zend_hash_next_index_insert(&list->free, (void *) handle, sizeof(void *), NULL)) {
10237 + --provider->list.used;
10245 +static inline STATUS http_persistent_handle_do_accrete(http_persistent_handle_provider *provider, void *old_handle, void **new_handle TSRMLS_DC)
10247 + http_persistent_handle_list *list;
10249 + if (provider->copy && (*new_handle = provider->copy(old_handle))) {
10250 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10253 + ++provider->list.used;
10259 +static void http_persistent_handles_hash_dtor(void *p)
10261 + http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p;
10262 + http_persistent_handle_list **list, *list_tmp;
10263 + HashPosition pos;
10265 + FOREACH_HASH_VAL(pos, &provider->list.free, list) {
10266 + /* fix shutdown crash in PHP4 */
10267 + list_tmp = *list;
10268 + http_persistent_handle_list_free(&list_tmp, provider->dtor);
10271 + zend_hash_destroy(&provider->list.free);
10274 +PHP_MINIT_FUNCTION(http_persistent_handle)
10276 + zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1);
10278 + http_persistent_handles_lock = tsrm_mutex_alloc();
10283 +PHP_MSHUTDOWN_FUNCTION(http_persistent_handle)
10285 + zend_hash_destroy(&http_persistent_handles_hash);
10287 + tsrm_mutex_free(http_persistent_handles_lock);
10292 +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)
10294 + STATUS status = FAILURE;
10295 + http_persistent_handle_provider provider;
10298 + if (http_persistent_handle_list_init(&provider.list)) {
10299 + provider.ctor = ctor;
10300 + provider.dtor = dtor;
10301 + provider.copy = copy;
10303 +#if HTTP_DEBUG_PHANDLES
10304 + fprintf(stderr, "PROVIDE: %s\n", name_str);
10307 + 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)) {
10308 + status = SUCCESS;
10316 +PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC)
10318 + STATUS status = FAILURE;
10319 + http_persistent_handle_provider *provider;
10323 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10324 + status = http_persistent_handle_do_acquire(provider, handle TSRMLS_CC);
10328 +#if HTTP_DEBUG_PHANDLES
10329 + fprintf(stderr, "ACQUIRE: %p (%s)\n", *handle, name_str);
10335 +PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC)
10337 + STATUS status = FAILURE;
10338 + http_persistent_handle_provider *provider;
10339 +#if HTTP_DEBUG_PHANDLES
10340 + void *handle_tmp = *handle;
10344 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10345 + status = http_persistent_handle_do_release(provider, handle TSRMLS_CC);
10349 +#if HTTP_DEBUG_PHANDLES
10350 + fprintf(stderr, "RELEASE: %p (%s)\n", handle_tmp, name_str);
10356 +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)
10358 + STATUS status = FAILURE;
10359 + http_persistent_handle_provider *provider;
10361 + *new_handle = NULL;
10363 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10364 + status = http_persistent_handle_do_accrete(provider, old_handle, new_handle TSRMLS_CC);
10368 +#if HTTP_DEBUG_PHANDLES
10369 + fprintf(stderr, "ACCRETE: %p > %p (%s)\n", old_handle, *new_handle, name_str);
10375 +PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC)
10377 + http_persistent_handle_provider *provider;
10378 + http_persistent_handle_list *list, **listp;
10379 + HashPosition pos1, pos2;
10382 + if (name_str && name_len) {
10383 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10384 + if (current_ident_only) {
10385 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10386 + http_persistent_handle_list_dtor(list, provider->dtor);
10387 + http_persistent_handle_list_init(list);
10390 + FOREACH_HASH_VAL(pos1, &provider->list.free, listp) {
10391 + http_persistent_handle_list_dtor(*listp, provider->dtor);
10392 + http_persistent_handle_list_init(*listp);
10397 + FOREACH_HASH_VAL(pos1, &http_persistent_handles_hash, provider) {
10398 + if (current_ident_only) {
10399 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10400 + http_persistent_handle_list_dtor(list, provider->dtor);
10401 + http_persistent_handle_list_init(list);
10404 + FOREACH_HASH_VAL(pos2, &provider->list.free, listp) {
10405 + http_persistent_handle_list_dtor(*listp, provider->dtor);
10406 + http_persistent_handle_list_init(*listp);
10414 +PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC)
10417 + HashPosition pos1, pos2;
10418 + HashKey key1 = initHashKey(0), key2 = initHashKey(0);
10419 + http_persistent_handle_provider *provider;
10420 + http_persistent_handle_list **list;
10423 + if (zend_hash_num_elements(&http_persistent_handles_hash)) {
10425 + ALLOC_HASHTABLE(ht);
10426 + zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
10429 + FOREACH_HASH_KEYVAL(pos1, &http_persistent_handles_hash, key1, provider) {
10430 + MAKE_STD_ZVAL(zentry[0]);
10431 + array_init(zentry[0]);
10433 + FOREACH_HASH_KEYVAL(pos2, &provider->list.free, key2, list) {
10434 + MAKE_STD_ZVAL(zentry[1]);
10435 + array_init(zentry[1]);
10436 + add_assoc_long_ex(zentry[1], ZEND_STRS("used"), (*list)->used);
10437 + add_assoc_long_ex(zentry[1], ZEND_STRS("free"), zend_hash_num_elements(&(*list)->free));
10439 + /* use zend_hash_* not add_assoc_* (which is zend_symtable_*) as we want a string even for numbers */
10440 + zend_hash_add(Z_ARRVAL_P(zentry[0]), key2.str, key2.len, &zentry[1], sizeof(zval *), NULL);
10443 + zend_hash_add(ht, key1.str, key1.len, &zentry[0], sizeof(zval *), NULL);
10455 + * Local variables:
10457 + * c-basic-offset: 4
10459 + * vim600: noet sw=4 ts=4 fdm=marker
10460 + * vim<600: noet sw=4 ts=4
10464 +++ b/ext/http/http_querystring_api.c
10467 + +--------------------------------------------------------------------+
10469 + +--------------------------------------------------------------------+
10470 + | Redistribution and use in source and binary forms, with or without |
10471 + | modification, are permitted provided that the conditions mentioned |
10472 + | in the accompanying LICENSE file are met. |
10473 + +--------------------------------------------------------------------+
10474 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10475 + +--------------------------------------------------------------------+
10478 +/* $Id: http_querystring_api.c 292841 2009-12-31 08:48:57Z mike $ */
10480 +#define HTTP_WANT_SAPI
10481 +#include "php_http.h"
10483 +#include "php_variables.h"
10484 +#ifdef HTTP_HAVE_ICONV
10485 +# undef PHP_ATOM_INC
10486 +# include "ext/iconv/php_iconv.h"
10487 +# include "ext/standard/url.h"
10490 +#include "php_http_api.h"
10491 +#include "php_http_url_api.h"
10492 +#include "php_http_querystring_api.h"
10494 +#ifdef ZEND_ENGINE_2
10495 +#define THIS_CE http_querystring_object_ce
10496 +extern zend_class_entry *http_querystring_object_ce;
10500 +#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)
10501 +static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC);
10502 +#define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC)
10503 +static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC);
10506 +#ifdef HTTP_HAVE_ICONV
10507 +PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC)
10509 + HashPosition pos;
10510 + zval **entry = NULL;
10511 + char *xlate_str = NULL, *xkey;
10512 + size_t xlate_len = 0, xlen;
10513 + HashKey key = initHashKey(0);
10515 + FOREACH_KEYVAL(pos, param, key, entry) {
10516 + if (key.type == HASH_KEY_IS_STRING) {
10517 + if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.str, key.len-1, &xkey, &xlen, oe, ie)) {
10518 + http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe);
10523 + if (Z_TYPE_PP(entry) == IS_STRING) {
10524 + if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
10525 + if (key.type == HASH_KEY_IS_STRING) {
10528 + 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);
10531 + if (key.type == HASH_KEY_IS_STRING) {
10532 + add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0);
10534 + add_index_stringl(array, key.num, xlate_str, xlate_len, 0);
10536 + } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
10539 + MAKE_STD_ZVAL(subarray);
10540 + array_init(subarray);
10541 + if (key.type == HASH_KEY_IS_STRING) {
10542 + add_assoc_zval_ex(array, xkey, xlen+1, subarray);
10544 + add_index_zval(array, key.num, subarray);
10546 + if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) {
10547 + if (key.type == HASH_KEY_IS_STRING) {
10554 + if (key.type == HASH_KEY_IS_STRING) {
10560 +#endif /* HAVE_ICONV */
10562 +PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC)
10567 + if (Z_TYPE_P(qarray) != IS_ARRAY) {
10568 + convert_to_array(qarray);
10570 + if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) {
10571 + zval_dtor(qstring);
10572 + ZVAL_STRINGL(qstring, s, l, 0);
10574 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string");
10578 +PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC)
10580 + if (Z_TYPE_P(params) == IS_ARRAY) {
10581 + return http_querystring_modify_array(qarray, params);
10582 + } else if (Z_TYPE_P(params) == IS_OBJECT) {
10583 +#ifdef ZEND_ENGINE_2
10584 + if (instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) {
10585 + return http_querystring_modify_array(qarray, zend_read_property(THIS_CE, params, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC));
10588 + return http_querystring_modify_array(qarray, params);
10589 +#ifdef ZEND_ENGINE_2
10595 + zval *qstring = http_zsep(IS_STRING, params);
10597 + INIT_PZVAL(&array);
10598 + array_init(&array);
10600 + sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(qstring)), &array TSRMLS_CC);
10601 + zval_ptr_dtor(&qstring);
10603 + rv = http_querystring_modify_array(qarray, &array);
10604 + zval_dtor(&array);
10609 +static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC)
10612 + HashKey key = initHashKey(0);
10613 + HashPosition pos;
10614 + zval **params_entry = NULL;
10616 + FOREACH_HASH_KEYVAL(pos, HASH_OF(params), key, params_entry) {
10617 + /* only public properties */
10618 + 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)) {
10626 +static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC)
10628 + zval **qarray_entry;
10630 + /* ensure array type */
10631 + if (Z_TYPE_P(qarray) != IS_ARRAY) {
10632 + convert_to_array(qarray);
10636 + if (Z_TYPE_P(params_entry) == IS_NULL) {
10637 + if (key_type == HASH_KEY_IS_STRING) {
10638 + return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen));
10640 + return (SUCCESS == zend_hash_index_del(Z_ARRVAL_P(qarray), idx));
10645 + if ( ((key_type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry))) ||
10646 + ((key_type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), idx, (void *) &qarray_entry)))) {
10650 + if (Z_TYPE_P(params_entry) == IS_ARRAY || Z_TYPE_P(params_entry) == IS_OBJECT) {
10651 + return http_querystring_modify(*qarray_entry, params_entry);
10654 + if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) {
10660 + if (Z_TYPE_P(params_entry) == IS_OBJECT) {
10663 + MAKE_STD_ZVAL(new_array);
10664 + array_init(new_array);
10665 + http_querystring_modify_array(new_array, params_entry);
10666 + params_entry = new_array;
10668 + ZVAL_ADDREF(params_entry);
10670 + if (key_type == HASH_KEY_IS_STRING) {
10671 + add_assoc_zval_ex(qarray, key, keylen, params_entry);
10673 + add_index_zval(qarray, idx, params_entry);
10679 + * Local variables:
10681 + * c-basic-offset: 4
10683 + * vim600: noet sw=4 ts=4 fdm=marker
10684 + * vim<600: noet sw=4 ts=4
10687 +++ b/ext/http/http_querystring_object.c
10690 + +--------------------------------------------------------------------+
10692 + +--------------------------------------------------------------------+
10693 + | Redistribution and use in source and binary forms, with or without |
10694 + | modification, are permitted provided that the conditions mentioned |
10695 + | in the accompanying LICENSE file are met. |
10696 + +--------------------------------------------------------------------+
10697 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10698 + +--------------------------------------------------------------------+
10701 +/* $Id: http_querystring_object.c 300299 2010-06-09 06:23:16Z mike $ */
10703 +#define HTTP_WANT_SAPI
10704 +#include "php_http.h"
10706 +#ifdef ZEND_ENGINE_2
10708 +#include "php_variables.h"
10709 +#include "zend_interfaces.h"
10711 +#include "php_http_api.h"
10712 +#include "php_http_querystring_api.h"
10713 +#include "php_http_querystring_object.h"
10714 +#include "php_http_exception_object.h"
10716 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpQueryString, method, 0, req_args)
10717 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpQueryString, method, 0)
10718 +#define HTTP_QUERYSTRING_ME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, method), visibility)
10719 +#define HTTP_QUERYSTRING_GME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, __getter), visibility)
10721 +HTTP_BEGIN_ARGS(__construct, 0)
10722 + HTTP_ARG_VAL(global, 0)
10723 + HTTP_ARG_VAL(params, 0)
10727 +HTTP_BEGIN_ARGS(singleton, 0)
10728 + HTTP_ARG_VAL(global, 0)
10732 +HTTP_BEGIN_ARGS(factory, 0)
10733 + HTTP_ARG_VAL(global, 0)
10734 + HTTP_ARG_VAL(params, 0)
10735 + HTTP_ARG_VAL(class_name, 0)
10738 +HTTP_EMPTY_ARGS(toArray);
10739 +HTTP_EMPTY_ARGS(toString);
10741 +HTTP_BEGIN_ARGS(get, 0)
10742 + HTTP_ARG_VAL(name, 0)
10743 + HTTP_ARG_VAL(type, 0)
10744 + HTTP_ARG_VAL(defval, 0)
10745 + HTTP_ARG_VAL(delete, 0)
10748 +HTTP_BEGIN_ARGS(set, 1)
10749 + HTTP_ARG_VAL(params, 0)
10752 +HTTP_BEGIN_ARGS(mod, 0)
10753 + HTTP_ARG_VAL(params, 0)
10756 +HTTP_BEGIN_ARGS(__getter, 1)
10757 + HTTP_ARG_VAL(name, 0)
10758 + HTTP_ARG_VAL(defval, 0)
10759 + HTTP_ARG_VAL(delete, 0)
10762 +#ifdef HTTP_HAVE_ICONV
10763 +HTTP_BEGIN_ARGS(xlate, 2)
10764 + HTTP_ARG_VAL(from_encoding, 0)
10765 + HTTP_ARG_VAL(to_encoding, 0)
10769 +HTTP_EMPTY_ARGS(serialize);
10770 +HTTP_BEGIN_ARGS(unserialize, 1)
10771 + HTTP_ARG_VAL(serialized, 0)
10774 +HTTP_BEGIN_ARGS(offsetGet, 1)
10775 + HTTP_ARG_VAL(offset, 0)
10778 +HTTP_BEGIN_ARGS(offsetSet, 2)
10779 + HTTP_ARG_VAL(offset, 0)
10780 + HTTP_ARG_VAL(value, 0)
10783 +HTTP_BEGIN_ARGS(offsetExists, 1)
10784 + HTTP_ARG_VAL(offset, 0)
10787 +HTTP_BEGIN_ARGS(offsetUnset, 1)
10788 + HTTP_ARG_VAL(offset, 0)
10792 +#define THIS_CE http_querystring_object_ce
10793 +zend_class_entry *http_querystring_object_ce;
10794 +zend_function_entry http_querystring_object_fe[] = {
10795 + HTTP_QUERYSTRING_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
10797 + HTTP_QUERYSTRING_ME(toArray, ZEND_ACC_PUBLIC)
10798 + HTTP_QUERYSTRING_ME(toString, ZEND_ACC_PUBLIC)
10799 + ZEND_MALIAS(HttpQueryString, __toString, toString, HTTP_ARGS(HttpQueryString, toString), ZEND_ACC_PUBLIC)
10801 + HTTP_QUERYSTRING_ME(get, ZEND_ACC_PUBLIC)
10802 + HTTP_QUERYSTRING_ME(set, ZEND_ACC_PUBLIC)
10803 + HTTP_QUERYSTRING_ME(mod, ZEND_ACC_PUBLIC)
10805 + HTTP_QUERYSTRING_GME(getBool, ZEND_ACC_PUBLIC)
10806 + HTTP_QUERYSTRING_GME(getInt, ZEND_ACC_PUBLIC)
10807 + HTTP_QUERYSTRING_GME(getFloat, ZEND_ACC_PUBLIC)
10808 + HTTP_QUERYSTRING_GME(getString, ZEND_ACC_PUBLIC)
10809 + HTTP_QUERYSTRING_GME(getArray, ZEND_ACC_PUBLIC)
10810 + HTTP_QUERYSTRING_GME(getObject, ZEND_ACC_PUBLIC)
10812 + HTTP_QUERYSTRING_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
10814 + HTTP_QUERYSTRING_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
10816 +#ifdef HTTP_HAVE_ICONV
10817 + HTTP_QUERYSTRING_ME(xlate, ZEND_ACC_PUBLIC)
10820 + /* Implements Serializable */
10821 + HTTP_QUERYSTRING_ME(serialize, ZEND_ACC_PUBLIC)
10822 + HTTP_QUERYSTRING_ME(unserialize, ZEND_ACC_PUBLIC)
10824 + /* Implements ArrayAccess */
10825 + HTTP_QUERYSTRING_ME(offsetGet, ZEND_ACC_PUBLIC)
10826 + HTTP_QUERYSTRING_ME(offsetSet, ZEND_ACC_PUBLIC)
10827 + HTTP_QUERYSTRING_ME(offsetExists, ZEND_ACC_PUBLIC)
10828 + HTTP_QUERYSTRING_ME(offsetUnset, ZEND_ACC_PUBLIC)
10830 + EMPTY_FUNCTION_ENTRY
10832 +static zend_object_handlers http_querystring_object_handlers;
10834 +PHP_MINIT_FUNCTION(http_querystring_object)
10836 + HTTP_REGISTER_CLASS_EX(HttpQueryString, http_querystring_object, NULL, 0);
10839 + zend_class_implements(http_querystring_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_arrayaccess);
10842 + zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
10843 + zend_declare_property_null(THIS_CE, ZEND_STRS("queryArray")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
10844 + zend_declare_property_string(THIS_CE, ZEND_STRS("queryString")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
10847 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_BOOL")-1, HTTP_QUERYSTRING_TYPE_BOOL TSRMLS_CC);
10848 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_INT")-1, HTTP_QUERYSTRING_TYPE_INT TSRMLS_CC);
10849 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_FLOAT")-1, HTTP_QUERYSTRING_TYPE_FLOAT TSRMLS_CC);
10850 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_STRING")-1, HTTP_QUERYSTRING_TYPE_STRING TSRMLS_CC);
10851 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ARRAY")-1, HTTP_QUERYSTRING_TYPE_ARRAY TSRMLS_CC);
10852 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_OBJECT")-1, HTTP_QUERYSTRING_TYPE_OBJECT TSRMLS_CC);
10855 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_BOOL", HTTP_QUERYSTRING_TYPE_BOOL);
10856 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_INT", HTTP_QUERYSTRING_TYPE_INT);
10857 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_FLOAT", HTTP_QUERYSTRING_TYPE_FLOAT);
10858 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_STRING", HTTP_QUERYSTRING_TYPE_STRING);
10859 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_ARRAY", HTTP_QUERYSTRING_TYPE_ARRAY);
10860 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_OBJECT", HTTP_QUERYSTRING_TYPE_OBJECT);
10865 +zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC)
10867 + return http_querystring_object_new_ex(ce, NULL, NULL);
10870 +zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC)
10872 + zend_object_value ov;
10873 + http_querystring_object *o;
10875 + o = ecalloc(1, sizeof(http_querystring_object));
10882 + ALLOC_HASHTABLE(OBJ_PROP(o));
10883 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
10884 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
10886 + ov.handle = putObject(http_querystring_object, o);
10887 + ov.handlers = &http_querystring_object_handlers;
10892 +void _http_querystring_object_free(zend_object *object TSRMLS_DC)
10894 + http_querystring_object *o = (http_querystring_object *) object;
10899 +/* {{{ querystring helpers */
10900 +#define http_querystring_instantiate(t, g, p, u) _http_querystring_instantiate((t), (g), (p), (u) TSRMLS_CC)
10901 +static inline zval *_http_querystring_instantiate(zval *this_ptr, zend_bool global, zval *params, zend_bool defer_update TSRMLS_DC)
10903 + zval *qarray = NULL, *qstring = NULL, **_SERVER = NULL, **_GET = NULL, **QUERY_STRING = NULL;;
10906 + MAKE_STD_ZVAL(this_ptr);
10907 + Z_TYPE_P(this_ptr) = IS_OBJECT;
10908 + this_ptr->value.obj = http_querystring_object_new(http_querystring_object_ce);
10911 +#ifdef ZEND_ENGINE_2
10912 + zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
10914 + if ( (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &_SERVER)) &&
10915 + (Z_TYPE_PP(_SERVER) == IS_ARRAY) &&
10916 + (SUCCESS == zend_hash_find(Z_ARRVAL_PP(_SERVER), "QUERY_STRING", sizeof("QUERY_STRING"), (void *) &QUERY_STRING))) {
10918 + qstring = *QUERY_STRING;
10919 +#ifdef ZEND_ENGINE_2
10920 + zend_is_auto_global("_GET", lenof("_GET") TSRMLS_CC);
10922 + if ((SUCCESS == zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void *) &_GET)) && (Z_TYPE_PP(_GET) == IS_ARRAY)) {
10925 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to superglobal GET array");
10928 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to QUERY_STRING");
10931 + if (qarray && qstring) {
10932 + if (Z_TYPE_P(qstring) != IS_STRING) {
10933 + convert_to_string(qstring);
10936 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC);
10937 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, qstring TSRMLS_CC);
10938 +#ifdef Z_SET_ISREF
10939 + Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC));
10940 + Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
10942 + zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)->is_ref = 1;
10943 + zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)->is_ref = 1;
10947 + http_querystring_modify(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), params);
10949 + if (!defer_update) {
10950 + 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));
10954 + MAKE_STD_ZVAL(qarray);
10955 + array_init(qarray);
10957 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC);
10958 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryString")-1, "", 0 TSRMLS_CC);
10960 + if (params && http_querystring_modify(qarray, params) && !defer_update) {
10961 + http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
10964 + zval_ptr_dtor(&qarray);
10970 +#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC)
10971 +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)
10973 + zval **arrval, *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
10975 + if ((Z_TYPE_P(qarray) == IS_ARRAY) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), name, name_len + 1, (void *) &arrval))) {
10977 + zval *value = http_zsep(type, *arrval);
10978 + RETVAL_ZVAL(value, 1, 1);
10980 + RETVAL_ZVAL(*arrval, 1, 0);
10983 + if (del && (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), name, name_len + 1))) {
10984 + http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
10986 + } else if(defval) {
10987 + RETURN_ZVAL(defval, 1, 0);
10992 +/* {{{ proto final void HttpQueryString::__construct([bool global = true[, mixed add])
10993 + Creates a new HttpQueryString object instance. Operates on and modifies $_GET and $_SERVER['QUERY_STRING'] if global is TRUE. */
10994 +PHP_METHOD(HttpQueryString, __construct)
10996 + zend_bool global = 1;
10997 + zval *params = NULL;
10999 + SET_EH_THROW_HTTP();
11000 + if (!sapi_module.treat_data) {
11001 + http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered");
11002 + } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bz", &global, ¶ms)) {
11003 + http_querystring_instantiate(getThis(), global, params, 0);
11009 +/* {{{ proto HttpQueryString HttpQueryString::factory([bool global = TRUE[, mixed params[, string class_name = "HttpQueryString"])
11010 + Creates a new HttpQueryString object instance. */
11011 +PHP_METHOD(HttpQueryString, factory)
11013 + zend_bool global = 1;
11014 + zval *params = NULL;
11017 + zend_object_value ov;
11019 + SET_EH_THROW_HTTP();
11020 + if (!sapi_module.treat_data) {
11021 + http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered");
11022 + } else if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bzs", &global, ¶ms, &cn, &cl) &&
11023 + SUCCESS == http_object_new(&ov, cn, cl, _http_querystring_object_new_ex, http_querystring_object_ce, NULL, NULL)) {
11024 + RETVAL_OBJVAL(ov, 0);
11025 + http_querystring_instantiate(return_value, global, params, 0);
11031 +/* {{{ proto string HttpQueryString::toString()
11032 + Returns the string representation. */
11033 +PHP_METHOD(HttpQueryString, toString)
11036 + RETURN_PROP(queryString);
11040 +/* {{{ proto array HttpQueryString::toArray()
11041 + Returns the array representation. */
11042 +PHP_METHOD(HttpQueryString, toArray)
11045 + RETURN_PROP(queryArray);
11049 +/* {{{ proto mixed HttpQueryString::get([string key[, mixed type = 0[, mixed defval = NULL[, bool delete = false]]]])
11050 + 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. */
11051 +PHP_METHOD(HttpQueryString, get)
11053 + char *name = NULL;
11054 + int name_len = 0;
11056 + zend_bool del = 0;
11057 + zval *ztype = NULL, *defval = NULL;
11059 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szzb", &name, &name_len, &ztype, &defval, &del)) {
11060 + if (name && name_len) {
11062 + if (Z_TYPE_P(ztype) == IS_LONG) {
11063 + type = Z_LVAL_P(ztype);
11064 + } else if(Z_TYPE_P(ztype) == IS_STRING) {
11065 + switch (Z_STRVAL_P(ztype)[0]) {
11067 + case 'b': type = HTTP_QUERYSTRING_TYPE_BOOL; break;
11069 + case 'i': type = HTTP_QUERYSTRING_TYPE_INT; break;
11071 + case 'f': type = HTTP_QUERYSTRING_TYPE_FLOAT; break;
11073 + case 's': type = HTTP_QUERYSTRING_TYPE_STRING; break;
11075 + case 'a': type = HTTP_QUERYSTRING_TYPE_ARRAY; break;
11077 + case 'o': type = HTTP_QUERYSTRING_TYPE_OBJECT; break;
11081 + http_querystring_get(getThis(), type, name, name_len, defval, del, return_value);
11083 + RETURN_PROP(queryString);
11089 +/* {{{ proto string HttpQueryString::set(mixed params)
11090 + Set query string entry/entries. NULL values will unset the variable. */
11091 +PHP_METHOD(HttpQueryString, set)
11095 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) {
11096 + zval *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11097 + if (http_querystring_modify(qarray, params)) {
11098 + http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
11102 + if (return_value_used) {
11103 + RETURN_PROP(queryString);
11108 +/* {{{ proto HttpQueryString HttpQueryString::mod(mixed params)
11109 + Copies the query string object and sets provided params at the clone. */
11110 +PHP_METHOD(HttpQueryString, mod)
11112 + zval *zobj, *qarr, *qstr, *params;
11114 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) {
11115 + zobj = http_querystring_instantiate(NULL, 0, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), 1);
11116 + qarr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11117 + qstr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryString")-1, 0 TSRMLS_CC);
11119 + http_querystring_modify(qarr, params);
11120 + http_querystring_update(qarr, qstr);
11122 + RETURN_ZVAL(zobj, 1, 1);
11128 +/* {{{ proto static HttpQueryString HttpQueryString::singleton([bool global = true])
11129 + Get a single instance (differentiates between the global setting). */
11130 +PHP_METHOD(HttpQueryString, singleton)
11132 + zend_bool global = 1;
11133 + zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
11135 + SET_EH_THROW_HTTP();
11136 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) {
11137 + zval **zobj_ptr = NULL, *zobj = NULL;
11139 + if (Z_TYPE_P(instance) == IS_ARRAY) {
11140 + if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) {
11141 + RETVAL_ZVAL(*zobj_ptr, 1, 0);
11143 + zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global);
11144 + add_index_zval(instance, global, zobj);
11145 + RETVAL_OBJECT(zobj, 1);
11148 + MAKE_STD_ZVAL(instance);
11149 + array_init(instance);
11151 + zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global);
11152 + add_index_zval(instance, global, zobj);
11153 + RETVAL_OBJECT(zobj, 1);
11155 + zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC);
11156 + zval_ptr_dtor(&instance);
11164 +/* {{{ Getters by type */
11165 +#define HTTP_QUERYSTRING_GETTER(method, TYPE) \
11166 +PHP_METHOD(HttpQueryString, method) \
11170 + zval *defval = NULL; \
11171 + zend_bool del = 0; \
11172 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &name, &name_len, &defval, &del)) { \
11173 + http_querystring_get(getThis(), TYPE, name, name_len, defval, del, return_value); \
11176 +HTTP_QUERYSTRING_GETTER(getBool, IS_BOOL);
11177 +HTTP_QUERYSTRING_GETTER(getInt, IS_LONG);
11178 +HTTP_QUERYSTRING_GETTER(getFloat, IS_DOUBLE);
11179 +HTTP_QUERYSTRING_GETTER(getString, IS_STRING);
11180 +HTTP_QUERYSTRING_GETTER(getArray, IS_ARRAY);
11181 +HTTP_QUERYSTRING_GETTER(getObject, IS_OBJECT);
11184 +#ifdef HTTP_HAVE_ICONV
11185 +/* {{{ proto bool HttpQueryString::xlate(string ie, string oe)
11186 + 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. */
11187 +PHP_METHOD(HttpQueryString, xlate)
11190 + int ie_len, oe_len;
11191 + zval xa, *qa, *qs;
11194 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ie, &ie_len, &oe, &oe_len)) {
11198 + qa = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11199 + qs = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC);
11203 + if (SUCCESS == (rs = http_querystring_xlate(&xa, qa, ie, oe))) {
11204 + zend_hash_clean(Z_ARRVAL_P(qa));
11205 + zend_hash_copy(Z_ARRVAL_P(qa), Z_ARRVAL(xa), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
11206 + http_querystring_update(qa, qs);
11210 + RETURN_SUCCESS(rs);
11213 +#endif /* HAVE_ICONV */
11215 +/* {{{ proto string HttpQueryString::serialize()
11216 + Implements Serializable::serialize(). */
11217 +PHP_METHOD(HttpQueryString, serialize)
11220 + RETURN_PROP(queryString);
11224 +/* {{{ proto void HttpQueryString::unserialize(string serialized)
11225 + Implements Serializable::unserialize(). */
11226 +PHP_METHOD(HttpQueryString, unserialize)
11228 + zval *serialized;
11230 + SET_EH_THROW_HTTP();
11231 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &serialized)) {
11232 + if (Z_TYPE_P(serialized) == IS_STRING) {
11233 + http_querystring_instantiate(getThis(), 0, serialized, 0);
11235 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Expected a string as parameter");
11242 +/* {{{ proto mixed HttpQueryString::offsetGet(string offset)
11243 + Implements ArrayAccess::offsetGet(). */
11244 +PHP_METHOD(HttpQueryString, offsetGet)
11246 + char *offset_str;
11250 + if ( (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) &&
11251 + (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))) {
11252 + RETVAL_ZVAL(*value, 1, 0);
11257 +/* {{{ proto void HttpQueryString::offsetSet(string offset, mixed value)
11258 + Implements ArrayAccess::offsetGet(). */
11259 +PHP_METHOD(HttpQueryString, offsetSet)
11261 + char *offset_str;
11265 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset_str, &offset_len, &value)) {
11266 + 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);
11268 + ZVAL_ADDREF(value);
11269 + add_assoc_zval_ex(qarr, offset_str, offset_len + 1, value);
11270 + http_querystring_update(qarr, qstr);
11275 +/* {{{ proto bool HttpQueryString::offsetExists(string offset)
11276 + Implements ArrayAccess::offsetExists(). */
11277 +PHP_METHOD(HttpQueryString, offsetExists)
11279 + char *offset_str;
11283 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
11284 + 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));
11289 +/* {{{ proto void HttpQueryString::offsetUnset(string offset)
11290 + Implements ArrayAccess::offsetUnset(). */
11291 +PHP_METHOD(HttpQueryString, offsetUnset)
11293 + char *offset_str;
11296 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
11297 + zval *qarr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11299 + if (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarr), offset_str, offset_len + 1)) {
11300 + http_querystring_update(qarr, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
11306 +#endif /* ZEND_ENGINE_2 */
11309 + * Local variables:
11311 + * c-basic-offset: 4
11313 + * vim600: noet sw=4 ts=4 fdm=marker
11314 + * vim<600: noet sw=4 ts=4
11318 +++ b/ext/http/http_request_api.c
11321 + +--------------------------------------------------------------------+
11323 + +--------------------------------------------------------------------+
11324 + | Redistribution and use in source and binary forms, with or without |
11325 + | modification, are permitted provided that the conditions mentioned |
11326 + | in the accompanying LICENSE file are met. |
11327 + +--------------------------------------------------------------------+
11328 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
11329 + +--------------------------------------------------------------------+
11332 +/* $Id: http_request_api.c 310775 2011-05-05 06:02:50Z mike $ */
11334 +#define HTTP_WANT_SAPI
11335 +#define HTTP_WANT_CURL
11336 +#include "php_http.h"
11338 +#ifdef HTTP_HAVE_CURL
11340 +#include "php_http_api.h"
11341 +#include "php_http_persistent_handle_api.h"
11342 +#include "php_http_request_api.h"
11343 +#include "php_http_url_api.h"
11345 +#ifdef ZEND_ENGINE_2
11346 +# include "php_http_request_object.h"
11349 +#include "php_http_request_int.h"
11351 +/* {{{ cruft for thread safe SSL crypto locks */
11352 +#ifdef HTTP_NEED_OPENSSL_TSL
11353 +static MUTEX_T *http_openssl_tsl = NULL;
11355 +static void http_openssl_thread_lock(int mode, int n, const char * file, int line)
11357 + if (mode & CRYPTO_LOCK) {
11358 + tsrm_mutex_lock(http_openssl_tsl[n]);
11360 + tsrm_mutex_unlock(http_openssl_tsl[n]);
11364 +static ulong http_openssl_thread_id(void)
11366 + return (ulong) tsrm_thread_id();
11369 +#ifdef HTTP_NEED_GNUTLS_TSL
11370 +static int http_gnutls_mutex_create(void **m)
11372 + if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
11379 +static int http_gnutls_mutex_destroy(void **m)
11381 + tsrm_mutex_free(*((MUTEX_T *) m));
11385 +static int http_gnutls_mutex_lock(void **m)
11387 + return tsrm_mutex_lock(*((MUTEX_T *) m));
11390 +static int http_gnutls_mutex_unlock(void **m)
11392 + return tsrm_mutex_unlock(*((MUTEX_T *) m));
11395 +static struct gcry_thread_cbs http_gnutls_tsl = {
11396 + GCRY_THREAD_OPTION_USER,
11398 + http_gnutls_mutex_create,
11399 + http_gnutls_mutex_destroy,
11400 + http_gnutls_mutex_lock,
11401 + http_gnutls_mutex_unlock
11406 +/* safe curl wrappers */
11407 +#define init_curl_storage(ch) \
11409 + http_request_storage *st = pecalloc(1, sizeof(http_request_storage), 1); \
11410 + curl_easy_setopt(ch, CURLOPT_PRIVATE, st); \
11411 + curl_easy_setopt(ch, CURLOPT_ERRORBUFFER, st->errorbuffer); \
11414 +static void *safe_curl_init(void)
11418 + if ((ch = curl_easy_init())) {
11419 + init_curl_storage(ch);
11424 +static void *safe_curl_copy(void *p)
11428 + if ((ch = curl_easy_duphandle(p))) {
11429 + init_curl_storage(ch);
11434 +static void safe_curl_dtor(void *p) {
11435 + http_request_storage *st = http_request_storage_get(p);
11437 + curl_easy_cleanup(p);
11441 + pefree(st->url, 1);
11443 + if (st->cookiestore) {
11444 + pefree(st->cookiestore, 1);
11452 +PHP_MINIT_FUNCTION(http_request)
11454 +#ifdef HTTP_NEED_OPENSSL_TSL
11455 + /* mod_ssl, libpq or ext/curl might already have set thread lock callbacks */
11456 + if (!CRYPTO_get_id_callback()) {
11457 + int i, c = CRYPTO_num_locks();
11459 + http_openssl_tsl = malloc(c * sizeof(MUTEX_T));
11461 + for (i = 0; i < c; ++i) {
11462 + http_openssl_tsl[i] = tsrm_mutex_alloc();
11465 + CRYPTO_set_id_callback(http_openssl_thread_id);
11466 + CRYPTO_set_locking_callback(http_openssl_thread_lock);
11469 +#ifdef HTTP_NEED_GNUTLS_TSL
11470 + gcry_control(GCRYCTL_SET_THREAD_CBS, &http_gnutls_tsl);
11473 + if (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL)) {
11477 + if (SUCCESS != http_persistent_handle_provide("http_request", safe_curl_init, safe_curl_dtor, safe_curl_copy)) {
11481 + HTTP_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC);
11482 + HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST);
11483 +#if HTTP_CURL_VERSION(7,19,3)
11484 + HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST_IE", CURLAUTH_DIGEST_IE);
11486 + HTTP_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM);
11487 + HTTP_LONG_CONSTANT("HTTP_AUTH_GSSNEG", CURLAUTH_GSSNEGOTIATE);
11488 + HTTP_LONG_CONSTANT("HTTP_AUTH_ANY", CURLAUTH_ANY);
11490 + HTTP_LONG_CONSTANT("HTTP_VERSION_NONE", CURL_HTTP_VERSION_NONE); /* to be removed */
11491 + HTTP_LONG_CONSTANT("HTTP_VERSION_1_0", CURL_HTTP_VERSION_1_0);
11492 + HTTP_LONG_CONSTANT("HTTP_VERSION_1_1", CURL_HTTP_VERSION_1_1);
11493 + HTTP_LONG_CONSTANT("HTTP_VERSION_ANY", CURL_HTTP_VERSION_NONE);
11495 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_TLSv1", CURL_SSLVERSION_TLSv1);
11496 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv2", CURL_SSLVERSION_SSLv2);
11497 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv3", CURL_SSLVERSION_SSLv3);
11498 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_ANY", CURL_SSLVERSION_DEFAULT);
11500 + HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V4", CURL_IPRESOLVE_V4);
11501 + HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V6", CURL_IPRESOLVE_V6);
11502 + HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_ANY", CURL_IPRESOLVE_WHATEVER);
11504 +#if HTTP_CURL_VERSION(7,15,2)
11505 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4", CURLPROXY_SOCKS4);
11507 +#if HTTP_CURL_VERSION(7,18,0)
11508 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4A", CURLPROXY_SOCKS4A);
11509 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5_HOSTNAME);
11511 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5", CURLPROXY_SOCKS5);
11512 + HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP", CURLPROXY_HTTP);
11513 +#if HTTP_CURL_VERSION(7,19,4)
11514 + HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP_1_0", CURLPROXY_HTTP_1_0);
11517 +#if HTTP_CURL_VERSION(7,19,1)
11518 + HTTP_LONG_CONSTANT("HTTP_POSTREDIR_301", CURL_REDIR_POST_301);
11519 + HTTP_LONG_CONSTANT("HTTP_POSTREDIR_302", CURL_REDIR_POST_302);
11520 + HTTP_LONG_CONSTANT("HTTP_POSTREDIR_ALL", CURL_REDIR_POST_ALL);
11526 +/* {{{ MSHUTDOWN */
11527 +PHP_MSHUTDOWN_FUNCTION(http_request)
11529 + curl_global_cleanup();
11530 +#ifdef HTTP_NEED_OPENSSL_TSL
11531 + if (http_openssl_tsl) {
11532 + int i, c = CRYPTO_num_locks();
11534 + CRYPTO_set_id_callback(NULL);
11535 + CRYPTO_set_locking_callback(NULL);
11537 + for (i = 0; i < c; ++i) {
11538 + tsrm_mutex_free(http_openssl_tsl[i]);
11541 + free(http_openssl_tsl);
11542 + http_openssl_tsl = NULL;
11549 +/* {{{ forward declarations */
11550 +#define http_request_option(r, o, k, t) _http_request_option_ex((r), (o), (k), sizeof(k), (t) TSRMLS_CC)
11551 +#define http_request_option_ex(r, o, k, l, t) _http_request_option_ex((r), (o), (k), (l), (t) TSRMLS_CC)
11552 +static inline zval *_http_request_option_ex(http_request *request, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC);
11553 +#define http_request_option_cache(r, k, z) _http_request_option_cache_ex((r), (k), sizeof(k), 0, (z) TSRMLS_CC)
11554 +#define http_request_option_cache_ex(r, k, kl, h, z) _http_request_option_cache_ex((r), (k), (kl), (h), (z) TSRMLS_CC)
11555 +static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC);
11557 +#define http_request_cookies_enabled(r) _http_request_cookies_enabled((r))
11558 +static inline int _http_request_cookies_enabled(http_request *r);
11560 +static size_t http_curl_read_callback(void *, size_t, size_t, void *);
11561 +static int http_curl_progress_callback(void *, double, double, double, double);
11562 +static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *);
11563 +static int http_curl_dummy_callback(char *data, size_t n, size_t l, void *s) { return n*l; }
11564 +static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *);
11567 +/* {{{ CURL *http_curl_init(http_request *) */
11568 +PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC)
11570 + if (ch || (SUCCESS == http_persistent_handle_acquire("http_request", &ch))) {
11572 + curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
11574 + curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
11575 + curl_easy_setopt(ch, CURLOPT_FILETIME, 1L);
11576 + curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1L);
11577 + curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
11578 + curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, NULL);
11579 + curl_easy_setopt(ch, CURLOPT_DEBUGFUNCTION, http_curl_raw_callback);
11580 + curl_easy_setopt(ch, CURLOPT_READFUNCTION, http_curl_read_callback);
11581 + curl_easy_setopt(ch, CURLOPT_IOCTLFUNCTION, http_curl_ioctl_callback);
11582 + curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, http_curl_dummy_callback);
11584 + /* set context */
11586 + curl_easy_setopt(ch, CURLOPT_DEBUGDATA, request);
11588 + /* attach curl handle */
11589 + request->ch = ch;
11590 + /* set defaults (also in http_request_reset()) */
11591 + http_request_defaults(request);
11599 +/* {{{ CURL *http_curl_copy(CURL *) */
11600 +PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC)
11604 + if (SUCCESS == http_persistent_handle_accrete("http_request", ch, ©)) {
11611 +/* {{{ void http_curl_free(CURL **) */
11612 +PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC)
11615 + curl_easy_setopt(*ch, CURLOPT_NOPROGRESS, 1L);
11616 + curl_easy_setopt(*ch, CURLOPT_PROGRESSFUNCTION, NULL);
11617 + curl_easy_setopt(*ch, CURLOPT_VERBOSE, 0L);
11618 + curl_easy_setopt(*ch, CURLOPT_DEBUGFUNCTION, NULL);
11620 + http_persistent_handle_release("http_request", ch);
11625 +/* {{{ http_request *http_request_init(http_request *) */
11626 +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)
11633 + r = emalloc_rel(sizeof(http_request));
11635 + memset(r, 0, sizeof(http_request));
11638 + r->url = (url) ? http_absolute_url(url) : NULL;
11639 + r->meth = (meth > 0) ? meth : HTTP_GET;
11641 + phpstr_init(&r->conv.request);
11642 + phpstr_init_ex(&r->conv.response, HTTP_CURLBUF_SIZE, 0);
11643 + phpstr_init(&r->_cache.cookies);
11644 + zend_hash_init(&r->_cache.options, 0, NULL, ZVAL_PTR_DTOR, 0);
11646 + TSRMLS_SET_CTX(r->tsrm_ls);
11652 +/* {{{ void http_request_dtor(http_request *) */
11653 +PHP_HTTP_API void _http_request_dtor(http_request *request)
11655 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11657 + http_request_reset(request);
11658 + http_curl_free(&request->ch);
11660 + phpstr_dtor(&request->_cache.cookies);
11661 + zend_hash_destroy(&request->_cache.options);
11662 + if (request->_cache.headers) {
11663 + curl_slist_free_all(request->_cache.headers);
11664 + request->_cache.headers = NULL;
11666 + if (request->_progress_callback) {
11667 + zval_ptr_dtor(&request->_progress_callback);
11668 + request->_progress_callback = NULL;
11673 +/* {{{ void http_request_free(http_request **) */
11674 +PHP_HTTP_API void _http_request_free(http_request **request)
11677 + TSRMLS_FETCH_FROM_CTX((*request)->tsrm_ls);
11678 + http_request_body_free(&(*request)->body);
11679 + http_request_dtor(*request);
11686 +/* {{{ void http_request_reset(http_request *) */
11687 +PHP_HTTP_API void _http_request_reset(http_request *request)
11689 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11690 + STR_SET(request->url, NULL);
11691 + request->conv.last_type = 0;
11692 + phpstr_dtor(&request->conv.request);
11693 + phpstr_dtor(&request->conv.response);
11694 + http_request_body_dtor(request->body);
11695 + http_request_defaults(request);
11697 + if (request->ch) {
11698 + http_request_storage *st = http_request_storage_get(request->ch);
11702 + pefree(st->url, 1);
11705 + if (st->cookiestore) {
11706 + pefree(st->cookiestore, 1);
11707 + st->cookiestore = NULL;
11709 + st->errorbuffer[0] = '\0';
11715 +/* {{{ STATUS http_request_enable_cookies(http_request *) */
11716 +PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request)
11718 + int initialized = 1;
11719 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11721 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
11722 + if (initialized && (http_request_cookies_enabled(request) || (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIEFILE, "")))) {
11725 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not enable cookies for this session");
11730 +/* {{{ STATUS http_request_reset_cookies(http_request *, int) */
11731 +PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only)
11733 + int initialized = 1;
11734 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11736 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
11737 + if (initialized) {
11738 + if (!http_request_cookies_enabled(request)) {
11739 + if (SUCCESS != http_request_enable_cookies(request)) {
11743 + if (session_only) {
11744 +#if HTTP_CURL_VERSION(7,15,4)
11745 + if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "SESS")) {
11749 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset session cookies (need libcurl >= v7.15.4)");
11752 +#if HTTP_CURL_VERSION(7,14,1)
11753 + if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "ALL")) {
11757 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset cookies (need libcurl >= v7.14.1)");
11765 +PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request)
11767 + int initialized = 1;
11768 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11770 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
11771 + if (initialized) {
11772 + if (!http_request_cookies_enabled(request)) {
11775 +#if HTTP_CURL_VERSION(7,17,1)
11776 + if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "FLUSH")) {
11780 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not flush cookies (need libcurl >= v7.17.1)");
11786 +/* {{{ void http_request_defaults(http_request *) */
11787 +PHP_HTTP_API void _http_request_defaults(http_request *request)
11789 + if (request->ch) {
11790 + HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL);
11791 + HTTP_CURL_OPT(CURLOPT_URL, NULL);
11792 + HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1L);
11793 +#if HTTP_CURL_VERSION(7,19,4)
11794 + HTTP_CURL_OPT(CURLOPT_NOPROXY, NULL);
11796 + HTTP_CURL_OPT(CURLOPT_PROXY, NULL);
11797 + HTTP_CURL_OPT(CURLOPT_PROXYPORT, 0L);
11798 + HTTP_CURL_OPT(CURLOPT_PROXYTYPE, 0L);
11799 + /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
11800 +#if HTTP_CURL_VERSION(7,19,1)
11801 + HTTP_CURL_OPT(CURLOPT_PROXYUSERNAME, NULL);
11802 + HTTP_CURL_OPT(CURLOPT_PROXYPASSWORD, NULL);
11804 + HTTP_CURL_OPT(CURLOPT_PROXYAUTH, 0L);
11805 + HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 0L);
11806 + HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, 60L);
11807 + HTTP_CURL_OPT(CURLOPT_IPRESOLVE, 0);
11808 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, 0L);
11809 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, 0L);
11810 +#if HTTP_CURL_VERSION(7,15,5)
11812 + HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) 0);
11813 + HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) 0);
11817 + HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, 5L); */
11818 + HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 0L);
11819 + HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 0L);
11820 + HTTP_CURL_OPT(CURLOPT_INTERFACE, NULL);
11821 + HTTP_CURL_OPT(CURLOPT_PORT, 0L);
11822 +#if HTTP_CURL_VERSION(7,19,0)
11823 + HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, 0L);
11825 +#if HTTP_CURL_VERSION(7,15,2)
11826 + HTTP_CURL_OPT(CURLOPT_LOCALPORT, 0L);
11827 + HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, 0L);
11829 + /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
11830 +#if HTTP_CURL_VERSION(7,19,1)
11831 + HTTP_CURL_OPT(CURLOPT_USERNAME, NULL);
11832 + HTTP_CURL_OPT(CURLOPT_PASSWORD, NULL);
11834 + HTTP_CURL_OPT(CURLOPT_HTTPAUTH, 0L);
11835 + HTTP_CURL_OPT(CURLOPT_ENCODING, NULL);
11836 +#if HTTP_CURL_VERSION(7,16,2)
11837 + /* we do this ourself anyway */
11838 + HTTP_CURL_OPT(CURLOPT_HTTP_CONTENT_DECODING, 0L);
11839 + HTTP_CURL_OPT(CURLOPT_HTTP_TRANSFER_DECODING, 0L);
11841 + HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, 0L);
11842 +#if HTTP_CURL_VERSION(7,19,1)
11843 + HTTP_CURL_OPT(CURLOPT_POSTREDIR, 0L);
11844 +#elif HTTP_CURL_VERSION(7,17,1)
11845 + HTTP_CURL_OPT(CURLOPT_POST301, 0L);
11847 + HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, 0L);
11848 + HTTP_CURL_OPT(CURLOPT_REFERER, NULL);
11849 + HTTP_CURL_OPT(CURLOPT_USERAGENT, "PECL::HTTP/" PHP_HTTP_VERSION " (PHP/" PHP_VERSION ")");
11850 + HTTP_CURL_OPT(CURLOPT_HTTPHEADER, NULL);
11851 + HTTP_CURL_OPT(CURLOPT_COOKIE, NULL);
11852 + HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 0L);
11853 + /* these options would enable curl's cookie engine by default which we don't want
11854 + HTTP_CURL_OPT(CURLOPT_COOKIEFILE, NULL);
11855 + HTTP_CURL_OPT(CURLOPT_COOKIEJAR, NULL); */
11856 +#if HTTP_CURL_VERSION(7,14,1)
11857 + HTTP_CURL_OPT(CURLOPT_COOKIELIST, NULL);
11859 + HTTP_CURL_OPT(CURLOPT_RANGE, NULL);
11860 + HTTP_CURL_OPT(CURLOPT_RESUME_FROM, 0L);
11861 + HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, 0L);
11862 + HTTP_CURL_OPT(CURLOPT_TIMECONDITION, 0L);
11863 + HTTP_CURL_OPT(CURLOPT_TIMEVALUE, 0L);
11864 + HTTP_CURL_OPT(CURLOPT_TIMEOUT, 0L);
11865 + HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, 3);
11866 + HTTP_CURL_OPT(CURLOPT_SSLCERT, NULL);
11867 + HTTP_CURL_OPT(CURLOPT_SSLCERTTYPE, NULL);
11868 + HTTP_CURL_OPT(CURLOPT_SSLCERTPASSWD, NULL);
11869 + HTTP_CURL_OPT(CURLOPT_SSLKEY, NULL);
11870 + HTTP_CURL_OPT(CURLOPT_SSLKEYTYPE, NULL);
11871 + HTTP_CURL_OPT(CURLOPT_SSLKEYPASSWD, NULL);
11872 + HTTP_CURL_OPT(CURLOPT_SSLENGINE, NULL);
11873 + HTTP_CURL_OPT(CURLOPT_SSLVERSION, 0L);
11874 + HTTP_CURL_OPT(CURLOPT_SSL_VERIFYPEER, 0L);
11875 + HTTP_CURL_OPT(CURLOPT_SSL_VERIFYHOST, 0L);
11876 + HTTP_CURL_OPT(CURLOPT_SSL_CIPHER_LIST, NULL);
11877 +#if HTTP_CURL_VERSION(7,19,0)
11878 + HTTP_CURL_OPT(CURLOPT_ISSUERCERT, NULL);
11879 + #if defined(HTTP_HAVE_OPENSSL)
11880 + HTTP_CURL_OPT(CURLOPT_CRLFILE, NULL);
11883 +#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
11884 + HTTP_CURL_OPT(CURLOPT_CERTINFO, NULL);
11886 +#ifdef HTTP_CURL_CAINFO
11887 + HTTP_CURL_OPT(CURLOPT_CAINFO, HTTP_CURL_CAINFO);
11889 + HTTP_CURL_OPT(CURLOPT_CAINFO, NULL);
11891 + HTTP_CURL_OPT(CURLOPT_CAPATH, NULL);
11892 + HTTP_CURL_OPT(CURLOPT_RANDOM_FILE, NULL);
11893 + HTTP_CURL_OPT(CURLOPT_EGDSOCKET, NULL);
11894 + HTTP_CURL_OPT(CURLOPT_POSTFIELDS, NULL);
11895 + HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, 0L);
11896 + HTTP_CURL_OPT(CURLOPT_HTTPPOST, NULL);
11897 + HTTP_CURL_OPT(CURLOPT_IOCTLDATA, NULL);
11898 + HTTP_CURL_OPT(CURLOPT_READDATA, NULL);
11899 + HTTP_CURL_OPT(CURLOPT_INFILESIZE, 0L);
11900 + HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE);
11901 + HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, NULL);
11902 + HTTP_CURL_OPT(CURLOPT_NOBODY, 0L);
11903 + HTTP_CURL_OPT(CURLOPT_POST, 0L);
11904 + HTTP_CURL_OPT(CURLOPT_UPLOAD, 0L);
11905 + HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L);
11910 +PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb)
11912 + if (request->_progress_callback) {
11913 + zval_ptr_dtor(&request->_progress_callback);
11915 + if ((request->_progress_callback = cb)) {
11917 + HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 0);
11918 + HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, request);
11919 + HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, http_curl_progress_callback);
11921 + HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1);
11922 + HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, NULL);
11923 + HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL);
11927 +/* {{{ STATUS http_request_prepare(http_request *, HashTable *) */
11928 +PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options)
11931 + zend_bool range_req = 0;
11932 + http_request_storage *storage;
11934 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11936 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init(request), return FAILURE);
11938 + if (!request->url) {
11941 + if (!(storage = http_request_storage_get(request->ch))) {
11944 + storage->errorbuffer[0] = '\0';
11945 + /* set options */
11946 + if (storage->url) {
11947 + pefree(storage->url, 1);
11949 + storage->url = pestrdup(request->url, 1);
11950 + HTTP_CURL_OPT(CURLOPT_URL, storage->url);
11952 + /* progress callback */
11953 + if ((zoption = http_request_option(request, options, "onprogress", -1))) {
11954 + http_request_set_progress_callback(request, zoption);
11958 + if ((zoption = http_request_option(request, options, "proxyhost", IS_STRING))) {
11959 + HTTP_CURL_OPT(CURLOPT_PROXY, Z_STRVAL_P(zoption));
11961 + if ((zoption = http_request_option(request, options, "proxytype", IS_LONG))) {
11962 + HTTP_CURL_OPT(CURLOPT_PROXYTYPE, Z_LVAL_P(zoption));
11965 + if ((zoption = http_request_option(request, options, "proxyport", IS_LONG))) {
11966 + HTTP_CURL_OPT(CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
11969 + if ((zoption = http_request_option(request, options, "proxyauth", IS_STRING)) && Z_STRLEN_P(zoption)) {
11970 + HTTP_CURL_OPT(CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
11972 + /* auth method */
11973 + if ((zoption = http_request_option(request, options, "proxyauthtype", IS_LONG))) {
11974 + HTTP_CURL_OPT(CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
11977 + if ((zoption = http_request_option(request, options, "proxytunnel", IS_BOOL)) && Z_BVAL_P(zoption)) {
11978 + HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 1L);
11981 +#if HTTP_CURL_VERSION(7,19,4)
11982 + if ((zoption = http_request_option(request, options, "noproxy", IS_STRING))) {
11983 + HTTP_CURL_OPT(CURLOPT_NOPROXY, Z_STRVAL_P(zoption));
11988 + if ((zoption = http_request_option(request, options, "dns_cache_timeout", IS_LONG))) {
11989 + HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, Z_LVAL_P(zoption));
11991 + if ((zoption = http_request_option(request, options, "ipresolve", IS_LONG)) && Z_LVAL_P(zoption)) {
11992 + HTTP_CURL_OPT(CURLOPT_IPRESOLVE, Z_LVAL_P(zoption));
11996 + if ((zoption = http_request_option(request, options, "low_speed_limit", IS_LONG))) {
11997 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, Z_LVAL_P(zoption));
11999 + if ((zoption = http_request_option(request, options, "low_speed_time", IS_LONG))) {
12000 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, Z_LVAL_P(zoption));
12002 +#if HTTP_CURL_VERSION(7,15,5)
12004 + if ((zoption = http_request_option(request, options, "max_send_speed", IS_LONG))) {
12005 + HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
12007 + if ((zoption = http_request_option(request, options, "max_recv_speed", IS_LONG))) {
12008 + HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
12013 + if ((zoption = http_request_option(request, options, "maxconnects", IS_LONG))) {
12014 + HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, Z_LVAL_P(zoption));
12016 + if ((zoption = http_request_option(request, options, "fresh_connect", IS_BOOL)) && Z_BVAL_P(zoption)) {
12017 + HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 1L);
12019 + if ((zoption = http_request_option(request, options, "forbid_reuse", IS_BOOL)) && Z_BVAL_P(zoption)) {
12020 + HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 1L);
12023 + /* outgoing interface */
12024 + if ((zoption = http_request_option(request, options, "interface", IS_STRING))) {
12025 + HTTP_CURL_OPT(CURLOPT_INTERFACE, Z_STRVAL_P(zoption));
12027 +#if HTTP_CURL_VERSION(7,15,2)
12028 + if ((zoption = http_request_option(request, options, "portrange", IS_ARRAY))) {
12029 + zval **prs, **pre;
12031 + zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
12032 + if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &prs)) {
12033 + zend_hash_move_forward(Z_ARRVAL_P(zoption));
12034 + if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &pre)) {
12035 + zval *prs_cpy = http_zsep(IS_LONG, *prs);
12036 + zval *pre_cpy = http_zsep(IS_LONG, *pre);
12038 + if (Z_LVAL_P(prs_cpy) && Z_LVAL_P(pre_cpy)) {
12039 + HTTP_CURL_OPT(CURLOPT_LOCALPORT, MIN(Z_LVAL_P(prs_cpy), Z_LVAL_P(pre_cpy)));
12040 + HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, labs(Z_LVAL_P(prs_cpy)-Z_LVAL_P(pre_cpy))+1L);
12042 + zval_ptr_dtor(&prs_cpy);
12043 + zval_ptr_dtor(&pre_cpy);
12050 + /* another port */
12051 + if ((zoption = http_request_option(request, options, "port", IS_LONG))) {
12052 + HTTP_CURL_OPT(CURLOPT_PORT, Z_LVAL_P(zoption));
12055 + /* RFC4007 zone_id */
12056 +#if HTTP_CURL_VERSION(7,19,0)
12057 + if ((zoption = http_request_option(request, options, "address_scope", IS_LONG))) {
12058 + HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, Z_LVAL_P(zoption));
12063 + if ((zoption = http_request_option(request, options, "httpauth", IS_STRING)) && Z_STRLEN_P(zoption)) {
12064 + HTTP_CURL_OPT(CURLOPT_USERPWD, Z_STRVAL_P(zoption));
12066 + if ((zoption = http_request_option(request, options, "httpauthtype", IS_LONG))) {
12067 + HTTP_CURL_OPT(CURLOPT_HTTPAUTH, Z_LVAL_P(zoption));
12070 + /* redirects, defaults to 0 */
12071 + if ((zoption = http_request_option(request, options, "redirect", IS_LONG))) {
12072 + HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1L : 0L);
12073 + HTTP_CURL_OPT(CURLOPT_MAXREDIRS, Z_LVAL_P(zoption));
12074 + if ((zoption = http_request_option(request, options, "unrestrictedauth", IS_BOOL))) {
12075 + HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, Z_LVAL_P(zoption));
12077 +#if HTTP_CURL_VERSION(7,17,1)
12078 + if ((zoption = http_request_option(request, options, "postredir", IS_BOOL))) {
12079 +# if HTTP_CURL_VERSION(7,19,1)
12080 + HTTP_CURL_OPT(CURLOPT_POSTREDIR, Z_BVAL_P(zoption) ? 1L : 0L);
12082 + HTTP_CURL_OPT(CURLOPT_POST301, Z_BVAL_P(zoption) ? 1L : 0L);
12088 + /* retries, defaults to 0 */
12089 + if ((zoption = http_request_option(request, options, "retrycount", IS_LONG))) {
12090 + request->_retry.count = Z_LVAL_P(zoption);
12091 + if ((zoption = http_request_option(request, options, "retrydelay", IS_DOUBLE))) {
12092 + request->_retry.delay = Z_DVAL_P(zoption);
12094 + request->_retry.delay = 0;
12097 + request->_retry.count = 0;
12101 + if ((zoption = http_request_option(request, options, "referer", IS_STRING)) && Z_STRLEN_P(zoption)) {
12102 + HTTP_CURL_OPT(CURLOPT_REFERER, Z_STRVAL_P(zoption));
12105 + /* useragent, default "PECL::HTTP/version (PHP/version)" */
12106 + if ((zoption = http_request_option(request, options, "useragent", IS_STRING))) {
12107 + /* allow to send no user agent, not even default one */
12108 + if (Z_STRLEN_P(zoption)) {
12109 + HTTP_CURL_OPT(CURLOPT_USERAGENT, Z_STRVAL_P(zoption));
12111 + HTTP_CURL_OPT(CURLOPT_USERAGENT, NULL);
12116 + if ((zoption = http_request_option(request, options, "resume", IS_LONG)) && (Z_LVAL_P(zoption) > 0)) {
12118 + HTTP_CURL_OPT(CURLOPT_RESUME_FROM, Z_LVAL_P(zoption));
12120 + /* or range of kind array(array(0,499), array(100,1499)) */
12121 + else if ((zoption = http_request_option(request, options, "range", IS_ARRAY)) && zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
12122 + HashPosition pos1, pos2;
12123 + zval **rr, **rb, **re;
12126 + phpstr_init(&rs);
12127 + FOREACH_VAL(pos1, zoption, rr) {
12128 + if (Z_TYPE_PP(rr) == IS_ARRAY) {
12129 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(rr), &pos2);
12130 + if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &rb, &pos2)) {
12131 + zend_hash_move_forward_ex(Z_ARRVAL_PP(rr), &pos2);
12132 + if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &re, &pos2)) {
12133 + 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))) &&
12134 + ((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)))) {
12135 + zval *rbl = http_zsep(IS_LONG, *rb);
12136 + zval *rel = http_zsep(IS_LONG, *re);
12138 + if ((Z_LVAL_P(rbl) >= 0) && (Z_LVAL_P(rel) >= 0)) {
12139 + phpstr_appendf(&rs, "%ld-%ld,", Z_LVAL_P(rbl), Z_LVAL_P(rel));
12141 + zval_ptr_dtor(&rbl);
12142 + zval_ptr_dtor(&rel);
12149 + if (PHPSTR_LEN(&rs)) {
12150 + zval *cached_range;
12152 + /* ditch last comma */
12153 + PHPSTR_VAL(&rs)[PHPSTR_LEN(&rs)-- -1] = '\0';
12154 + /* cache string */
12155 + MAKE_STD_ZVAL(cached_range);
12156 + ZVAL_STRINGL(cached_range, PHPSTR_VAL(&rs), PHPSTR_LEN(&rs), 0);
12157 + HTTP_CURL_OPT(CURLOPT_RANGE, Z_STRVAL_P(http_request_option_cache(request, "range", cached_range)));
12158 + zval_ptr_dtor(&cached_range);
12162 + /* additional headers, array('name' => 'value') */
12163 + if (request->_cache.headers) {
12164 + curl_slist_free_all(request->_cache.headers);
12165 + request->_cache.headers = NULL;
12167 + if ((zoption = http_request_option(request, options, "headers", IS_ARRAY))) {
12168 + HashKey header_key = initHashKey(0);
12169 + zval **header_val;
12170 + HashPosition pos;
12173 + phpstr_init(&header);
12174 + FOREACH_KEYVAL(pos, zoption, header_key, header_val) {
12175 + if (header_key.type == HASH_KEY_IS_STRING) {
12176 + zval *header_cpy = http_zsep(IS_STRING, *header_val);
12178 + if (!strcasecmp(header_key.str, "range")) {
12182 + phpstr_appendf(&header, "%s: %s", header_key.str, Z_STRVAL_P(header_cpy));
12183 + phpstr_fix(&header);
12184 + request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header));
12185 + phpstr_reset(&header);
12187 + zval_ptr_dtor(&header_cpy);
12190 + phpstr_dtor(&header);
12193 + if ((zoption = http_request_option(request, options, "etag", IS_STRING)) && Z_STRLEN_P(zoption)) {
12194 + zend_bool is_quoted = !((Z_STRVAL_P(zoption)[0] != '"') || (Z_STRVAL_P(zoption)[Z_STRLEN_P(zoption)-1] != '"'));
12197 + phpstr_init(&header);
12198 + phpstr_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", range_req?"If-Match":"If-None-Match", Z_STRVAL_P(zoption));
12199 + phpstr_fix(&header);
12200 + request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header));
12201 + phpstr_dtor(&header);
12203 + /* compression */
12204 + if ((zoption = http_request_option(request, options, "compress", IS_BOOL)) && Z_LVAL_P(zoption)) {
12205 + request->_cache.headers = curl_slist_append(request->_cache.headers, "Accept-Encoding: gzip;q=1.0,deflate;q=0.5");
12207 + HTTP_CURL_OPT(CURLOPT_HTTPHEADER, request->_cache.headers);
12209 + /* lastmodified */
12210 + if ((zoption = http_request_option(request, options, "lastmodified", IS_LONG))) {
12211 + if (Z_LVAL_P(zoption)) {
12212 + if (Z_LVAL_P(zoption) > 0) {
12213 + HTTP_CURL_OPT(CURLOPT_TIMEVALUE, Z_LVAL_P(zoption));
12215 + HTTP_CURL_OPT(CURLOPT_TIMEVALUE, (long) HTTP_G->request.time + Z_LVAL_P(zoption));
12217 + HTTP_CURL_OPT(CURLOPT_TIMECONDITION, (long) (range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE));
12219 + HTTP_CURL_OPT(CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
12223 + /* cookies, array('name' => 'value') */
12224 + if ((zoption = http_request_option(request, options, "cookies", IS_ARRAY))) {
12225 + phpstr_dtor(&request->_cache.cookies);
12226 + if (zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
12227 + zval *urlenc_cookies = NULL;
12228 + /* check whether cookies should not be urlencoded; default is to urlencode them */
12229 + if ((!(urlenc_cookies = http_request_option(request, options, "encodecookies", IS_BOOL))) || Z_BVAL_P(urlenc_cookies)) {
12230 + if (SUCCESS == http_urlencode_hash_recursive(HASH_OF(zoption), &request->_cache.cookies, "; ", lenof("; "), NULL, 0)) {
12231 + phpstr_fix(&request->_cache.cookies);
12232 + HTTP_CURL_OPT(CURLOPT_COOKIE, request->_cache.cookies.data);
12235 + HashPosition pos;
12236 + HashKey cookie_key = initHashKey(0);
12237 + zval **cookie_val;
12239 + FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) {
12240 + if (cookie_key.type == HASH_KEY_IS_STRING) {
12241 + zval *val = http_zsep(IS_STRING, *cookie_val);
12242 + phpstr_appendf(&request->_cache.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val));
12243 + zval_ptr_dtor(&val);
12247 + phpstr_fix(&request->_cache.cookies);
12248 + if (PHPSTR_LEN(&request->_cache.cookies)) {
12249 + HTTP_CURL_OPT(CURLOPT_COOKIE, PHPSTR_VAL(&request->_cache.cookies));
12255 + /* don't load session cookies from cookiestore */
12256 + if ((zoption = http_request_option(request, options, "cookiesession", IS_BOOL)) && Z_BVAL_P(zoption)) {
12257 + HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 1L);
12260 + /* cookiestore, read initial cookies from that file and store cookies back into that file */
12261 + if ((zoption = http_request_option(request, options, "cookiestore", IS_STRING))) {
12262 + if (Z_STRLEN_P(zoption)) {
12263 + HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(zoption), return FAILURE);
12265 + if (storage->cookiestore) {
12266 + pefree(storage->cookiestore, 1);
12268 + storage->cookiestore = pestrndup(Z_STRVAL_P(zoption), Z_STRLEN_P(zoption), 1);
12269 + HTTP_CURL_OPT(CURLOPT_COOKIEFILE, storage->cookiestore);
12270 + HTTP_CURL_OPT(CURLOPT_COOKIEJAR, storage->cookiestore);
12273 + /* maxfilesize */
12274 + if ((zoption = http_request_option(request, options, "maxfilesize", IS_LONG))) {
12275 + HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, Z_LVAL_P(zoption));
12278 + /* http protocol */
12279 + if ((zoption = http_request_option(request, options, "protocol", IS_LONG))) {
12280 + HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, Z_LVAL_P(zoption));
12283 +#if HTTP_CURL_VERSION(7,16,2)
12284 + /* timeout, defaults to 0 */
12285 + if ((zoption = http_request_option(request, options, "timeout", IS_DOUBLE))) {
12286 + HTTP_CURL_OPT(CURLOPT_TIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000));
12288 + /* connecttimeout, defaults to 0 */
12289 + if ((zoption = http_request_option(request, options, "connecttimeout", IS_DOUBLE))) {
12290 + HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000));
12293 + /* timeout, defaults to 0 */
12294 + if ((zoption = http_request_option(request, options, "timeout", IS_LONG))) {
12295 + HTTP_CURL_OPT(CURLOPT_TIMEOUT, Z_LVAL_P(zoption));
12297 + /* connecttimeout, defaults to 0 */
12298 + if ((zoption = http_request_option(request, options, "connecttimeout", IS_LONG))) {
12299 + HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, Z_LVAL_P(zoption));
12304 + if ((zoption = http_request_option(request, options, "ssl", IS_ARRAY))) {
12305 + HashKey key = initHashKey(0);
12307 + HashPosition pos;
12309 + FOREACH_KEYVAL(pos, zoption, key, param) {
12310 + if (key.type == HASH_KEY_IS_STRING) {
12311 + HTTP_CURL_OPT_STRING(CURLOPT_SSLCERT, 0, 1);
12312 + HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTTYPE, 0, 0);
12313 + HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTPASSWD, 0, 0);
12315 + HTTP_CURL_OPT_STRING(CURLOPT_SSLKEY, 0, 0);
12316 + HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYTYPE, 0, 0);
12317 + HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYPASSWD, 0, 0);
12319 + HTTP_CURL_OPT_STRING(CURLOPT_SSLENGINE, 0, 0);
12320 + HTTP_CURL_OPT_LONG(CURLOPT_SSLVERSION, 0);
12322 + HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYPEER, 1);
12323 + HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYHOST, 1);
12324 + HTTP_CURL_OPT_STRING(CURLOPT_SSL_CIPHER_LIST, 1, 0);
12326 + HTTP_CURL_OPT_STRING(CURLOPT_CAINFO, -3, 1);
12327 + HTTP_CURL_OPT_STRING(CURLOPT_CAPATH, -3, 1);
12328 + HTTP_CURL_OPT_STRING(CURLOPT_RANDOM_FILE, -3, 1);
12329 + HTTP_CURL_OPT_STRING(CURLOPT_EGDSOCKET, -3, 1);
12330 +#if HTTP_CURL_VERSION(7,19,0)
12331 + HTTP_CURL_OPT_STRING(CURLOPT_ISSUERCERT, -3, 1);
12332 + #if defined(HTTP_HAVE_OPENSSL)
12333 + HTTP_CURL_OPT_STRING(CURLOPT_CRLFILE, -3, 1);
12336 +#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
12337 + HTTP_CURL_OPT_LONG(CURLOPT_CERTINFO, -3);
12343 + /* request method */
12344 + switch (request->meth) {
12346 + HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L);
12350 + HTTP_CURL_OPT(CURLOPT_NOBODY, 1L);
12354 + HTTP_CURL_OPT(CURLOPT_POST, 1L);
12358 + HTTP_CURL_OPT(CURLOPT_UPLOAD, 1L);
12362 + if (http_request_method_exists(0, request->meth, NULL)) {
12363 + HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, http_request_method_name(request->meth));
12365 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unsupported request method: %d (%s)", request->meth, request->url);
12371 + /* attach request body */
12372 + if (request->body && (request->meth != HTTP_GET) && (request->meth != HTTP_HEAD) && (request->meth != HTTP_OPTIONS)) {
12373 + switch (request->body->type) {
12374 + case HTTP_REQUEST_BODY_EMPTY:
12378 + case HTTP_REQUEST_BODY_CURLPOST:
12379 + HTTP_CURL_OPT(CURLOPT_HTTPPOST, (struct curl_httppost *) request->body->data);
12382 + case HTTP_REQUEST_BODY_CSTRING:
12383 + if (request->meth != HTTP_PUT) {
12384 + HTTP_CURL_OPT(CURLOPT_POSTFIELDS, request->body->data);
12385 + HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, request->body->size);
12388 + /* fallthrough, PUT/UPLOAD _needs_ READDATA */
12389 + case HTTP_REQUEST_BODY_UPLOADFILE:
12390 + HTTP_CURL_OPT(CURLOPT_IOCTLDATA, request);
12391 + HTTP_CURL_OPT(CURLOPT_READDATA, request);
12392 + HTTP_CURL_OPT(CURLOPT_INFILESIZE, request->body->size);
12396 + /* shouldn't ever happen */
12397 + http_error_ex(HE_ERROR, 0, "Unknown request body type: %d (%s)", request->body->type, request->url);
12406 +/* {{{ void http_request_exec(http_request *) */
12407 +PHP_HTTP_API void _http_request_exec(http_request *request)
12411 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12414 + if (CURLE_OK != (result = curl_easy_perform(request->ch))) {
12415 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(result), http_request_storage_get(request->ch)->errorbuffer, request->url);
12416 +#ifdef ZEND_ENGINE_2
12417 + if ((HTTP_G->only_exceptions || GLOBAL_ERROR_HANDLING == EH_THROW) && EG(exception)) {
12418 + add_property_long(EG(exception), "curlCode", result);
12422 + if (request->_retry.count > tries++) {
12423 + switch (result) {
12424 + case CURLE_COULDNT_RESOLVE_PROXY:
12425 + case CURLE_COULDNT_RESOLVE_HOST:
12426 + case CURLE_COULDNT_CONNECT:
12427 + case CURLE_WRITE_ERROR:
12428 + case CURLE_READ_ERROR:
12429 + case CURLE_OPERATION_TIMEDOUT:
12430 + case CURLE_SSL_CONNECT_ERROR:
12431 + case CURLE_GOT_NOTHING:
12432 + case CURLE_SSL_ENGINE_SETFAILED:
12433 + case CURLE_SEND_ERROR:
12434 + case CURLE_RECV_ERROR:
12435 + case CURLE_SSL_ENGINE_INITFAILED:
12436 + case CURLE_LOGIN_DENIED:
12437 + if (request->_retry.delay >= HTTP_DIFFSEC) {
12438 + http_sleep(request->_retry.delay);
12449 +/* {{{ static size_t http_curl_read_callback(void *, size_t, size_t, void *) */
12450 +static size_t http_curl_read_callback(void *data, size_t len, size_t n, void *ctx)
12452 + http_request *request = (http_request *) ctx;
12453 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12455 + if (request->body) {
12456 + switch (request->body->type) {
12457 + case HTTP_REQUEST_BODY_CSTRING:
12459 + size_t out = MIN(len * n, request->body->size - request->body->priv);
12462 + memcpy(data, ((char *) request->body->data) + request->body->priv, out);
12463 + request->body->priv += out;
12469 + case HTTP_REQUEST_BODY_UPLOADFILE:
12470 + return php_stream_read((php_stream *) request->body->data, data, len * n);
12477 +/* {{{ static int http_curl_progress_callback(void *, double, double, double, double) */
12478 +static int http_curl_progress_callback(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow)
12480 + zval *param, retval;
12481 + http_request *request = (http_request *) ctx;
12482 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12484 + INIT_PZVAL(&retval);
12485 + ZVAL_NULL(&retval);
12487 + MAKE_STD_ZVAL(param);
12488 + array_init(param);
12489 + add_assoc_double(param, "dltotal", dltotal);
12490 + add_assoc_double(param, "dlnow", dlnow);
12491 + add_assoc_double(param, "ultotal", ultotal);
12492 + add_assoc_double(param, "ulnow", ulnow);
12494 + with_error_handling(EH_NORMAL, NULL) {
12495 + request->_in_progress_cb = 1;
12496 + call_user_function(EG(function_table), NULL, request->_progress_callback, &retval, 1, ¶m TSRMLS_CC);
12497 + request->_in_progress_cb = 0;
12498 + } end_error_handling();
12500 + zval_ptr_dtor(¶m);
12501 + zval_dtor(&retval);
12507 +/* {{{ static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *) */
12508 +static curlioerr http_curl_ioctl_callback(CURL *ch, curliocmd cmd, void *ctx)
12510 + http_request *request = (http_request *) ctx;
12511 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12513 + if (cmd != CURLIOCMD_RESTARTREAD) {
12514 + return CURLIOE_UNKNOWNCMD;
12517 + if (request->body) {
12518 + switch (request->body->type) {
12519 + case HTTP_REQUEST_BODY_CSTRING:
12520 + request->body->priv = 0;
12521 + return CURLIOE_OK;
12524 + case HTTP_REQUEST_BODY_UPLOADFILE:
12525 + if (SUCCESS == php_stream_rewind((php_stream *) request->body->data)) {
12526 + return CURLIOE_OK;
12532 + return CURLIOE_FAILRESTART;
12536 +/* {{{ static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *) */
12537 +static int http_curl_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx)
12539 + http_request *request = (http_request *) ctx;
12541 +#define EMPTY_HEADER(d, l) (!l || (l == 1 && d[0] == '\n') || (l == 2 && d[0] == '\r' && d[1] == '\n'))
12543 + case CURLINFO_DATA_IN:
12544 + if (request->conv.last_type == CURLINFO_HEADER_IN) {
12545 + phpstr_appends(&request->conv.response, HTTP_CRLF);
12547 + phpstr_append(&request->conv.response, data, length);
12549 + case CURLINFO_HEADER_IN:
12550 + if (!EMPTY_HEADER(data, length)) {
12551 + phpstr_append(&request->conv.response, data, length);
12554 + case CURLINFO_DATA_OUT:
12555 + case CURLINFO_HEADER_OUT:
12556 + phpstr_append(&request->conv.request, data, length);
12564 + const char _sym[] = "><><><";
12566 + for (fprintf(stderr, "%c ", _sym[type-1]); length--; data++) {
12567 + fprintf(stderr, HTTP_IS_CTYPE(print, *data)?"%c":"\\x%02X", (int) *data);
12568 + if (*data == '\n' && length) {
12569 + fprintf(stderr, "\n%c ", _sym[type-1]);
12572 + fprintf(stderr, "\n");
12574 + fprintf(stderr, "# %s", data);
12580 + request->conv.last_type = type;
12586 +/* {{{ static inline zval *http_request_option(http_request *, HashTable *, char *, size_t, int) */
12587 +static inline zval *_http_request_option_ex(http_request *r, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC)
12591 + ulong h = zend_hash_func(key, keylen);
12593 + if (SUCCESS == zend_hash_quick_find(options, key, keylen, h, (void *) &zoption)) {
12594 + zval *option, *cached;
12596 + option = http_zsep(type, *zoption);
12597 + cached = http_request_option_cache_ex(r, key, keylen, h, option);
12599 + zval_ptr_dtor(&option);
12608 +/* {{{ static inline zval *http_request_option_cache(http_request *, char *key, zval *) */
12609 +static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC)
12611 + ZVAL_ADDREF(opt);
12614 + zend_hash_quick_update(&r->_cache.options, key, keylen, h, &opt, sizeof(zval *), NULL);
12616 + zend_hash_update(&r->_cache.options, key, keylen, &opt, sizeof(zval *), NULL);
12623 +/* {{{ static inline int http_request_cookies_enabled(http_request *) */
12624 +static inline int _http_request_cookies_enabled(http_request *request) {
12625 + http_request_storage *st;
12627 + if (request->ch && (st = http_request_storage_get(request->ch)) && st->cookiestore) {
12628 + /* cookies are enabled */
12635 +#endif /* HTTP_HAVE_CURL */
12638 + * Local variables:
12640 + * c-basic-offset: 4
12642 + * vim600: noet sw=4 ts=4 fdm=marker
12643 + * vim<600: noet sw=4 ts=4
12647 +++ b/ext/http/http_request_body_api.c
12650 + +--------------------------------------------------------------------+
12652 + +--------------------------------------------------------------------+
12653 + | Redistribution and use in source and binary forms, with or without |
12654 + | modification, are permitted provided that the conditions mentioned |
12655 + | in the accompanying LICENSE file are met. |
12656 + +--------------------------------------------------------------------+
12657 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
12658 + +--------------------------------------------------------------------+
12661 +/* $Id: http_request_body_api.c 292841 2009-12-31 08:48:57Z mike $ */
12663 +#define HTTP_WANT_CURL
12664 +#include "php_http.h"
12666 +#ifdef HTTP_HAVE_CURL
12668 +#include "php_http_api.h"
12669 +#include "php_http_url_api.h"
12670 +#include "php_http_request_body_api.h"
12673 +typedef struct curl_httppost *post_data[2];
12674 +static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC);
12675 +static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC);
12678 +/* {{{ http_request_body *http_request_body_new() */
12679 +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)
12682 + body = emalloc_rel(sizeof(http_request_body));
12685 + body->type = type;
12686 + body->free = free;
12688 + body->data = data;
12689 + body->size = size;
12695 +/* {{{ http_request_body *http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */
12696 +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)
12698 + if (files && (zend_hash_num_elements(files) > 0)) {
12699 + struct curl_httppost *http_post_data[2] = {NULL, NULL};
12701 + if (fields && SUCCESS != recursive_fields(http_post_data, fields, NULL TSRMLS_CC)) {
12704 + if (SUCCESS != recursive_files(http_post_data, files, NULL TSRMLS_CC)) {
12707 + return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CURLPOST, http_post_data[0], 0, 1);
12708 + } else if (fields) {
12710 + size_t encoded_len;
12712 + if (SUCCESS != http_urlencode_hash_ex(fields, 1, NULL, 0, &encoded, &encoded_len)) {
12713 + http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post data");
12717 + return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, encoded, encoded_len, 1);
12719 + return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, estrndup("", 0), 0, 1);
12723 +/* STATUS http_request_body_encode(http_request_body *, char**, size_t *) */
12724 +PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC)
12726 + switch (body->type) {
12727 + case HTTP_REQUEST_BODY_CURLPOST:
12729 +#ifdef HAVE_CURL_FORMGET
12732 + phpstr_init_ex(&str, 0x8000, 0);
12733 + if (curl_formget(body->data, &str, (curl_formget_callback) phpstr_append)) {
12734 + phpstr_dtor(&str);
12736 + phpstr_fix(&str);
12737 + *buf = PHPSTR_VAL(&str);
12738 + *len = PHPSTR_LEN(&str);
12745 + case HTTP_REQUEST_BODY_CSTRING:
12746 + *buf = estrndup(body->data, *len = body->size);
12756 +/* {{{ void http_request_body_dtor(http_request_body *) */
12757 +PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC)
12760 + if (body->free) {
12761 + switch (body->type) {
12762 + case HTTP_REQUEST_BODY_CSTRING:
12763 + if (body->data) {
12764 + efree(body->data);
12768 + case HTTP_REQUEST_BODY_CURLPOST:
12769 + curl_formfree(body->data);
12772 + case HTTP_REQUEST_BODY_UPLOADFILE:
12773 + php_stream_close(body->data);
12777 + memset(body, 0, sizeof(http_request_body));
12782 +/* {{{ void http_request_body_free(http_request_body *) */
12783 +PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC)
12786 + http_request_body_dtor(*body);
12793 +static inline char *format_key(uint type, char *str, ulong num, const char *prefix, int numeric_key_for_empty_prefix) {
12794 + char *new_key = NULL;
12796 + if (prefix && *prefix) {
12797 + if (type == HASH_KEY_IS_STRING) {
12798 + spprintf(&new_key, 0, "%s[%s]", prefix, str);
12800 + spprintf(&new_key, 0, "%s[%lu]", prefix, num);
12802 + } else if (type == HASH_KEY_IS_STRING) {
12803 + new_key = estrdup(str);
12804 + } else if (numeric_key_for_empty_prefix) {
12805 + spprintf(&new_key, 0, "%lu", num);
12811 +/* {{{ static STATUS recursive_fields(post_data d, HashTable *f, const char *p TSRMLS_DC) */
12812 +static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC) {
12813 + HashKey key = initHashKey(0);
12815 + HashPosition pos;
12816 + char *new_key = NULL;
12817 + CURLcode err = 0;
12819 + if (fields && !fields->nApplyCount) {
12820 + FOREACH_HASH_KEYVAL(pos, fields, key, data_ptr) {
12821 + if (key.type != HASH_KEY_IS_STRING || *key.str) {
12822 + new_key = format_key(key.type, key.str, key.num, prefix, 1);
12824 + switch (Z_TYPE_PP(data_ptr)) {
12826 + case IS_OBJECT: {
12829 + ++fields->nApplyCount;
12830 + status = recursive_fields(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC);
12831 + --fields->nApplyCount;
12833 + if (SUCCESS != status) {
12840 + zval *data = http_zsep(IS_STRING, *data_ptr);
12842 + err = curl_formadd(&http_post_data[0], &http_post_data[1],
12843 + CURLFORM_COPYNAME, new_key,
12844 + CURLFORM_COPYCONTENTS, Z_STRVAL_P(data),
12845 + CURLFORM_CONTENTSLENGTH, (long) Z_STRLEN_P(data),
12849 + zval_ptr_dtor(&data);
12851 + if (CURLE_OK != err) {
12857 + STR_FREE(new_key);
12868 + if (http_post_data[0]) {
12869 + curl_formfree(http_post_data[0]);
12872 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: %s", curl_easy_strerror(err));
12874 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: unknown error");
12880 +/* {{{ static STATUS recursive_files(post_data d, HashTable *f, const char *p TSRMLS_DC) */
12881 +static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC) {
12882 + HashKey key = initHashKey(0);
12884 + HashPosition pos;
12885 + char *new_key = NULL;
12886 + CURLcode err = 0;
12888 + if (files && !files->nApplyCount) {
12889 + FOREACH_HASH_KEYVAL(pos, files, key, data_ptr) {
12890 + zval **file_ptr, **type_ptr, **name_ptr;
12892 + if (key.type != HASH_KEY_IS_STRING || *key.str) {
12893 + new_key = format_key(key.type, key.str, key.num, prefix, 0);
12895 + if (Z_TYPE_PP(data_ptr) != IS_ARRAY && Z_TYPE_PP(data_ptr) != IS_OBJECT) {
12896 + if (new_key || key.type == HASH_KEY_IS_STRING) {
12897 + http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%s'", new_key ? new_key : key.str);
12899 + http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%lu'", key.num);
12901 + } else if ( SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "name", sizeof("name"), (void *) &name_ptr) ||
12902 + SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "type", sizeof("type"), (void *) &type_ptr) ||
12903 + SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "file", sizeof("file"), (void *) &file_ptr)) {
12906 + ++files->nApplyCount;
12907 + status = recursive_files(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC);
12908 + --files->nApplyCount;
12910 + if (SUCCESS != status) {
12914 + const char *path;
12915 + zval *file = http_zsep(IS_STRING, *file_ptr);
12916 + zval *type = http_zsep(IS_STRING, *type_ptr);
12917 + zval *name = http_zsep(IS_STRING, *name_ptr);
12919 + HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(file), goto error);
12921 + /* this is blatant but should be sufficient for most cases */
12922 + if (strncasecmp(Z_STRVAL_P(file), "file://", lenof("file://"))) {
12923 + path = Z_STRVAL_P(file);
12925 + path = Z_STRVAL_P(file) + lenof("file://");
12929 + char *tmp_key = format_key(HASH_KEY_IS_STRING, Z_STRVAL_P(name), 0, new_key, 0);
12930 + STR_SET(new_key, tmp_key);
12933 + err = curl_formadd(&http_post_data[0], &http_post_data[1],
12934 + CURLFORM_COPYNAME, new_key ? new_key : Z_STRVAL_P(name),
12935 + CURLFORM_FILE, path,
12936 + CURLFORM_CONTENTTYPE, Z_STRVAL_P(type),
12940 + zval_ptr_dtor(&file);
12941 + zval_ptr_dtor(&type);
12942 + zval_ptr_dtor(&name);
12944 + if (CURLE_OK != err) {
12948 + STR_FREE(new_key);
12959 + if (http_post_data[0]) {
12960 + curl_formfree(http_post_data[0]);
12963 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: %s", curl_easy_strerror(err));
12965 + http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: unknown error");
12971 +#endif /* HTTP_HAVE_CURL */
12974 + * Local variables:
12976 + * c-basic-offset: 4
12978 + * vim600: noet sw=4 ts=4 fdm=marker
12979 + * vim<600: noet sw=4 ts=4
12982 +++ b/ext/http/http_request_datashare_api.c
12985 + +--------------------------------------------------------------------+
12987 + +--------------------------------------------------------------------+
12988 + | Redistribution and use in source and binary forms, with or without |
12989 + | modification, are permitted provided that the conditions mentioned |
12990 + | in the accompanying LICENSE file are met. |
12991 + +--------------------------------------------------------------------+
12992 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
12993 + +--------------------------------------------------------------------+
12996 +/* $Id: http_request_datashare_api.c 292841 2009-12-31 08:48:57Z mike $ */
12998 +#define HTTP_WANT_CURL
12999 +#include "php_http.h"
13001 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
13003 +#include "php_http_api.h"
13004 +#include "php_http_persistent_handle_api.h"
13005 +#include "php_http_request_datashare_api.h"
13006 +#include "php_http_request_api.h"
13007 +#include "php_http_request_object.h"
13009 +static HashTable http_request_datashare_options;
13010 +static http_request_datashare http_request_datashare_global;
13011 +static int http_request_datashare_compare_handles(void *h1, void *h2);
13012 +static void http_request_datashare_destroy_handles(void *el);
13014 +static void *http_request_datashare_locks_init(void);
13015 +static void http_request_datashare_locks_dtor(void *l);
13016 +static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr);
13017 +static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr);
13020 +http_request_datashare *_http_request_datashare_global_get(void)
13022 + return &http_request_datashare_global;
13025 +PHP_MINIT_FUNCTION(http_request_datashare)
13027 + curl_lock_data val;
13029 + if (SUCCESS != http_persistent_handle_provide("http_request_datashare", curl_share_init, (http_persistent_handle_dtor) curl_share_cleanup, NULL)) {
13033 + if (SUCCESS != http_persistent_handle_provide("http_request_datashare_lock", http_request_datashare_locks_init, http_request_datashare_locks_dtor, NULL)) {
13038 + if (!http_request_datashare_init_ex(&http_request_datashare_global, 1)) {
13042 + zend_hash_init(&http_request_datashare_options, 4, NULL, NULL, 1);
13043 +#define ADD_DATASHARE_OPT(name, opt) \
13045 + zend_hash_add(&http_request_datashare_options, name, sizeof(name), &val, sizeof(curl_lock_data), NULL)
13046 + ADD_DATASHARE_OPT("cookie", CURL_LOCK_DATA_COOKIE);
13047 + ADD_DATASHARE_OPT("dns", CURL_LOCK_DATA_DNS);
13048 + ADD_DATASHARE_OPT("ssl", CURL_LOCK_DATA_SSL_SESSION);
13049 + ADD_DATASHARE_OPT("connect", CURL_LOCK_DATA_CONNECT);
13054 +PHP_MSHUTDOWN_FUNCTION(http_request_datashare)
13056 + http_request_datashare_dtor(&http_request_datashare_global);
13057 + zend_hash_destroy(&http_request_datashare_options);
13062 +PHP_RINIT_FUNCTION(http_request_datashare)
13064 + zend_llist_init(&HTTP_G->request.datashare.handles, sizeof(zval *), http_request_datashare_destroy_handles, 0);
13069 +PHP_RSHUTDOWN_FUNCTION(http_request_datashare)
13071 + zend_llist_destroy(&HTTP_G->request.datashare.handles);
13076 +PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC)
13078 + zend_bool free_share;
13080 + if ((free_share = !share)) {
13081 + share = pemalloc(sizeof(http_request_datashare), persistent);
13083 + memset(share, 0, sizeof(http_request_datashare));
13085 + if (SUCCESS != http_persistent_handle_acquire("http_request_datashare", &share->ch)) {
13086 + if (free_share) {
13087 + pefree(share, persistent);
13092 + if (!(share->persistent = persistent)) {
13093 + share->handle.list = emalloc(sizeof(zend_llist));
13094 + zend_llist_init(share->handle.list, sizeof(zval *), ZVAL_PTR_DTOR, 0);
13097 + if (SUCCESS == http_persistent_handle_acquire("http_request_datashare_lock", (void *) &share->handle.locks)) {
13098 + curl_share_setopt(share->ch, CURLSHOPT_LOCKFUNC, http_request_datashare_lock_func);
13099 + curl_share_setopt(share->ch, CURLSHOPT_UNLOCKFUNC, http_request_datashare_unlock_func);
13100 + curl_share_setopt(share->ch, CURLSHOPT_USERDATA, share->handle.locks);
13108 +PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC)
13111 + getObjectEx(http_request_object, obj, request);
13113 + if (obj->share) {
13114 + if (obj->share == share) {
13116 + } else if (SUCCESS != http_request_datashare_detach(obj->share, request)) {
13121 + HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init_ex(obj->request->ch, obj->request), return FAILURE);
13122 + if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, share->ch))) {
13123 + 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));
13127 + obj->share = share;
13128 + ZVAL_ADDREF(request);
13129 + zend_llist_add_element(HTTP_RSHARE_HANDLES(share), (void *) &request);
13134 +PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC)
13137 + getObjectEx(http_request_object, obj, request);
13139 + if (!obj->share) {
13140 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to any HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
13141 + } else if (obj->share != share) {
13142 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to this HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
13143 + } else if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL))) {
13144 + 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));
13146 + obj->share = NULL;
13147 + zend_llist_del_element(HTTP_RSHARE_HANDLES(share), request, http_request_datashare_compare_handles);
13153 +PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC)
13157 + while ((r = zend_llist_get_first(HTTP_RSHARE_HANDLES(share)))) {
13158 + http_request_datashare_detach(share, *r);
13162 +PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC)
13164 + if (!share->persistent) {
13165 + zend_llist_destroy(share->handle.list);
13166 + efree(share->handle.list);
13168 + http_persistent_handle_release("http_request_datashare", &share->ch);
13170 + if (share->persistent) {
13171 + http_persistent_handle_release("http_request_datashare_lock", (void *) &share->handle.locks);
13176 +PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC)
13178 + http_request_datashare_dtor(*share);
13179 + pefree(*share, (*share)->persistent);
13183 +PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC)
13185 + curl_lock_data *opt;
13188 + if (SUCCESS == zend_hash_find(&http_request_datashare_options, (char *) option, option_len + 1, (void *) &opt)) {
13189 + if (CURLSHE_OK == (rc = curl_share_setopt(share->ch, enable ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, *opt))) {
13192 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not %s sharing of %s data: %s", enable ? "enable" : "disable", option, curl_share_strerror(rc));
13197 +static int http_request_datashare_compare_handles(void *h1, void *h2)
13199 + return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
13202 +static void http_request_datashare_destroy_handles(void *el)
13204 + zval **r = (zval **) el;
13207 + { /* gcc 2.95 needs these braces */
13208 + getObjectEx(http_request_object, obj, *r);
13210 + curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL);
13211 + zval_ptr_dtor(r);
13216 +static void *http_request_datashare_locks_init(void)
13219 + http_request_datashare_lock *locks = pecalloc(CURL_LOCK_DATA_LAST, sizeof(http_request_datashare_lock), 1);
13222 + for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
13223 + locks[i].mx = tsrm_mutex_alloc();
13230 +static void http_request_datashare_locks_dtor(void *l)
13233 + http_request_datashare_lock *locks = (http_request_datashare_lock *) l;
13235 + for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
13236 + tsrm_mutex_free(locks[i].mx);
13238 + pefree(locks, 1);
13241 +static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr)
13243 + http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
13245 + /* TSRM can't distinguish shared/exclusive locks */
13246 + tsrm_mutex_lock(locks[data].mx);
13247 + locks[data].ch = handle;
13250 +static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr)
13252 + http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
13254 + if (locks[data].ch == handle) {
13255 + tsrm_mutex_unlock(locks[data].mx);
13260 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
13264 + * Local variables:
13266 + * c-basic-offset: 4
13268 + * vim600: noet sw=4 ts=4 fdm=marker
13269 + * vim<600: noet sw=4 ts=4
13273 +++ b/ext/http/http_request_info.c
13276 + +--------------------------------------------------------------------+
13278 + +--------------------------------------------------------------------+
13279 + | Redistribution and use in source and binary forms, with or without |
13280 + | modification, are permitted provided that the conditions mentioned |
13281 + | in the accompanying LICENSE file are met. |
13282 + +--------------------------------------------------------------------+
13283 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
13284 + +--------------------------------------------------------------------+
13287 +/* $Id: http_request_info.c 293136 2010-01-05 08:48:52Z mike $ */
13289 +#define HTTP_WANT_CURL
13290 +#include "php_http.h"
13292 +#ifdef HTTP_HAVE_CURL
13293 +#include "php_http_request_api.h"
13295 +/* {{{ void http_request_info(http_request *, HashTable *) */
13296 +PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info)
13301 + struct curl_slist *s, *p;
13302 + zval *subarray, array;
13303 + INIT_ZARR(array, info);
13306 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_EFFECTIVE_URL, &c)) {
13307 + add_assoc_string_ex(&array, "effective_url", sizeof("effective_url"), c ? c : "", 1);
13309 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_RESPONSE_CODE, &l)) {
13310 + add_assoc_long_ex(&array, "response_code", sizeof("response_code"), l);
13312 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_TOTAL_TIME, &d)) {
13313 + add_assoc_double_ex(&array, "total_time", sizeof("total_time"), d);
13315 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NAMELOOKUP_TIME, &d)) {
13316 + add_assoc_double_ex(&array, "namelookup_time", sizeof("namelookup_time"), d);
13318 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONNECT_TIME, &d)) {
13319 + add_assoc_double_ex(&array, "connect_time", sizeof("connect_time"), d);
13321 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRETRANSFER_TIME, &d)) {
13322 + add_assoc_double_ex(&array, "pretransfer_time", sizeof("pretransfer_time"), d);
13324 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_UPLOAD, &d)) {
13325 + add_assoc_double_ex(&array, "size_upload", sizeof("size_upload"), d);
13327 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_DOWNLOAD, &d)) {
13328 + add_assoc_double_ex(&array, "size_download", sizeof("size_download"), d);
13330 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_DOWNLOAD, &d)) {
13331 + add_assoc_double_ex(&array, "speed_download", sizeof("speed_download"), d);
13333 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_UPLOAD, &d)) {
13334 + add_assoc_double_ex(&array, "speed_upload", sizeof("speed_upload"), d);
13336 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HEADER_SIZE, &l)) {
13337 + add_assoc_long_ex(&array, "header_size", sizeof("header_size"), l);
13339 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REQUEST_SIZE, &l)) {
13340 + add_assoc_long_ex(&array, "request_size", sizeof("request_size"), l);
13342 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_VERIFYRESULT, &l)) {
13343 + add_assoc_long_ex(&array, "ssl_verifyresult", sizeof("ssl_verifyresult"), l);
13345 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_FILETIME, &l)) {
13346 + add_assoc_long_ex(&array, "filetime", sizeof("filetime"), l);
13348 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
13349 + add_assoc_double_ex(&array, "content_length_download", sizeof("content_length_download"), d);
13351 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_UPLOAD, &d)) {
13352 + add_assoc_double_ex(&array, "content_length_upload", sizeof("content_length_upload"), d);
13354 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_STARTTRANSFER_TIME, &d)) {
13355 + add_assoc_double_ex(&array, "starttransfer_time", sizeof("starttransfer_time"), d);
13357 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_TYPE, &c)) {
13358 + add_assoc_string_ex(&array, "content_type", sizeof("content_type"), c ? c : "", 1);
13360 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_TIME, &d)) {
13361 + add_assoc_double_ex(&array, "redirect_time", sizeof("redirect_time"), d);
13363 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_COUNT, &l)) {
13364 + add_assoc_long_ex(&array, "redirect_count", sizeof("redirect_count"), l);
13366 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTP_CONNECTCODE, &l)) {
13367 + add_assoc_long_ex(&array, "connect_code", sizeof("connect_code"), l);
13369 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTPAUTH_AVAIL, &l)) {
13370 + add_assoc_long_ex(&array, "httpauth_avail", sizeof("httpauth_avail"), l);
13372 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PROXYAUTH_AVAIL, &l)) {
13373 + add_assoc_long_ex(&array, "proxyauth_avail", sizeof("proxyauth_avail"), l);
13375 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_OS_ERRNO, &l)) {
13376 + add_assoc_long_ex(&array, "os_errno", sizeof("os_errno"), l);
13378 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NUM_CONNECTS, &l)) {
13379 + add_assoc_long_ex(&array, "num_connects", sizeof("num_connects"), l);
13381 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_ENGINES, &s)) {
13382 + MAKE_STD_ZVAL(subarray);
13383 + array_init(subarray);
13384 + for (p = s; p; p = p->next) {
13386 + add_next_index_string(subarray, p->data, 1);
13389 + add_assoc_zval_ex(&array, "ssl_engines", sizeof("ssl_engines"), subarray);
13390 + curl_slist_free_all(s);
13392 +#if HTTP_CURL_VERSION(7,14,1)
13393 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_COOKIELIST, &s)) {
13394 + MAKE_STD_ZVAL(subarray);
13395 + array_init(subarray);
13396 + for (p = s; p; p = p->next) {
13398 + add_next_index_string(subarray, p->data, 1);
13401 + add_assoc_zval_ex(&array, "cookies", sizeof("cookies"), subarray);
13402 + curl_slist_free_all(s);
13405 +#if HTTP_CURL_VERSION(7,18,2)
13406 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_URL, &c)) {
13407 + add_assoc_string_ex(&array, "redirect_url", sizeof("redirect_url"), c ? c : "", 1);
13410 +#if HTTP_CURL_VERSION(7,19,0)
13411 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRIMARY_IP, &c)) {
13412 + add_assoc_string_ex(&array, "primary_ip", sizeof("primary_ip"), c ? c : "", 1);
13415 +#if HTTP_CURL_VERSION(7,19,0)
13416 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_APPCONNECT_TIME, &d)) {
13417 + add_assoc_double_ex(&array, "appconnect_time", sizeof("appconnect_time"), d);
13420 +#if HTTP_CURL_VERSION(7,19,4)
13421 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONDITION_UNMET, &l)) {
13422 + add_assoc_long_ex(&array, "condition_unmet", sizeof("condition_unmet"), l);
13426 +#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
13430 + struct curl_certinfo *ci;
13431 + char *colon, *keyname;
13433 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CERTINFO, &ci)) {
13434 + MAKE_STD_ZVAL(ci_array);
13435 + array_init(ci_array);
13437 + for (i = 0; i < ci->num_of_certs; ++i) {
13438 + s = ci->certinfo[i];
13440 + MAKE_STD_ZVAL(subarray);
13441 + array_init(subarray);
13442 + for (p = s; p; p = p->next) {
13444 + if ((colon = strchr(p->data, ':'))) {
13445 + keyname = estrndup(p->data, colon - p->data);
13446 + add_assoc_string_ex(subarray, keyname, colon - p->data + 1, colon + 1, 1);
13449 + add_next_index_string(subarray, p->data, 1);
13453 + add_next_index_zval(ci_array, subarray);
13455 + add_assoc_zval_ex(&array, "certinfo", sizeof("certinfo"), ci_array);
13459 + add_assoc_string_ex(&array, "error", sizeof("error"), http_request_storage_get(request->ch)->errorbuffer, 1);
13463 +#endif /* HTTP_HAVE_CURL */
13466 + * Local variables:
13468 + * c-basic-offset: 4
13470 + * vim600: noet sw=4 ts=4 fdm=marker
13471 + * vim<600: noet sw=4 ts=4
13474 +++ b/ext/http/http_request_method_api.c
13477 + +--------------------------------------------------------------------+
13479 + +--------------------------------------------------------------------+
13480 + | Redistribution and use in source and binary forms, with or without |
13481 + | modification, are permitted provided that the conditions mentioned |
13482 + | in the accompanying LICENSE file are met. |
13483 + +--------------------------------------------------------------------+
13484 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
13485 + +--------------------------------------------------------------------+
13488 +/* $Id: http_request_method_api.c 292841 2009-12-31 08:48:57Z mike $ */
13490 +#define HTTP_WANT_CURL
13491 +#include "php_http.h"
13493 +#include "php_http_api.h"
13494 +#include "php_http_request_api.h"
13495 +#include "php_http_request_method_api.h"
13497 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
13498 +# include "php_http_request_object.h"
13501 +/* {{{ char *http_request_methods[] */
13502 +static const char *const http_request_methods[] = {
13513 + /* WebDAV - RFC 2518 */
13521 + /* WebDAV Versioning - RFC 3253 */
13522 + "VERSION-CONTROL",
13531 + "BASELINE-CONTROL",
13533 + /* WebDAV Access Control - RFC 3744 */
13540 +PHP_MINIT_FUNCTION(http_request_method)
13543 + HTTP_LONG_CONSTANT("HTTP_METH_GET", HTTP_GET);
13544 + HTTP_LONG_CONSTANT("HTTP_METH_HEAD", HTTP_HEAD);
13545 + HTTP_LONG_CONSTANT("HTTP_METH_POST", HTTP_POST);
13546 + HTTP_LONG_CONSTANT("HTTP_METH_PUT", HTTP_PUT);
13547 + HTTP_LONG_CONSTANT("HTTP_METH_DELETE", HTTP_DELETE);
13548 + HTTP_LONG_CONSTANT("HTTP_METH_OPTIONS", HTTP_OPTIONS);
13549 + HTTP_LONG_CONSTANT("HTTP_METH_TRACE", HTTP_TRACE);
13550 + HTTP_LONG_CONSTANT("HTTP_METH_CONNECT", HTTP_CONNECT);
13551 + /* WebDAV - RFC 2518 */
13552 + HTTP_LONG_CONSTANT("HTTP_METH_PROPFIND", HTTP_PROPFIND);
13553 + HTTP_LONG_CONSTANT("HTTP_METH_PROPPATCH", HTTP_PROPPATCH);
13554 + HTTP_LONG_CONSTANT("HTTP_METH_MKCOL", HTTP_MKCOL);
13555 + HTTP_LONG_CONSTANT("HTTP_METH_COPY", HTTP_COPY);
13556 + HTTP_LONG_CONSTANT("HTTP_METH_MOVE", HTTP_MOVE);
13557 + HTTP_LONG_CONSTANT("HTTP_METH_LOCK", HTTP_LOCK);
13558 + HTTP_LONG_CONSTANT("HTTP_METH_UNLOCK", HTTP_UNLOCK);
13559 + /* WebDAV Versioning - RFC 3253 */
13560 + HTTP_LONG_CONSTANT("HTTP_METH_VERSION_CONTROL", HTTP_VERSION_CONTROL);
13561 + HTTP_LONG_CONSTANT("HTTP_METH_REPORT", HTTP_REPORT);
13562 + HTTP_LONG_CONSTANT("HTTP_METH_CHECKOUT", HTTP_CHECKOUT);
13563 + HTTP_LONG_CONSTANT("HTTP_METH_CHECKIN", HTTP_CHECKIN);
13564 + HTTP_LONG_CONSTANT("HTTP_METH_UNCHECKOUT", HTTP_UNCHECKOUT);
13565 + HTTP_LONG_CONSTANT("HTTP_METH_MKWORKSPACE", HTTP_MKWORKSPACE);
13566 + HTTP_LONG_CONSTANT("HTTP_METH_UPDATE", HTTP_UPDATE);
13567 + HTTP_LONG_CONSTANT("HTTP_METH_LABEL", HTTP_LABEL);
13568 + HTTP_LONG_CONSTANT("HTTP_METH_MERGE", HTTP_MERGE);
13569 + HTTP_LONG_CONSTANT("HTTP_METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL);
13570 + HTTP_LONG_CONSTANT("HTTP_METH_MKACTIVITY", HTTP_MKACTIVITY);
13571 + /* WebDAV Access Control - RFC 3744 */
13572 + HTTP_LONG_CONSTANT("HTTP_METH_ACL", HTTP_ACL);
13577 +static void free_method(void *el)
13579 + efree(*(char **)el);
13582 +static void unregister_method(const char *name TSRMLS_DC)
13584 + char *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_";
13586 + strlcpy(tmp + lenof("HTTP_METH_"), name, HTTP_REQUEST_METHOD_MAXLEN);
13587 + for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) {
13588 + if (*ptr == '-') {
13593 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
13594 + if (SUCCESS != zend_hash_del(&http_request_object_ce->constants_table, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")) + 1)) {
13595 + http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: HttpRequest::%s", tmp + lenof("HTTP_"));
13598 + if (SUCCESS != zend_hash_del(EG(zend_constants), tmp, strlen(tmp) + 1)) {
13599 + http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: %s", tmp);
13603 +PHP_RINIT_FUNCTION(http_request_method)
13607 + zend_hash_init(&HTTP_G->request.methods.registered, 0, NULL, free_method, 0);
13608 +#define HTTP_METH_REG(m) \
13610 + char *_m=estrdup(m); \
13611 + zend_hash_next_index_insert(&HTTP_G->request.methods.registered, (void *) &_m, sizeof(char *), NULL); \
13613 + HTTP_METH_REG("UNKNOWN");
13615 + HTTP_METH_REG("GET");
13616 + HTTP_METH_REG("HEAD");
13617 + HTTP_METH_REG("POST");
13618 + HTTP_METH_REG("PUT");
13619 + HTTP_METH_REG("DELETE");
13620 + HTTP_METH_REG("OPTIONS");
13621 + HTTP_METH_REG("TRACE");
13622 + HTTP_METH_REG("CONNECT");
13623 + /* WebDAV - RFC 2518 */
13624 + HTTP_METH_REG("PROPFIND");
13625 + HTTP_METH_REG("PROPPATCH");
13626 + HTTP_METH_REG("MKCOL");
13627 + HTTP_METH_REG("COPY");
13628 + HTTP_METH_REG("MOVE");
13629 + HTTP_METH_REG("LOCK");
13630 + HTTP_METH_REG("UNLOCK");
13631 + /* WebDAV Versioning - RFC 3253 */
13632 + HTTP_METH_REG("VERSION-CONTROL");
13633 + HTTP_METH_REG("REPORT");
13634 + HTTP_METH_REG("CHECKOUT");
13635 + HTTP_METH_REG("CHECKIN");
13636 + HTTP_METH_REG("UNCHECKOUT");
13637 + HTTP_METH_REG("MKWORKSPACE");
13638 + HTTP_METH_REG("UPDATE");
13639 + HTTP_METH_REG("LABEL");
13640 + HTTP_METH_REG("MERGE");
13641 + HTTP_METH_REG("BASELINE-CONTROL");
13642 + HTTP_METH_REG("MKACTIVITY");
13643 + /* WebDAV Access Control - RFC 3744 */
13644 + HTTP_METH_REG("ACL");
13646 + zend_hash_init(&ht, 0, NULL, ZVAL_PTR_DTOR, 0);
13647 + if (*HTTP_G->request.methods.custom && SUCCESS == http_parse_params(HTTP_G->request.methods.custom, HTTP_PARAMS_DEFAULT, &ht)) {
13648 + HashPosition pos;
13651 + FOREACH_HASH_VAL(pos, &ht, val) {
13652 + if (Z_TYPE_PP(val) == IS_STRING) {
13653 + http_request_method_register(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
13657 + zend_hash_destroy(&ht);
13662 +PHP_RSHUTDOWN_FUNCTION(http_request_method)
13665 + int i, c = zend_hash_next_free_element(&HTTP_G->request.methods.registered);
13667 + for (i = HTTP_MAX_REQUEST_METHOD; i < c; ++i) {
13668 + if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, i, (void *) &name)) {
13669 + unregister_method(*name TSRMLS_CC);
13673 + zend_hash_destroy(&HTTP_G->request.methods.registered);
13677 +#define http_request_method_cncl(m, c) _http_request_method_cncl_ex((m), strlen(m), (c) TSRMLS_CC)
13678 +#define http_request_method_cncl_ex(m, l, c) _http_request_method_cncl_ex((m), (l), (c) TSRMLS_CC)
13679 +static STATUS _http_request_method_cncl_ex(const char *method_name, int method_name_len, char **cnst TSRMLS_DC)
13684 + if (method_name_len >= HTTP_REQUEST_METHOD_MAXLEN) {
13685 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method too long (%s)", method_name);
13687 + cncl = emalloc(method_name_len + 1);
13689 + for (i = 0; i < method_name_len; ++i) {
13690 + switch (method_name[i]) {
13696 + if (!HTTP_IS_CTYPE(alnum, method_name[i])) {
13698 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method contains illegal characters (%s)", method_name);
13701 + cncl[i] = HTTP_TO_CTYPE(upper, method_name[i]);
13705 + cncl[method_name_len] = '\0';
13711 +PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC)
13715 + if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, m, (void *) &name)) {
13718 + return "UNKNOWN";
13721 +PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id_num, const char *id_str TSRMLS_DC)
13725 + if (by_name && (SUCCESS == http_request_method_cncl(id_str, &id_dup))) {
13727 + HashPosition pos;
13728 + HashKey key = initHashKey(0);
13730 + FOREACH_HASH_KEYVAL(pos, &HTTP_G->request.methods.registered, key, name) {
13731 + if (key.type == HASH_KEY_IS_LONG && !strcmp(*name, id_dup)) {
13737 + } else if (zend_hash_index_exists(&HTTP_G->request.methods.registered, id_num)){
13743 +PHP_HTTP_API int _http_request_method_register(const char *method_str, int method_len TSRMLS_DC)
13745 + char *method_dup, *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_";
13746 + int method_num = http_request_method_exists(1, 0, method_str);
13748 + if (!method_num && (SUCCESS == http_request_method_cncl_ex(method_str, method_len, &method_dup))) {
13749 + method_num = zend_hash_next_free_element(&HTTP_G->request.methods.registered);
13750 + zend_hash_index_update(&HTTP_G->request.methods.registered, method_num, (void *) &method_dup, sizeof(char *), NULL);
13752 + strlcpy(tmp + lenof("HTTP_METH_"), method_dup, HTTP_REQUEST_METHOD_MAXLEN);
13753 + for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) {
13754 + if (*ptr == '-') {
13759 + zend_register_long_constant(tmp, strlen(tmp) + 1, method_num, CONST_CS, http_module_number TSRMLS_CC);
13760 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
13761 + zend_declare_class_constant_long(http_request_object_ce, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")), method_num TSRMLS_CC);
13765 + return method_num;
13768 +PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC)
13772 + if (HTTP_STD_REQUEST_METHOD(method)) {
13773 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Standard request methods cannot be unregistered");
13777 + if (SUCCESS != zend_hash_index_find(&HTTP_G->request.methods.registered, method, (void *) &name)) {
13778 + http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Custom request method with id %d does not exist", method);
13782 + unregister_method(*name TSRMLS_CC);
13784 + zend_hash_index_del(&HTTP_G->request.methods.registered, method);
13789 + * Local variables:
13791 + * c-basic-offset: 4
13793 + * vim600: noet sw=4 ts=4 fdm=marker
13794 + * vim<600: noet sw=4 ts=4
13798 +++ b/ext/http/http_request_object.c
13801 + +--------------------------------------------------------------------+
13803 + +--------------------------------------------------------------------+
13804 + | Redistribution and use in source and binary forms, with or without |
13805 + | modification, are permitted provided that the conditions mentioned |
13806 + | in the accompanying LICENSE file are met. |
13807 + +--------------------------------------------------------------------+
13808 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
13809 + +--------------------------------------------------------------------+
13812 +/* $Id: http_request_object.c 300299 2010-06-09 06:23:16Z mike $ */
13814 +#define HTTP_WANT_CURL
13815 +#include "php_http.h"
13817 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
13819 +#include "zend_interfaces.h"
13821 +#include "php_http_api.h"
13822 +#include "php_http_cookie_api.h"
13823 +#include "php_http_exception_object.h"
13824 +#include "php_http_message_api.h"
13825 +#include "php_http_message_object.h"
13826 +#include "php_http_request_api.h"
13827 +#include "php_http_request_object.h"
13828 +#include "php_http_request_pool_api.h"
13829 +#include "php_http_url_api.h"
13831 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequest, method, 0, req_args)
13832 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequest, method, 0)
13833 +#define HTTP_REQUEST_ME(method, visibility) PHP_ME(HttpRequest, method, HTTP_ARGS(HttpRequest, method), visibility)
13834 +#define HTTP_REQUEST_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpRequest, method))
13835 +#define HTTP_REQUEST_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpRequest_##al), HTTP_ARGS(HttpRequest, al), vis)
13837 +HTTP_BEGIN_ARGS(__construct, 0)
13838 + HTTP_ARG_VAL(url, 0)
13839 + HTTP_ARG_VAL(method, 0)
13840 + HTTP_ARG_VAL(options, 0)
13843 +HTTP_BEGIN_ARGS(factory, 0)
13844 + HTTP_ARG_VAL(url, 0)
13845 + HTTP_ARG_VAL(method, 0)
13846 + HTTP_ARG_VAL(options, 0)
13847 + HTTP_ARG_VAL(class_name, 0)
13850 +HTTP_EMPTY_ARGS(getOptions);
13851 +HTTP_BEGIN_ARGS(setOptions, 0)
13852 + HTTP_ARG_VAL(options, 0)
13855 +HTTP_EMPTY_ARGS(getSslOptions);
13856 +HTTP_BEGIN_ARGS(setSslOptions, 0)
13857 + HTTP_ARG_VAL(ssl_options, 0)
13860 +HTTP_BEGIN_ARGS(addSslOptions, 0)
13861 + HTTP_ARG_VAL(ssl_optins, 0)
13864 +HTTP_EMPTY_ARGS(getHeaders);
13865 +HTTP_BEGIN_ARGS(setHeaders, 0)
13866 + HTTP_ARG_VAL(headers, 0)
13869 +HTTP_BEGIN_ARGS(addHeaders, 1)
13870 + HTTP_ARG_VAL(headers, 0)
13873 +HTTP_EMPTY_ARGS(getCookies);
13874 +HTTP_BEGIN_ARGS(setCookies, 0)
13875 + HTTP_ARG_VAL(cookies, 0)
13878 +HTTP_BEGIN_ARGS(addCookies, 1)
13879 + HTTP_ARG_VAL(cookies, 0)
13882 +HTTP_EMPTY_ARGS(enableCookies);
13883 +HTTP_BEGIN_ARGS(resetCookies, 0)
13884 + HTTP_ARG_VAL(session_only, 0)
13886 +HTTP_EMPTY_ARGS(flushCookies);
13888 +HTTP_EMPTY_ARGS(getUrl);
13889 +HTTP_BEGIN_ARGS(setUrl, 1)
13890 + HTTP_ARG_VAL(url, 0)
13893 +HTTP_EMPTY_ARGS(getMethod);
13894 +HTTP_BEGIN_ARGS(setMethod, 1)
13895 + HTTP_ARG_VAL(request_method, 0)
13898 +HTTP_EMPTY_ARGS(getContentType);
13899 +HTTP_BEGIN_ARGS(setContentType, 1)
13900 + HTTP_ARG_VAL(content_type, 0)
13903 +HTTP_EMPTY_ARGS(getQueryData);
13904 +HTTP_BEGIN_ARGS(setQueryData, 0)
13905 + HTTP_ARG_VAL(query_data, 0)
13908 +HTTP_BEGIN_ARGS(addQueryData, 1)
13909 + HTTP_ARG_VAL(query_data, 0)
13912 +HTTP_EMPTY_ARGS(getPostFields);
13913 +HTTP_BEGIN_ARGS(setPostFields, 0)
13914 + HTTP_ARG_VAL(post_fields, 0)
13917 +HTTP_BEGIN_ARGS(addPostFields, 1)
13918 + HTTP_ARG_VAL(post_fields, 0)
13921 +HTTP_EMPTY_ARGS(getPostFiles);
13922 +HTTP_BEGIN_ARGS(setPostFiles, 0)
13923 + HTTP_ARG_VAL(post_files, 0)
13926 +HTTP_BEGIN_ARGS(addPostFile, 2)
13927 + HTTP_ARG_VAL(formname, 0)
13928 + HTTP_ARG_VAL(filename, 0)
13929 + HTTP_ARG_VAL(content_type, 0)
13932 +HTTP_EMPTY_ARGS(getBody);
13933 +HTTP_BEGIN_ARGS(setBody, 0)
13934 + HTTP_ARG_VAL(request_body_data, 0)
13937 +HTTP_BEGIN_ARGS(addBody, 1)
13938 + HTTP_ARG_VAL(request_body_data, 0)
13941 +HTTP_EMPTY_ARGS(getPutFile);
13942 +HTTP_BEGIN_ARGS(setPutFile, 0)
13943 + HTTP_ARG_VAL(filename, 0)
13946 +HTTP_EMPTY_ARGS(getPutData);
13947 +HTTP_BEGIN_ARGS(setPutData, 0)
13948 + HTTP_ARG_VAL(put_data, 0)
13951 +HTTP_BEGIN_ARGS(addPutData, 1)
13952 + HTTP_ARG_VAL(put_data, 0)
13955 +HTTP_EMPTY_ARGS(getResponseData);
13956 +HTTP_BEGIN_ARGS(getResponseHeader, 0)
13957 + HTTP_ARG_VAL(name, 0)
13960 +HTTP_BEGIN_ARGS(getResponseCookies, 0)
13961 + HTTP_ARG_VAL(flags, 0)
13962 + HTTP_ARG_VAL(allowed_extras, 0)
13965 +HTTP_EMPTY_ARGS(getResponseBody);
13966 +HTTP_EMPTY_ARGS(getResponseCode);
13967 +HTTP_EMPTY_ARGS(getResponseStatus);
13968 +HTTP_BEGIN_ARGS(getResponseInfo, 0)
13969 + HTTP_ARG_VAL(name, 0)
13972 +HTTP_EMPTY_ARGS(getMessageClass);
13973 +HTTP_BEGIN_ARGS(setMessageClass, 1)
13974 + HTTP_ARG_VAL(message_class_name, 0)
13977 +HTTP_EMPTY_ARGS(getResponseMessage);
13978 +HTTP_EMPTY_ARGS(getRawResponseMessage);
13979 +HTTP_EMPTY_ARGS(getRequestMessage);
13980 +HTTP_EMPTY_ARGS(getRawRequestMessage);
13981 +HTTP_EMPTY_ARGS(getHistory);
13982 +HTTP_EMPTY_ARGS(clearHistory);
13983 +HTTP_EMPTY_ARGS(send);
13985 +HTTP_BEGIN_ARGS(get, 1)
13986 + HTTP_ARG_VAL(url, 0)
13987 + HTTP_ARG_VAL(options, 0)
13988 + HTTP_ARG_VAL(info, 1)
13991 +HTTP_BEGIN_ARGS(head, 1)
13992 + HTTP_ARG_VAL(url, 0)
13993 + HTTP_ARG_VAL(options, 0)
13994 + HTTP_ARG_VAL(info, 1)
13997 +HTTP_BEGIN_ARGS(postData, 2)
13998 + HTTP_ARG_VAL(url, 0)
13999 + HTTP_ARG_VAL(data, 0)
14000 + HTTP_ARG_VAL(options, 0)
14001 + HTTP_ARG_VAL(info, 1)
14004 +HTTP_BEGIN_ARGS(postFields, 2)
14005 + HTTP_ARG_VAL(url, 0)
14006 + HTTP_ARG_VAL(data, 0)
14007 + HTTP_ARG_VAL(options, 0)
14008 + HTTP_ARG_VAL(info, 1)
14011 +HTTP_BEGIN_ARGS(putData, 2)
14012 + HTTP_ARG_VAL(url, 0)
14013 + HTTP_ARG_VAL(data, 0)
14014 + HTTP_ARG_VAL(options, 0)
14015 + HTTP_ARG_VAL(info, 1)
14018 +HTTP_BEGIN_ARGS(putFile, 2)
14019 + HTTP_ARG_VAL(url, 0)
14020 + HTTP_ARG_VAL(file, 0)
14021 + HTTP_ARG_VAL(options, 0)
14022 + HTTP_ARG_VAL(info, 1)
14025 +HTTP_BEGIN_ARGS(putStream, 2)
14026 + HTTP_ARG_VAL(url, 0)
14027 + HTTP_ARG_VAL(stream, 0)
14028 + HTTP_ARG_VAL(options, 0)
14029 + HTTP_ARG_VAL(info, 1)
14032 +HTTP_BEGIN_ARGS(methodRegister, 1)
14033 + HTTP_ARG_VAL(method_name, 0)
14036 +HTTP_BEGIN_ARGS(methodUnregister, 1)
14037 + HTTP_ARG_VAL(method, 0)
14040 +HTTP_BEGIN_ARGS(methodName, 1)
14041 + HTTP_ARG_VAL(method_id, 0)
14044 +HTTP_BEGIN_ARGS(methodExists, 1)
14045 + HTTP_ARG_VAL(method, 0)
14048 +#ifdef HAVE_CURL_FORMGET
14049 +HTTP_BEGIN_ARGS(encodeBody, 2)
14050 + HTTP_ARG_VAL(fields, 0)
14051 + HTTP_ARG_VAL(files, 0)
14055 +#define THIS_CE http_request_object_ce
14056 +zend_class_entry *http_request_object_ce;
14057 +zend_function_entry http_request_object_fe[] = {
14058 + HTTP_REQUEST_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
14060 + HTTP_REQUEST_ME(setOptions, ZEND_ACC_PUBLIC)
14061 + HTTP_REQUEST_ME(getOptions, ZEND_ACC_PUBLIC)
14062 + HTTP_REQUEST_ME(setSslOptions, ZEND_ACC_PUBLIC)
14063 + HTTP_REQUEST_ME(getSslOptions, ZEND_ACC_PUBLIC)
14064 + HTTP_REQUEST_ME(addSslOptions, ZEND_ACC_PUBLIC)
14066 + HTTP_REQUEST_ME(addHeaders, ZEND_ACC_PUBLIC)
14067 + HTTP_REQUEST_ME(getHeaders, ZEND_ACC_PUBLIC)
14068 + HTTP_REQUEST_ME(setHeaders, ZEND_ACC_PUBLIC)
14070 + HTTP_REQUEST_ME(addCookies, ZEND_ACC_PUBLIC)
14071 + HTTP_REQUEST_ME(getCookies, ZEND_ACC_PUBLIC)
14072 + HTTP_REQUEST_ME(setCookies, ZEND_ACC_PUBLIC)
14074 + HTTP_REQUEST_ME(enableCookies, ZEND_ACC_PUBLIC)
14075 + HTTP_REQUEST_ME(resetCookies, ZEND_ACC_PUBLIC)
14076 + HTTP_REQUEST_ME(flushCookies, ZEND_ACC_PUBLIC)
14078 + HTTP_REQUEST_ME(setMethod, ZEND_ACC_PUBLIC)
14079 + HTTP_REQUEST_ME(getMethod, ZEND_ACC_PUBLIC)
14081 + HTTP_REQUEST_ME(setUrl, ZEND_ACC_PUBLIC)
14082 + HTTP_REQUEST_ME(getUrl, ZEND_ACC_PUBLIC)
14084 + HTTP_REQUEST_ME(setContentType, ZEND_ACC_PUBLIC)
14085 + HTTP_REQUEST_ME(getContentType, ZEND_ACC_PUBLIC)
14087 + HTTP_REQUEST_ME(setQueryData, ZEND_ACC_PUBLIC)
14088 + HTTP_REQUEST_ME(getQueryData, ZEND_ACC_PUBLIC)
14089 + HTTP_REQUEST_ME(addQueryData, ZEND_ACC_PUBLIC)
14091 + HTTP_REQUEST_ME(setPostFields, ZEND_ACC_PUBLIC)
14092 + HTTP_REQUEST_ME(getPostFields, ZEND_ACC_PUBLIC)
14093 + HTTP_REQUEST_ME(addPostFields, ZEND_ACC_PUBLIC)
14095 + HTTP_REQUEST_ME(setBody, ZEND_ACC_PUBLIC)
14096 + HTTP_REQUEST_ME(getBody, ZEND_ACC_PUBLIC)
14097 + HTTP_REQUEST_ME(addBody, ZEND_ACC_PUBLIC)
14098 + HTTP_REQUEST_MALIAS(setRawPostData, setBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
14099 + HTTP_REQUEST_MALIAS(getRawPostData, getBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
14100 + HTTP_REQUEST_MALIAS(addRawPostData, addBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
14102 + HTTP_REQUEST_ME(setPostFiles, ZEND_ACC_PUBLIC)
14103 + HTTP_REQUEST_ME(addPostFile, ZEND_ACC_PUBLIC)
14104 + HTTP_REQUEST_ME(getPostFiles, ZEND_ACC_PUBLIC)
14106 + HTTP_REQUEST_ME(setPutFile, ZEND_ACC_PUBLIC)
14107 + HTTP_REQUEST_ME(getPutFile, ZEND_ACC_PUBLIC)
14109 + HTTP_REQUEST_ME(setPutData, ZEND_ACC_PUBLIC)
14110 + HTTP_REQUEST_ME(getPutData, ZEND_ACC_PUBLIC)
14111 + HTTP_REQUEST_ME(addPutData, ZEND_ACC_PUBLIC)
14113 + HTTP_REQUEST_ME(send, ZEND_ACC_PUBLIC)
14115 + HTTP_REQUEST_ME(getResponseData, ZEND_ACC_PUBLIC)
14116 + HTTP_REQUEST_ME(getResponseHeader, ZEND_ACC_PUBLIC)
14117 + HTTP_REQUEST_ME(getResponseCookies, ZEND_ACC_PUBLIC)
14118 + HTTP_REQUEST_ME(getResponseCode, ZEND_ACC_PUBLIC)
14119 + HTTP_REQUEST_ME(getResponseStatus, ZEND_ACC_PUBLIC)
14120 + HTTP_REQUEST_ME(getResponseBody, ZEND_ACC_PUBLIC)
14121 + HTTP_REQUEST_ME(getResponseInfo, ZEND_ACC_PUBLIC)
14122 + HTTP_REQUEST_ME(getResponseMessage, ZEND_ACC_PUBLIC)
14123 + HTTP_REQUEST_ME(getRawResponseMessage, ZEND_ACC_PUBLIC)
14124 + HTTP_REQUEST_ME(getRequestMessage, ZEND_ACC_PUBLIC)
14125 + HTTP_REQUEST_ME(getRawRequestMessage, ZEND_ACC_PUBLIC)
14126 + HTTP_REQUEST_ME(getHistory, ZEND_ACC_PUBLIC)
14127 + HTTP_REQUEST_ME(clearHistory, ZEND_ACC_PUBLIC)
14129 + HTTP_REQUEST_ME(getMessageClass, ZEND_ACC_PUBLIC)
14130 + HTTP_REQUEST_ME(setMessageClass, ZEND_ACC_PUBLIC)
14132 + HTTP_REQUEST_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
14134 + HTTP_REQUEST_ALIAS(get, http_get)
14135 + HTTP_REQUEST_ALIAS(head, http_head)
14136 + HTTP_REQUEST_ALIAS(postData, http_post_data)
14137 + HTTP_REQUEST_ALIAS(postFields, http_post_fields)
14138 + HTTP_REQUEST_ALIAS(putData, http_put_data)
14139 + HTTP_REQUEST_ALIAS(putFile, http_put_file)
14140 + HTTP_REQUEST_ALIAS(putStream, http_put_stream)
14142 + HTTP_REQUEST_ALIAS(methodRegister, http_request_method_register)
14143 + HTTP_REQUEST_ALIAS(methodUnregister, http_request_method_unregister)
14144 + HTTP_REQUEST_ALIAS(methodName, http_request_method_name)
14145 + HTTP_REQUEST_ALIAS(methodExists, http_request_method_exists)
14146 +#ifdef HAVE_CURL_FORMGET
14147 + HTTP_REQUEST_ALIAS(encodeBody, http_request_body_encode)
14149 + EMPTY_FUNCTION_ENTRY
14151 +static zend_object_handlers http_request_object_handlers;
14153 +PHP_MINIT_FUNCTION(http_request_object)
14155 + HTTP_REGISTER_CLASS_EX(HttpRequest, http_request_object, NULL, 0);
14156 + http_request_object_handlers.clone_obj = _http_request_object_clone_obj;
14158 + zend_declare_property_null(THIS_CE, ZEND_STRS("options")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14159 + zend_declare_property_null(THIS_CE, ZEND_STRS("postFields")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14160 + zend_declare_property_null(THIS_CE, ZEND_STRS("postFiles")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14161 + zend_declare_property_null(THIS_CE, ZEND_STRS("responseInfo")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14162 + zend_declare_property_null(THIS_CE, ZEND_STRS("responseMessage")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14163 + zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PRIVATE TSRMLS_CC);
14164 + zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14165 + zend_declare_property_long(THIS_CE, ZEND_STRS("method")-1, HTTP_GET, ZEND_ACC_PRIVATE TSRMLS_CC);
14166 + zend_declare_property_string(THIS_CE, ZEND_STRS("url")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14167 + zend_declare_property_string(THIS_CE, ZEND_STRS("contentType")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14168 + zend_declare_property_string(THIS_CE, ZEND_STRS("requestBody")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14169 + zend_declare_property_string(THIS_CE, ZEND_STRS("queryData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14170 + zend_declare_property_string(THIS_CE, ZEND_STRS("putFile")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14171 + zend_declare_property_string(THIS_CE, ZEND_STRS("putData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14172 + zend_declare_property_null(THIS_CE, ZEND_STRS("history")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14173 + zend_declare_property_bool(THIS_CE, ZEND_STRS("recordHistory")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
14174 + zend_declare_property_string(THIS_CE, ZEND_STRS("messageClass")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14178 + * Request Method Constants
14181 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_GET")-1, HTTP_GET TSRMLS_CC);
14182 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_HEAD")-1, HTTP_HEAD TSRMLS_CC);
14183 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_POST")-1, HTTP_POST TSRMLS_CC);
14184 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PUT")-1, HTTP_PUT TSRMLS_CC);
14185 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_DELETE")-1, HTTP_DELETE TSRMLS_CC);
14186 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_OPTIONS")-1, HTTP_OPTIONS TSRMLS_CC);
14187 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_TRACE")-1, HTTP_TRACE TSRMLS_CC);
14188 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CONNECT")-1, HTTP_CONNECT TSRMLS_CC);
14189 + /* WebDAV - RFC 2518 */
14190 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPFIND")-1, HTTP_PROPFIND TSRMLS_CC);
14191 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPPATCH")-1, HTTP_PROPPATCH TSRMLS_CC);
14192 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKCOL")-1, HTTP_MKCOL TSRMLS_CC);
14193 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_COPY")-1, HTTP_COPY TSRMLS_CC);
14194 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MOVE")-1, HTTP_MOVE TSRMLS_CC);
14195 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LOCK")-1, HTTP_LOCK TSRMLS_CC);
14196 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNLOCK")-1, HTTP_UNLOCK TSRMLS_CC);
14197 + /* WebDAV Versioning - RFC 3253 */
14198 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_VERSION_CONTROL")-1, HTTP_VERSION_CONTROL TSRMLS_CC);
14199 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_REPORT")-1, HTTP_REPORT TSRMLS_CC);
14200 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKOUT")-1, HTTP_CHECKOUT TSRMLS_CC);
14201 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKIN")-1, HTTP_CHECKIN TSRMLS_CC);
14202 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNCHECKOUT")-1, HTTP_UNCHECKOUT TSRMLS_CC);
14203 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKWORKSPACE")-1, HTTP_MKWORKSPACE TSRMLS_CC);
14204 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UPDATE")-1, HTTP_UPDATE TSRMLS_CC);
14205 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LABEL")-1, HTTP_LABEL TSRMLS_CC);
14206 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MERGE")-1, HTTP_MERGE TSRMLS_CC);
14207 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_BASELINE_CONTROL")-1, HTTP_BASELINE_CONTROL TSRMLS_CC);
14208 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKACTIVITY")-1, HTTP_MKACTIVITY TSRMLS_CC);
14209 + /* WebDAV Access Control - RFC 3744 */
14210 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_ACL")-1, HTTP_ACL TSRMLS_CC);
14213 + * HTTP Protocol Version Constants
14215 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_0")-1, CURL_HTTP_VERSION_1_0 TSRMLS_CC);
14216 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_1")-1, CURL_HTTP_VERSION_1_1 TSRMLS_CC);
14217 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_NONE")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC); /* to be removed */
14218 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_ANY")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC);
14221 + * SSL Version Constants
14223 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_TLSv1")-1, CURL_SSLVERSION_TLSv1 TSRMLS_CC);
14224 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv2")-1, CURL_SSLVERSION_SSLv2 TSRMLS_CC);
14225 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv3")-1, CURL_SSLVERSION_SSLv3 TSRMLS_CC);
14226 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_ANY")-1, CURL_SSLVERSION_DEFAULT TSRMLS_CC);
14229 + * DNS IPvX resolving
14231 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V4")-1, CURL_IPRESOLVE_V4 TSRMLS_CC);
14232 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V6")-1, CURL_IPRESOLVE_V6 TSRMLS_CC);
14233 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_ANY")-1, CURL_IPRESOLVE_WHATEVER TSRMLS_CC);
14238 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_BASIC")-1, CURLAUTH_BASIC TSRMLS_CC);
14239 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST")-1, CURLAUTH_DIGEST TSRMLS_CC);
14240 +#if HTTP_CURL_VERSION(7,19,3)
14241 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST_IE")-1, CURLAUTH_DIGEST_IE TSRMLS_CC);
14243 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_NTLM")-1, CURLAUTH_NTLM TSRMLS_CC);
14244 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_GSSNEG")-1, CURLAUTH_GSSNEGOTIATE TSRMLS_CC);
14245 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_ANY")-1, CURLAUTH_ANY TSRMLS_CC);
14248 + * Proxy Type Constants
14250 +# if HTTP_CURL_VERSION(7,15,2)
14251 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4")-1, CURLPROXY_SOCKS4 TSRMLS_CC);
14253 +#if HTTP_CURL_VERSION(7,18,0)
14254 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4A")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
14255 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5_HOSTNAME")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
14257 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
14258 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP")-1, CURLPROXY_HTTP TSRMLS_CC);
14259 +# if HTTP_CURL_VERSION(7,19,4)
14260 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP_1_0")-1, CURLPROXY_HTTP_1_0 TSRMLS_CC);
14262 +#endif /* WONKY */
14265 + * Post Redirection Constants
14267 +#if HTTP_CURL_VERSION(7,19,1)
14268 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_301")-1, CURL_REDIR_POST_301 TSRMLS_CC);
14269 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_302")-1, CURL_REDIR_POST_302 TSRMLS_CC);
14270 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_ALL")-1, CURL_REDIR_POST_ALL TSRMLS_CC);
14276 +zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC)
14278 + return http_request_object_new_ex(ce, NULL, NULL);
14281 +zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC)
14283 + zend_object_value ov;
14284 + http_request_object *o;
14286 + o = ecalloc(1, sizeof(http_request_object));
14288 + o->request = http_request_init_ex(NULL, ch, 0, NULL);
14294 + ALLOC_HASHTABLE(OBJ_PROP(o));
14295 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
14296 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
14298 + ov.handle = putObject(http_request_object, o);
14299 + ov.handlers = &http_request_object_handlers;
14304 +zend_object_value _http_request_object_clone_obj(zval *this_ptr TSRMLS_DC)
14306 + zend_object_value new_ov;
14307 + http_request_object *new_obj;
14308 + getObject(http_request_object, old_obj);
14310 + new_ov = http_request_object_new_ex(old_obj->zo.ce, NULL, &new_obj);
14311 + if (old_obj->request->ch) {
14312 + http_curl_init_ex(http_curl_copy(old_obj->request->ch), new_obj->request);
14315 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
14316 + phpstr_append(&new_obj->request->conv.request, old_obj->request->conv.request.data, old_obj->request->conv.request.used);
14317 + phpstr_append(&new_obj->request->conv.response, old_obj->request->conv.response.data, old_obj->request->conv.response.used);
14322 +void _http_request_object_free(zend_object *object TSRMLS_DC)
14324 + http_request_object *o = (http_request_object *) object;
14326 + http_request_free(&o->request);
14330 +#define http_request_object_check_request_content_type(t) _http_request_object_check_request_content_type((t) TSRMLS_CC)
14331 +static inline void _http_request_object_check_request_content_type(zval *this_ptr TSRMLS_DC)
14333 + zval *ctype = zend_read_property(THIS_CE, getThis(), ZEND_STRS("contentType")-1, 0 TSRMLS_CC);
14335 + if (Z_STRLEN_P(ctype)) {
14336 + zval **headers, *opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14338 + if ( (Z_TYPE_P(opts) == IS_ARRAY) &&
14339 + (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void *) &headers)) &&
14340 + (Z_TYPE_PP(headers) == IS_ARRAY)) {
14341 + zval **ct_header;
14343 + /* only override if not already set */
14344 + if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(headers), "Content-Type", sizeof("Content-Type"), (void *) &ct_header))) {
14345 + add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14347 + /* or not a string, zero length string or a string of spaces */
14348 + if ((Z_TYPE_PP(ct_header) != IS_STRING) || !Z_STRLEN_PP(ct_header)) {
14349 + add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14351 + int i, only_space = 1;
14353 + /* check for spaces only */
14354 + for (i = 0; i < Z_STRLEN_PP(ct_header); ++i) {
14355 + if (!HTTP_IS_CTYPE(space, Z_STRVAL_PP(ct_header)[i])) {
14360 + if (only_space) {
14361 + add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14367 + MAKE_STD_ZVAL(headers);
14368 + array_init(headers);
14369 + add_assoc_stringl(headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14370 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, headers);
14371 + zval_ptr_dtor(&headers);
14376 +#define http_request_object_message(zo, msg) _http_request_object_message((zo), (msg) TSRMLS_CC)
14377 +static inline zend_object_value _http_request_object_message(zval *this_ptr, http_message *msg TSRMLS_DC)
14379 + zend_object_value ov;
14380 + zval *zcn = zend_read_property(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, 0 TSRMLS_CC);
14382 + 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))) {
14385 + return http_message_object_new_ex(http_message_object_ce, msg, NULL);
14389 +STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC)
14391 + STATUS status = SUCCESS;
14392 + char *url = http_absolute_url(Z_STRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("url")-1, 0 TSRMLS_CC)));
14398 + http_request_reset(obj->request);
14399 + obj->request->url = url;
14400 + HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init(obj->request), return FAILURE);
14402 + switch (obj->request->meth = Z_LVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("method")-1, 0 TSRMLS_CC)))
14410 + zval *put_file = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putFile")-1, 0 TSRMLS_CC);
14412 + http_request_object_check_request_content_type(getThis());
14414 + if (Z_STRLEN_P(put_file)) {
14415 + php_stream_statbuf ssb;
14416 + php_stream *stream = php_stream_open_wrapper_ex(Z_STRVAL_P(put_file), "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT);
14418 + if (stream && SUCCESS == php_stream_stat(stream, &ssb)) {
14419 + obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
14421 + status = FAILURE;
14424 + zval *put_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC);
14425 + obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING,
14426 + estrndup(Z_STRVAL_P(put_data), Z_STRLEN_P(put_data)), Z_STRLEN_P(put_data), 1);
14434 + /* check for raw request body */
14435 + zval *raw_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC);
14437 + if (Z_STRLEN_P(raw_data)) {
14438 + http_request_object_check_request_content_type(getThis());
14439 + obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING,
14440 + estrndup(Z_STRVAL_P(raw_data), Z_STRLEN_P(raw_data)), Z_STRLEN_P(raw_data), 1);
14442 + 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);
14443 + HashTable *fields;
14444 + HashTable *files;
14446 + fields = (Z_TYPE_P(zfields) == IS_ARRAY) ? Z_ARRVAL_P(zfields) : NULL;
14447 + files = (Z_TYPE_P(zfiles) == IS_ARRAY) ? Z_ARRVAL_P(zfiles) : NULL;
14449 + if ((fields && zend_hash_num_elements(fields)) || (files && zend_hash_num_elements(files))) {
14450 + if (!(obj->request->body = http_request_body_fill(obj->request->body, fields, files))) {
14451 + status = FAILURE;
14459 + if (status == SUCCESS) {
14460 + zval *qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC);
14461 + zval *options = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14463 + if (Z_STRLEN_P(qdata)) {
14464 + if (!strchr(obj->request->url, '?')) {
14465 + strlcat(obj->request->url, "?", HTTP_URL_MAXLEN);
14467 + strlcat(obj->request->url, "&", HTTP_URL_MAXLEN);
14469 + strlcat(obj->request->url, Z_STRVAL_P(qdata), HTTP_URL_MAXLEN);
14472 + http_request_prepare(obj->request, Z_ARRVAL_P(options));
14474 + /* check if there's a onProgress method and add it as progress callback if one isn't already set */
14475 + if (zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onprogress", sizeof("onprogress"))) {
14476 + zval **entry, *pcb;
14478 + if ( (Z_TYPE_P(options) != IS_ARRAY)
14479 + || (SUCCESS != zend_hash_find(Z_ARRVAL_P(options), "onprogress", sizeof("onprogress"), (void *) &entry)
14480 + || (!IS_CALLABLE(*entry, 0, NULL)))) {
14481 + MAKE_STD_ZVAL(pcb);
14483 + ZVAL_ADDREF(getThis());
14484 + add_next_index_zval(pcb, getThis());
14485 + add_next_index_stringl(pcb, "onprogress", lenof("onprogress"), 1);
14486 + http_request_set_progress_callback(obj->request, pcb);
14487 + zval_ptr_dtor(&pcb);
14495 +STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC)
14499 + http_message *msg;
14501 + /* always fetch info */
14502 + MAKE_STD_ZVAL(info);
14503 + array_init(info);
14504 + http_request_info(obj->request, Z_ARRVAL_P(info));
14505 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, info TSRMLS_CC);
14506 + zval_ptr_dtor(&info);
14508 + /* parse response message */
14509 + phpstr_fix(&obj->request->conv.request);
14510 + phpstr_fix(&obj->request->conv.response);
14512 + if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response)))) {
14515 + if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) {
14516 + zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
14517 + http_message *response = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response));
14518 + http_message *request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request));
14520 + MAKE_STD_ZVAL(hist);
14521 + ZVAL_OBJVAL(hist, http_request_object_message(getThis(), http_message_interconnect(response, request)), 0);
14522 + if (Z_TYPE_P(history) == IS_OBJECT) {
14523 + http_message_object_prepend(hist, history);
14525 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
14526 + zval_ptr_dtor(&hist);
14529 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, msg->http.info.response.code TSRMLS_CC);
14530 + zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, STR_PTR(msg->http.info.response.status) TSRMLS_CC);
14532 + MAKE_STD_ZVAL(message);
14533 + ZVAL_OBJVAL(message, http_request_object_message(getThis(), msg), 0);
14534 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, message TSRMLS_CC);
14535 + zval_ptr_dtor(&message);
14539 + /* update properties with empty values*/
14542 + MAKE_STD_ZVAL(znull);
14543 + ZVAL_NULL(znull);
14544 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, znull TSRMLS_CC);
14545 + zval_ptr_dtor(&znull);
14547 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, 0 TSRMLS_CC);
14548 + zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, "" TSRMLS_CC);
14550 + /* append request message to history */
14551 + if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) {
14552 + http_message *request;
14554 + if ((request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) {
14555 + zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
14557 + MAKE_STD_ZVAL(hist);
14558 + ZVAL_OBJVAL(hist, http_request_object_message(getThis(), request), 0);
14559 + if (Z_TYPE_P(history) == IS_OBJECT) {
14560 + http_message_object_prepend(hist, history);
14562 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
14563 + zval_ptr_dtor(&hist);
14570 + http_request_set_progress_callback(obj->request, NULL);
14572 + if (!EG(exception) && zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onfinish", sizeof("onfinish"))) {
14575 + MAKE_STD_ZVAL(param);
14576 + ZVAL_BOOL(param, ret == SUCCESS);
14577 + with_error_handling(EH_NORMAL, NULL) {
14578 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "onfinish", NULL, param);
14579 + } end_error_handling();
14580 + zval_ptr_dtor(¶m);
14586 +static int apply_pretty_key(void *pDest, int num_args, va_list args, zend_hash_key *hash_key)
14588 + if (hash_key->arKey && hash_key->nKeyLength > 1) {
14589 + hash_key->h = zend_hash_func(pretty_key(hash_key->arKey, hash_key->nKeyLength - 1, 1, 0), hash_key->nKeyLength);
14591 + return ZEND_HASH_APPLY_KEEP;
14594 +#define http_request_object_set_options_subr(key, ow, pk) \
14595 + _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key), (ow), (pk))
14596 +static inline void _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len, int overwrite, int prettify_keys)
14598 + zval *old_opts, *new_opts, *opts = NULL, **entry = NULL;
14600 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opts)) {
14604 + MAKE_STD_ZVAL(new_opts);
14605 + array_init(new_opts);
14606 + old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14607 + if (Z_TYPE_P(old_opts) == IS_ARRAY) {
14608 + array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
14611 + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), key, len, (void *) &entry)) {
14613 + zend_hash_clean(Z_ARRVAL_PP(entry));
14615 + if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
14617 + array_copy(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry));
14619 + array_join(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry), 0, prettify_keys ? ARRAY_JOIN_PRETTIFY : 0);
14622 + } else if (opts) {
14623 + if (prettify_keys) {
14624 + zend_hash_apply_with_arguments(Z_ARRVAL_P(opts) HTTP_ZAPI_HASH_TSRMLS_CC, apply_pretty_key, 0, NULL);
14626 + ZVAL_ADDREF(opts);
14627 + add_assoc_zval_ex(new_opts, key, len, opts);
14629 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
14630 + zval_ptr_dtor(&new_opts);
14635 +#define http_request_object_get_options_subr(key) \
14636 + _http_request_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key))
14637 +static inline void _http_request_get_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len)
14641 + if (return_value_used) {
14642 + zval *opts, **options;
14644 + opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14645 + array_init(return_value);
14647 + if ( (Z_TYPE_P(opts) == IS_ARRAY) &&
14648 + (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), key, len, (void *) &options))) {
14649 + convert_to_array(*options);
14650 + array_copy(Z_ARRVAL_PP(options), Z_ARRVAL_P(return_value));
14656 +/* ### USERLAND ### */
14658 +/* {{{ proto void HttpRequest::__construct([string url[, int request_method = HTTP_METH_GET[, array options]]])
14659 + Create a new HttpRequest object instance. */
14660 +PHP_METHOD(HttpRequest, __construct)
14662 + char *URL = NULL;
14665 + zval *options = NULL;
14667 + SET_EH_THROW_HTTP();
14668 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!", &URL, &URL_len, &meth, &options)) {
14670 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
14673 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
14676 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options);
14683 +/* {{{ proto HttpRequest HttpRequest::factory([string url[, int request_method HTTP_METH_GET[, array options[, string class_name = "HttpRequest"]]]])
14684 + Create a new HttpRequest object instance. */
14685 +PHP_METHOD(HttpRequest, factory)
14687 + char *cn = NULL, *URL = NULL;
14688 + int cl = 0, URL_len = 0;
14690 + zval *options = NULL;
14691 + zend_object_value ov;
14693 + SET_EH_THROW_HTTP();
14694 + if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!s", &URL, &URL_len, &meth, &options, &cn, &cl) &&
14695 + SUCCESS == http_object_new(&ov, cn, cl, _http_request_object_new_ex, http_request_object_ce, NULL, NULL)) {
14696 + RETVAL_OBJVAL(ov, 0);
14697 + getThis() = return_value;
14699 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
14702 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
14705 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options);
14712 +/* {{{ proto bool HttpRequest::setOptions([array options])
14713 + Set the request options to use. See http_get() for a full list of available options. */
14714 +PHP_METHOD(HttpRequest, setOptions)
14716 + HashKey key = initHashKey(0);
14717 + HashPosition pos;
14718 + zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt;
14720 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
14724 + MAKE_STD_ZVAL(new_opts);
14725 + array_init(new_opts);
14727 + if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
14728 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
14729 + zval_ptr_dtor(&new_opts);
14733 + MAKE_STD_ZVAL(add_opts);
14734 + array_init(add_opts);
14735 + /* some options need extra attention -- thus cannot use array_merge() directly */
14736 + FOREACH_KEYVAL(pos, opts, key, opt) {
14737 + if (key.type == HASH_KEY_IS_STRING) {
14738 +#define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
14739 + if (KEYMATCH(key, "headers")) {
14740 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, *opt);
14741 + } else if (KEYMATCH(key, "cookies")) {
14742 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt);
14743 + } else if (KEYMATCH(key, "ssl")) {
14744 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt);
14745 + } else if (KEYMATCH(key, "url") || KEYMATCH(key, "uri")) {
14746 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "seturl", NULL, *opt);
14747 + } else if (KEYMATCH(key, "method")) {
14748 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmethod", NULL, *opt);
14749 + } else if (KEYMATCH(key, "flushcookies")) {
14750 + getObject(http_request_object, obj);
14751 + if (i_zend_is_true(*opt)) {
14752 + http_request_flush_cookies(obj->request);
14754 + } else if (KEYMATCH(key, "resetcookies")) {
14755 + getObject(http_request_object, obj);
14756 + http_request_reset_cookies(obj->request, (zend_bool) i_zend_is_true(*opt));
14757 + } else if (KEYMATCH(key, "enablecookies")) {
14758 + getObject(http_request_object, obj);
14759 + http_request_enable_cookies(obj->request);
14760 + } else if (KEYMATCH(key, "recordHistory")) {
14761 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, *opt TSRMLS_CC);
14762 + } else if (KEYMATCH(key, "messageClass")) {
14763 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmessageclass", NULL, *opt);
14764 + } else if (Z_TYPE_PP(opt) == IS_NULL) {
14765 + old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14766 + if (Z_TYPE_P(old_opts) == IS_ARRAY) {
14767 + zend_hash_del(Z_ARRVAL_P(old_opts), key.str, key.len);
14770 + ZVAL_ADDREF(*opt);
14771 + add_assoc_zval_ex(add_opts, key.str, key.len, *opt);
14776 + old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14777 + if (Z_TYPE_P(old_opts) == IS_ARRAY) {
14778 + array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
14780 + array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0);
14781 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
14782 + zval_ptr_dtor(&new_opts);
14783 + zval_ptr_dtor(&add_opts);
14789 +/* {{{ proto array HttpRequest::getOptions()
14790 + Get currently set options. */
14791 +PHP_METHOD(HttpRequest, getOptions)
14795 + if (return_value_used) {
14796 + RETURN_PROP(options);
14801 +/* {{{ proto bool HttpRequest::setSslOptions([array options])
14802 + Set SSL options. */
14803 +PHP_METHOD(HttpRequest, setSslOptions)
14805 + http_request_object_set_options_subr("ssl", 1, 0);
14809 +/* {{{ proto bool HttpRequest::addSslOptions(array options)
14810 + Set additional SSL options. */
14811 +PHP_METHOD(HttpRequest, addSslOptions)
14813 + http_request_object_set_options_subr("ssl", 0, 0);
14817 +/* {{{ proto array HttpRequest::getSslOtpions()
14818 + Get previously set SSL options. */
14819 +PHP_METHOD(HttpRequest, getSslOptions)
14821 + http_request_object_get_options_subr("ssl");
14825 +/* {{{ proto bool HttpRequest::addHeaders(array headers)
14826 + Add request header name/value pairs. */
14827 +PHP_METHOD(HttpRequest, addHeaders)
14829 + http_request_object_set_options_subr("headers", 0, 1);
14832 +/* {{{ proto bool HttpRequest::setHeaders([array headers])
14833 + Set request header name/value pairs. */
14834 +PHP_METHOD(HttpRequest, setHeaders)
14836 + http_request_object_set_options_subr("headers", 1, 1);
14840 +/* {{{ proto array HttpRequest::getHeaders()
14841 + Get previously set request headers. */
14842 +PHP_METHOD(HttpRequest, getHeaders)
14844 + http_request_object_get_options_subr("headers");
14848 +/* {{{ proto bool HttpRequest::setCookies([array cookies])
14850 +PHP_METHOD(HttpRequest, setCookies)
14852 + http_request_object_set_options_subr("cookies", 1, 0);
14856 +/* {{{ proto bool HttpRequest::addCookies(array cookies)
14858 +PHP_METHOD(HttpRequest, addCookies)
14860 + http_request_object_set_options_subr("cookies", 0, 0);
14864 +/* {{{ proto array HttpRequest::getCookies()
14865 + Get previously set cookies. */
14866 +PHP_METHOD(HttpRequest, getCookies)
14868 + http_request_object_get_options_subr("cookies");
14872 +/* {{{ proto bool HttpRequest::enableCookies()
14873 + Enable automatic sending of received cookies. Note that customly set cookies will be sent anyway. */
14874 +PHP_METHOD(HttpRequest, enableCookies)
14877 + getObject(http_request_object, obj);
14878 + RETURN_SUCCESS(http_request_enable_cookies(obj->request));
14884 +/* {{{ proto bool HttpRequest::resetCookies([bool session_only = FALSE])
14885 + Reset all automatically received/sent cookies. Note that customly set cookies are not affected. */
14886 +PHP_METHOD(HttpRequest, resetCookies)
14888 + zend_bool session_only = 0;
14889 + getObject(http_request_object, obj);
14891 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &session_only)) {
14894 + RETURN_SUCCESS(http_request_reset_cookies(obj->request, session_only));
14898 +/* {{{ proto bool HttpRequest::flushCookies()
14899 + Flush internal cookies to the cookiestore file */
14900 +PHP_METHOD(HttpRequest, flushCookies)
14903 + getObject(http_request_object, obj);
14904 + RETURN_SUCCESS(http_request_flush_cookies(obj->request));
14909 +/* {{{ proto bool HttpRequest::setUrl(string url)
14910 + Set the request URL. */
14911 +PHP_METHOD(HttpRequest, setUrl)
14913 + char *URL = NULL;
14916 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
14920 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
14925 +/* {{{ proto string HttpRequest::getUrl()
14926 + Get the previously set request URL. */
14927 +PHP_METHOD(HttpRequest, getUrl)
14931 + if (return_value_used) {
14932 + RETURN_PROP(url);
14937 +/* {{{ proto bool HttpRequest::setMethod(int request_method)
14938 + Set the request method. */
14939 +PHP_METHOD(HttpRequest, setMethod)
14943 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
14947 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
14952 +/* {{{ proto int HttpRequest::getMethod()
14953 + Get the previously set request method. */
14954 +PHP_METHOD(HttpRequest, getMethod)
14958 + if (return_value_used) {
14959 + RETURN_PROP(method);
14964 +/* {{{ proto bool HttpRequest::setContentType(string content_type)
14965 + Set the content type the post request should have. */
14966 +PHP_METHOD(HttpRequest, setContentType)
14971 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
14976 + HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
14978 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("contentType")-1, ctype, ct_len TSRMLS_CC);
14983 +/* {{{ proto string HttpRequest::getContentType()
14984 + Get the previously content type. */
14985 +PHP_METHOD(HttpRequest, getContentType)
14989 + if (return_value_used) {
14990 + RETURN_PROP(contentType);
14995 +/* {{{ proto bool HttpRequest::setQueryData([mixed query_data])
14996 + Set the URL query parameters to use, overwriting previously set query parameters. */
14997 +PHP_METHOD(HttpRequest, setQueryData)
14999 + zval *qdata = NULL;
15001 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!", &qdata)) {
15005 + if ((!qdata) || Z_TYPE_P(qdata) == IS_NULL) {
15006 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, "", 0 TSRMLS_CC);
15007 + } else if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
15008 + char *query_data = NULL;
15010 + if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) {
15014 + zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data TSRMLS_CC);
15015 + efree(query_data);
15017 + zval *data = http_zsep(IS_STRING, qdata);
15019 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, Z_STRVAL_P(data), Z_STRLEN_P(data) TSRMLS_CC);
15020 + zval_ptr_dtor(&data);
15026 +/* {{{ proto string HttpRequest::getQueryData()
15027 + Get the current query data in form of an urlencoded query string. */
15028 +PHP_METHOD(HttpRequest, getQueryData)
15032 + if (return_value_used) {
15033 + RETURN_PROP(queryData);
15038 +/* {{{ proto bool HttpRequest::addQueryData(array query_params)
15039 + Add parameters to the query parameter list, leaving previously set unchanged. */
15040 +PHP_METHOD(HttpRequest, addQueryData)
15042 + zval *qdata, *old_qdata;
15043 + char *query_data = NULL;
15044 + size_t query_data_len = 0;
15046 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &qdata)) {
15050 + old_qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC);
15052 + 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)) {
15056 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data, query_data_len TSRMLS_CC);
15057 + efree(query_data);
15063 +/* {{{ proto bool HttpRequest::addPostFields(array post_data)
15064 + Adds POST data entries, leaving previously set unchanged, unless a post entry with the same name already exists. */
15065 +PHP_METHOD(HttpRequest, addPostFields)
15067 + zval *post_data, *old_post, *new_post;
15069 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &post_data)) {
15073 + if (zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
15074 + MAKE_STD_ZVAL(new_post);
15075 + array_init(new_post);
15076 + old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, 0 TSRMLS_CC);
15077 + if (Z_TYPE_P(old_post) == IS_ARRAY) {
15078 + array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
15080 + array_join(Z_ARRVAL_P(post_data), Z_ARRVAL_P(new_post), 0, 0);
15081 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, new_post TSRMLS_CC);
15082 + zval_ptr_dtor(&new_post);
15089 +/* {{{ proto bool HttpRequest::setPostFields([array post_data])
15090 + Set the POST data entries, overwriting previously set POST data. */
15091 +PHP_METHOD(HttpRequest, setPostFields)
15093 + zval *post, *post_data = NULL;
15095 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &post_data)) {
15099 + MAKE_STD_ZVAL(post);
15100 + array_init(post);
15101 + if (post_data && zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
15102 + array_copy(Z_ARRVAL_P(post_data), Z_ARRVAL_P(post));
15104 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, post TSRMLS_CC);
15105 + zval_ptr_dtor(&post);
15111 +/* {{{ proto array HttpRequest::getPostFields()
15112 + Get previously set POST data. */
15113 +PHP_METHOD(HttpRequest, getPostFields)
15117 + if (return_value_used) {
15118 + RETURN_PROP(postFields);
15123 +/* {{{ proto bool HttpRequest::setBody([string request_body_data])
15124 + Set request body to send, overwriting previously set request body. Don't forget to specify a content type. */
15125 +PHP_METHOD(HttpRequest, setBody)
15127 + char *raw_data = NULL;
15128 + int data_len = 0;
15130 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &raw_data, &data_len)) {
15138 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC);
15143 +/* {{{ proto bool HttpRequest::addBody(string request_body_data)
15144 + Add request body data, leaving previously set request body data unchanged. */
15145 +PHP_METHOD(HttpRequest, addBody)
15150 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &raw_data, &data_len)) {
15155 + zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC);
15157 + if (Z_STRLEN_P(data)) {
15158 + Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1);
15159 + Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0';
15160 + memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, raw_data, data_len);
15162 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC);
15170 +/* {{{ proto string HttpRequest::getBody()
15171 + Get previously set request body data. */
15172 +PHP_METHOD(HttpRequest, getBody)
15176 + if (return_value_used) {
15177 + RETURN_PROP(requestBody);
15182 +/* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
15183 + Add a file to the POST request, leaving previously set files unchanged. */
15184 +PHP_METHOD(HttpRequest, addPostFile)
15186 + zval *entry, *old_post, *new_post;
15187 + char *name, *file, *type = NULL;
15188 + int name_len, file_len, type_len = 0;
15190 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
15195 + HTTP_CHECK_CONTENT_TYPE(type, RETURN_FALSE);
15197 + type = "application/x-octetstream";
15198 + type_len = sizeof("application/x-octetstream") - 1;
15201 + MAKE_STD_ZVAL(entry);
15202 + array_init(entry);
15204 + add_assoc_stringl(entry, "name", name, name_len, 1);
15205 + add_assoc_stringl(entry, "type", type, type_len, 1);
15206 + add_assoc_stringl(entry, "file", file, file_len, 1);
15208 + MAKE_STD_ZVAL(new_post);
15209 + array_init(new_post);
15210 + old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, 0 TSRMLS_CC);
15211 + if (Z_TYPE_P(old_post) == IS_ARRAY) {
15212 + array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
15214 + add_next_index_zval(new_post, entry);
15215 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, new_post TSRMLS_CC);
15216 + zval_ptr_dtor(&new_post);
15222 +/* {{{ proto bool HttpRequest::setPostFiles([array post_files])
15223 + Set files to post, overwriting previously set post files. */
15224 +PHP_METHOD(HttpRequest, setPostFiles)
15226 + zval *files = NULL, *post;
15228 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!/", &files)) {
15232 + MAKE_STD_ZVAL(post);
15233 + array_init(post);
15234 + if (files && (Z_TYPE_P(files) == IS_ARRAY)) {
15235 + array_copy(Z_ARRVAL_P(files), Z_ARRVAL_P(post));
15237 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, post TSRMLS_CC);
15238 + zval_ptr_dtor(&post);
15244 +/* {{{ proto array HttpRequest::getPostFiles()
15245 + Get all previously added POST files. */
15246 +PHP_METHOD(HttpRequest, getPostFiles)
15250 + if (return_value_used) {
15251 + RETURN_PROP(postFiles);
15256 +/* {{{ proto bool HttpRequest::setPutFile([string file])
15257 + Set file to put. Affects only PUT requests. */
15258 +PHP_METHOD(HttpRequest, setPutFile)
15261 + int file_len = 0;
15263 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &file, &file_len)) {
15267 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putFile")-1, file, file_len TSRMLS_CC);
15272 +/* {{{ proto string HttpRequest::getPutFile()
15273 + Get previously set put file. */
15274 +PHP_METHOD(HttpRequest, getPutFile)
15278 + if (return_value_used) {
15279 + RETURN_PROP(putFile);
15284 +/* {{{ proto bool HttpRequest::setPutData([string put_data])
15285 + Set PUT data to send, overwriting previously set PUT data. */
15286 +PHP_METHOD(HttpRequest, setPutData)
15288 + char *put_data = NULL;
15289 + int data_len = 0;
15291 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &put_data, &data_len)) {
15299 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC);
15304 +/* {{{ proto bool HttpRequest::addPutData(string put_data)
15305 + Add PUT data, leaving previously set PUT data unchanged. */
15306 +PHP_METHOD(HttpRequest, addPutData)
15311 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &put_data, &data_len)) {
15316 + zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC);
15318 + if (Z_STRLEN_P(data)) {
15319 + Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1);
15320 + Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0';
15321 + memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, put_data, data_len);
15323 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC);
15331 +/* {{{ proto string HttpRequest::getPutData()
15332 + Get previously set PUT data. */
15333 +PHP_METHOD(HttpRequest, getPutData)
15337 + if (return_value_used) {
15338 + RETURN_PROP(putData);
15343 +/* {{{ proto array HttpRequest::getResponseData()
15344 + Get all response data after the request has been sent. */
15345 +PHP_METHOD(HttpRequest, getResponseData)
15349 + if (return_value_used) {
15352 + zval *headers, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15354 + if (Z_TYPE_P(message) == IS_OBJECT) {
15355 + getObjectEx(http_message_object, msg, message);
15357 + array_init(return_value);
15359 + MAKE_STD_ZVAL(headers);
15360 + array_init(headers);
15361 + zend_hash_copy(Z_ARRVAL_P(headers), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
15362 + add_assoc_zval(return_value, "headers", headers);
15364 + phpstr_data(PHPSTR(msg->message), &body, &body_len);
15365 + add_assoc_stringl(return_value, "body", body, body_len, 0);
15371 +/* {{{ proto mixed HttpRequest::getResponseHeader([string name])
15372 + Get response header(s) after the request has been sent. */
15373 +PHP_METHOD(HttpRequest, getResponseHeader)
15375 + if (return_value_used) {
15377 + char *header_name = NULL;
15378 + int header_len = 0;
15380 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) {
15381 + zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15383 + if (Z_TYPE_P(message) == IS_OBJECT) {
15384 + getObjectEx(http_message_object, msg, message);
15386 + if (header_len) {
15387 + if ((header = http_message_header_ex(msg->message, pretty_key(header_name, header_len, 1, 1), header_len + 1, 0))) {
15388 + RETURN_ZVAL(header, 1, 1);
15391 + array_init(return_value);
15392 + zend_hash_copy(Z_ARRVAL_P(return_value), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
15402 +/* {{{ proto array HttpRequest::getResponseCookies([int flags[, array allowed_extras]])
15403 + Get response cookie(s) after the request has been sent. */
15404 +PHP_METHOD(HttpRequest, getResponseCookies)
15406 + if (return_value_used) {
15408 + zval *allowed_extras_array = NULL;
15410 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|la!", &flags, &allowed_extras_array)) {
15412 + HashKey key = initHashKey(0);
15413 + char **allowed_extras = NULL;
15414 + zval **header = NULL, **entry = NULL, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15415 + HashPosition pos, pos1, pos2;
15417 + if (Z_TYPE_P(message) == IS_OBJECT) {
15418 + getObjectEx(http_message_object, msg, message);
15420 + array_init(return_value);
15422 + if (allowed_extras_array) {
15423 + allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
15424 + FOREACH_VAL(pos, allowed_extras_array, entry) {
15425 + zval *data = http_zsep(IS_STRING, *entry);
15426 + allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
15427 + zval_ptr_dtor(&data);
15431 + FOREACH_HASH_KEYVAL(pos1, &msg->message->hdrs, key, header) {
15432 + if (key.type == HASH_KEY_IS_STRING && !strcasecmp(key.str, "Set-Cookie")) {
15433 + http_cookie_list list;
15435 + if (Z_TYPE_PP(header) == IS_ARRAY) {
15436 + zval **single_header;
15438 + FOREACH_VAL(pos2, *header, single_header) {
15439 + zval *data = http_zsep(IS_STRING, *single_header);
15441 + if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) {
15444 + MAKE_STD_ZVAL(cookie);
15445 + object_init(cookie);
15446 + http_cookie_list_tostruct(&list, cookie);
15447 + add_next_index_zval(return_value, cookie);
15448 + http_cookie_list_dtor(&list);
15450 + zval_ptr_dtor(&data);
15453 + zval *data = http_zsep(IS_STRING, *header);
15454 + if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) {
15457 + MAKE_STD_ZVAL(cookie);
15458 + object_init(cookie);
15459 + http_cookie_list_tostruct(&list, cookie);
15460 + add_next_index_zval(return_value, cookie);
15461 + http_cookie_list_dtor(&list);
15463 + zval_ptr_dtor(&data);
15468 + if (allowed_extras) {
15469 + for (i = 0; allowed_extras[i]; ++i) {
15470 + efree(allowed_extras[i]);
15472 + efree(allowed_extras);
15483 +/* {{{ proto string HttpRequest::getResponseBody()
15484 + Get the response body after the request has been sent. */
15485 +PHP_METHOD(HttpRequest, getResponseBody)
15489 + if (return_value_used) {
15490 + zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15492 + if (Z_TYPE_P(message) == IS_OBJECT) {
15493 + getObjectEx(http_message_object, msg, message);
15494 + RETURN_PHPSTR_DUP(&msg->message->body);
15502 +/* {{{ proto int HttpRequest::getResponseCode()
15503 + Get the response code after the request has been sent. */
15504 +PHP_METHOD(HttpRequest, getResponseCode)
15508 + if (return_value_used) {
15509 + RETURN_PROP(responseCode);
15514 +/* {{{ proto string HttpRequest::getResponseStatus()
15515 + Get the response status (i.e. the string after the response code) after the message has been sent. */
15516 +PHP_METHOD(HttpRequest, getResponseStatus)
15520 + if (return_value_used) {
15521 + RETURN_PROP(responseStatus);
15526 +/* {{{ proto mixed HttpRequest::getResponseInfo([string name])
15527 + Get response info after the request has been sent. */
15528 +PHP_METHOD(HttpRequest, getResponseInfo)
15530 + if (return_value_used) {
15531 + zval *info, **infop;
15532 + char *info_name = NULL;
15533 + int info_len = 0;
15535 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) {
15539 + info = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, 0 TSRMLS_CC);
15541 + if (Z_TYPE_P(info) != IS_ARRAY) {
15545 + if (info_len && info_name) {
15546 + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void *) &infop)) {
15547 + RETURN_ZVAL(*infop, 1, 0);
15549 + http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Could not find response info named %s", info_name);
15553 + RETURN_ZVAL(info, 1, 0);
15559 +/* {{{ proto HttpMessage HttpRequest::getResponseMessage()
15560 + Get the full response as HttpMessage object after the request has been sent. */
15561 +PHP_METHOD(HttpRequest, getResponseMessage)
15566 + SET_EH_THROW_HTTP();
15567 + message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15568 + if (Z_TYPE_P(message) == IS_OBJECT) {
15569 + RETVAL_OBJECT(message, 1);
15571 + http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpRequest does not contain a response message");
15578 +/* {{{ proto HttpMessage HttpRequest::getRequestMessage()
15579 + Get sent HTTP message. */
15580 +PHP_METHOD(HttpRequest, getRequestMessage)
15584 + if (return_value_used) {
15585 + http_message *msg;
15586 + getObject(http_request_object, obj);
15588 + SET_EH_THROW_HTTP();
15589 + if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) {
15590 + RETVAL_OBJVAL(http_request_object_message(getThis(), msg), 0);
15597 +/* {{{ proto string HttpRequest::getRawRequestMessage()
15598 + Get sent HTTP message. */
15599 +PHP_METHOD(HttpRequest, getRawRequestMessage)
15603 + if (return_value_used) {
15604 + getObject(http_request_object, obj);
15606 + RETURN_PHPSTR_DUP(&obj->request->conv.request);
15611 +/* {{{ proto string HttpRequest::getRawResponseMessage()
15612 + Get the entire HTTP response. */
15613 +PHP_METHOD(HttpRequest, getRawResponseMessage)
15617 + if (return_value_used) {
15618 + getObject(http_request_object, obj);
15620 + RETURN_PHPSTR_DUP(&obj->request->conv.response);
15625 +/* {{{ proto HttpMessage HttpRequest::getHistory()
15626 + Get all sent requests and received responses as an HttpMessage object. */
15627 +PHP_METHOD(HttpRequest, getHistory)
15631 + if (return_value_used) {
15634 + SET_EH_THROW_HTTP();
15635 + hist = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
15636 + if (Z_TYPE_P(hist) == IS_OBJECT) {
15637 + RETVAL_OBJECT(hist, 1);
15639 + http_error(HE_WARNING, HTTP_E_RUNTIME, "The history is empty");
15646 +/* {{{ proto void HttpRequest::clearHistory()
15647 + Clear the history. */
15648 +PHP_METHOD(HttpRequest, clearHistory)
15653 + MAKE_STD_ZVAL(hist);
15655 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
15656 + zval_ptr_dtor(&hist);
15661 +/* {{{ proto string HttpRequest::getMessageClass()
15662 + Get the message class name. */
15663 +PHP_METHOD(HttpRequest, getMessageClass)
15667 + if (return_value_used) {
15668 + RETURN_PROP("messageClass");
15673 +/* {{{ proto void setMessageClass(string class_name)
15674 + Set the message class name. */
15675 +PHP_METHOD(HttpRequest, setMessageClass)
15680 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &cn, &cl)) {
15681 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, cn, cl TSRMLS_CC);
15686 +/* {{{ proto HttpMessage HttpRequest::send()
15687 + Send the HTTP request. */
15688 +PHP_METHOD(HttpRequest, send)
15690 + getObject(http_request_object, obj);
15694 + SET_EH_THROW_HTTP();
15699 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool");
15700 + } else if (SUCCESS == http_request_object_requesthandler(obj, getThis())) {
15701 + http_request_exec(obj->request);
15702 + if (SUCCESS == http_request_object_responsehandler(obj, getThis())) {
15703 + RETVAL_OBJECT(zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC), 1);
15711 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
15714 + * Local variables:
15716 + * c-basic-offset: 4
15718 + * vim600: noet sw=4 ts=4 fdm=marker
15719 + * vim<600: noet sw=4 ts=4
15723 +++ b/ext/http/http_request_pool_api.c
15726 + +--------------------------------------------------------------------+
15728 + +--------------------------------------------------------------------+
15729 + | Redistribution and use in source and binary forms, with or without |
15730 + | modification, are permitted provided that the conditions mentioned |
15731 + | in the accompanying LICENSE file are met. |
15732 + +--------------------------------------------------------------------+
15733 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
15734 + +--------------------------------------------------------------------+
15737 +/* $Id: http_request_pool_api.c 292841 2009-12-31 08:48:57Z mike $ */
15739 +#define HTTP_WANT_CURL
15740 +#define HTTP_WANT_EVENT
15741 +#include "php_http.h"
15743 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
15745 +#include "php_http_api.h"
15746 +#include "php_http_exception_object.h"
15747 +#include "php_http_persistent_handle_api.h"
15748 +#include "php_http_request_api.h"
15749 +#include "php_http_request_object.h"
15750 +#include "php_http_request_pool_api.h"
15751 +#include "php_http_requestpool_object.h"
15753 +#ifndef HTTP_DEBUG_REQPOOLS
15754 +# define HTTP_DEBUG_REQPOOLS 0
15757 +#ifdef HTTP_HAVE_EVENT
15758 +typedef struct _http_request_pool_event_t {
15759 + struct event evnt;
15760 + http_request_pool *pool;
15761 +} http_request_pool_event;
15763 +static void http_request_pool_timeout_callback(int socket, short action, void *event_data);
15764 +static void http_request_pool_event_callback(int socket, short action, void *event_data);
15765 +static int http_request_pool_socket_callback(CURL *easy, curl_socket_t s, int action, void *, void *);
15766 +static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data);
15769 +static int http_request_pool_compare_handles(void *h1, void *h2);
15771 +PHP_MINIT_FUNCTION(http_request_pool)
15773 + if (SUCCESS != http_persistent_handle_provide("http_request_pool", curl_multi_init, (http_persistent_handle_dtor) curl_multi_cleanup, NULL)) {
15779 +#ifdef HTTP_HAVE_EVENT
15780 +PHP_RINIT_FUNCTION(http_request_pool)
15782 + if (!HTTP_G->request.pool.event.base && !(HTTP_G->request.pool.event.base = event_init())) {
15790 +/* {{{ http_request_pool *http_request_pool_init(http_request_pool *) */
15791 +PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC)
15793 + zend_bool free_pool;
15795 +#if HTTP_DEBUG_REQPOOLS
15796 + fprintf(stderr, "Initializing request pool %p\n", pool);
15799 + if ((free_pool = (!pool))) {
15800 + pool = emalloc(sizeof(http_request_pool));
15804 + if (SUCCESS != http_persistent_handle_acquire("http_request_pool", &pool->ch)) {
15811 + TSRMLS_SET_CTX(pool->tsrm_ls);
15813 +#ifdef HTTP_HAVE_EVENT
15814 + pool->timeout = ecalloc(1, sizeof(struct event));
15815 + curl_multi_setopt(pool->ch, CURLMOPT_SOCKETDATA, pool);
15816 + curl_multi_setopt(pool->ch, CURLMOPT_SOCKETFUNCTION, http_request_pool_socket_callback);
15817 + curl_multi_setopt(pool->ch, CURLMOPT_TIMERDATA, pool);
15818 + curl_multi_setopt(pool->ch, CURLMOPT_TIMERFUNCTION, http_request_pool_timer_callback);
15821 + pool->unfinished = 0;
15822 + zend_llist_init(&pool->finished, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0);
15823 + zend_llist_init(&pool->handles, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0);
15825 +#if HTTP_DEBUG_REQPOOLS
15826 + fprintf(stderr, "Initialized request pool %p\n", pool);
15833 +/* {{{ STATUS http_request_pool_attach(http_request_pool *, zval *) */
15834 +PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request)
15837 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
15839 + getObjectEx(http_request_object, req, request);
15841 +#if HTTP_DEBUG_REQPOOLS
15842 + fprintf(stderr, "Attaching HttpRequest(#%d) %p to pool %p\n", Z_OBJ_HANDLE_P(request), req, pool);
15846 + 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");
15847 + } else if (SUCCESS != http_request_object_requesthandler(req, request)) {
15848 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not initialize HttpRequest object(#%d) for attaching to the HttpRequestPool", Z_OBJ_HANDLE_P(request));
15850 + CURLMcode code = curl_multi_add_handle(pool->ch, req->request->ch);
15852 + if (CURLM_OK != code) {
15853 + 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));
15855 + req->pool = pool;
15857 + ZVAL_ADDREF(request);
15858 + zend_llist_add_element(&pool->handles, &request);
15859 + ++pool->unfinished;
15861 +#if HTTP_DEBUG_REQPOOLS
15862 + fprintf(stderr, "> %d HttpRequests attached to pool %p\n", zend_llist_count(&pool->handles), pool);
15871 +/* {{{ STATUS http_request_pool_detach(http_request_pool *, zval *) */
15872 +PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request)
15876 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
15878 + getObjectEx(http_request_object, req, request);
15880 +#if HTTP_DEBUG_REQPOOLS
15881 + fprintf(stderr, "Detaching HttpRequest(#%d) %p from pool %p\n", Z_OBJ_HANDLE_P(request), req, pool);
15884 + if (!req->pool) {
15885 + /* not attached to any pool */
15886 +#if HTTP_DEBUG_REQPOOLS
15887 + fprintf(stderr, "HttpRequest object(#%d) %p is not attached to any HttpRequestPool\n", Z_OBJ_HANDLE_P(request), req);
15889 + } else if (req->pool != pool) {
15890 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is not attached to this HttpRequestPool", Z_OBJ_HANDLE_P(request));
15891 + } else if (req->request->_in_progress_cb) {
15892 + 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));
15893 + } else if (CURLM_OK != (code = curl_multi_remove_handle(pool->ch, req->request->ch))) {
15894 + 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));
15896 + req->pool = NULL;
15897 + zend_llist_del_element(&pool->finished, request, http_request_pool_compare_handles);
15898 + zend_llist_del_element(&pool->handles, request, http_request_pool_compare_handles);
15900 +#if HTTP_DEBUG_REQPOOLS
15901 + fprintf(stderr, "> %d HttpRequests remaining in pool %p\n", zend_llist_count(&pool->handles), pool);
15910 +/* {{{ void http_request_pool_apply(http_request_pool *, http_request_pool_apply_func) */
15911 +PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb)
15913 + int count = zend_llist_count(&pool->handles);
15917 + zend_llist_position pos;
15918 + zval **handle, **handles = emalloc(count * sizeof(zval *));
15920 + for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) {
15921 + handles[i++] = *handle;
15924 + /* should never happen */
15925 + if (i != count) {
15926 + zend_error(E_ERROR, "number of fetched request handles do not match overall count");
15930 + for (i = 0; i < count; ++i) {
15931 + if (cb(pool, handles[i])) {
15940 +/* {{{ void http_request_pool_apply_with_arg(http_request_pool *, http_request_pool_apply_with_arg_func, void *) */
15941 +PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg)
15943 + int count = zend_llist_count(&pool->handles);
15947 + zend_llist_position pos;
15948 + zval **handle, **handles = emalloc(count * sizeof(zval *));
15950 + for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) {
15951 + handles[i++] = *handle;
15954 + /* should never happen */
15955 + if (i != count) {
15956 + zend_error(E_ERROR, "number of fetched request handles do not match overall count");
15960 + for (i = 0; i < count; ++i) {
15961 + if (cb(pool, handles[i], arg)) {
15970 +/* {{{ void http_request_pool_detach_all(http_request_pool *) */
15971 +PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool)
15973 +#if HTTP_DEBUG_REQPOOLS
15974 + fprintf(stderr, "Detaching %d requests from pool %p\n", zend_llist_count(&pool->handles), pool);
15976 + http_request_pool_apply(pool, _http_request_pool_detach);
15980 +/* {{{ STATUS http_request_pool_send(http_request_pool *) */
15981 +PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool)
15983 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
15985 +#if HTTP_DEBUG_REQPOOLS
15986 + fprintf(stderr, "Attempt to send %d requests of pool %p\n", zend_llist_count(&pool->handles), pool);
15989 +#ifdef HTTP_HAVE_EVENT
15990 + if (pool->useevents) {
15992 +#if HTTP_DEBUG_REQPOOLS
15993 + fprintf(stderr, "& Starting event dispatcher of pool %p\n", pool);
15995 + event_base_dispatch(HTTP_G->request.pool.event.base);
15996 + } while (pool->unfinished);
16000 + while (http_request_pool_perform(pool)) {
16001 + if (SUCCESS != http_request_pool_select(pool)) {
16003 + /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */
16004 + http_error_ex(HE_WARNING, HTTP_E_SOCKET, "WinSock error: %d", WSAGetLastError());
16006 + http_error(HE_WARNING, HTTP_E_SOCKET, strerror(errno));
16013 +#if HTTP_DEBUG_REQPOOLS
16014 + fprintf(stderr, "Finished sending %d HttpRequests of pool %p (still unfinished: %d)\n", zend_llist_count(&pool->handles), pool, pool->unfinished);
16021 +/* {{{ void http_request_pool_dtor(http_request_pool *) */
16022 +PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool)
16024 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16026 +#if HTTP_DEBUG_REQPOOLS
16027 + fprintf(stderr, "Destructing request pool %p\n", pool);
16030 +#ifdef HTTP_HAVE_EVENT
16031 + efree(pool->timeout);
16034 + http_request_pool_detach_all(pool);
16036 + pool->unfinished = 0;
16037 + zend_llist_clean(&pool->finished);
16038 + zend_llist_clean(&pool->handles);
16039 + http_persistent_handle_release("http_request_pool", &pool->ch);
16044 +# define SELECT_ERROR SOCKET_ERROR
16046 +# define SELECT_ERROR -1
16049 +/* {{{ STATUS http_request_pool_select(http_request_pool *) */
16050 +PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool)
16052 + return http_request_pool_select_ex(pool, NULL);
16056 +/* {{{ STATUS http_request_pool_select_ex(http_request_pool *, struct timeval *) */
16057 +PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout)
16061 + struct timeval timeout;
16063 +#ifdef HTTP_HAVE_EVENT
16064 + if (pool->useevents) {
16065 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16066 + http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks");
16071 + if (custom_timeout && timerisset(custom_timeout)) {
16072 + timeout = *custom_timeout;
16074 + http_request_pool_timeout(pool, &timeout);
16081 + if (CURLM_OK == curl_multi_fdset(pool->ch, &R, &W, &E, &MAX)) {
16083 + http_sleep((double) timeout.tv_sec + (double) (timeout.tv_usec / HTTP_MCROSEC));
16085 + } else if (SELECT_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) {
16093 +/* {{{ int http_request_pool_perform(http_request_pool *) */
16094 +PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool)
16096 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16098 +#ifdef HTTP_HAVE_EVENT
16099 + if (pool->useevents) {
16100 + http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks");
16105 + while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(pool->ch, &pool->unfinished));
16107 +#if HTTP_DEBUG_REQPOOLS
16108 + fprintf(stderr, "%u unfinished requests of pool %p remaining\n", pool->unfinished, pool);
16111 + http_request_pool_responsehandler(pool);
16113 + return pool->unfinished;
16117 +/* {{{ void http_request_pool_responsehandler(http_request_pool *) */
16118 +void _http_request_pool_responsehandler(http_request_pool *pool)
16121 + int remaining = 0;
16122 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16125 + msg = curl_multi_info_read(pool->ch, &remaining);
16126 + if (msg && CURLMSG_DONE == msg->msg) {
16127 + if (CURLE_OK != msg->data.result) {
16128 + http_request_storage *st = http_request_storage_get(msg->easy_handle);
16129 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(msg->data.result), st?st->errorbuffer:"", st?st->url:"");
16131 + http_request_pool_apply_with_arg(pool, _http_request_pool_apply_responsehandler, msg->easy_handle);
16133 + } while (remaining);
16137 +/* {{{ int http_request_pool_apply_responsehandler(http_request_pool *, zval *, void *) */
16138 +int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch)
16141 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16143 + getObjectEx(http_request_object, obj, req);
16145 + if ((!ch) || obj->request->ch == (CURL *) ch) {
16147 +#if HTTP_DEBUG_REQPOOLS
16148 + fprintf(stderr, "Fetching data from HttpRequest(#%d) %p of pool %p\n", Z_OBJ_HANDLE_P(req), obj, obj->pool);
16151 + ZVAL_ADDREF(req);
16152 + zend_llist_add_element(&obj->pool->finished, &req);
16153 + http_request_object_responsehandler(obj, req);
16160 +/* {{{ struct timeval *_http_request_pool_timeout(http_request_pool *, struct timeval *) */
16161 +struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout)
16163 +#ifdef HAVE_CURL_MULTI_TIMEOUT
16164 + long max_tout = 1000;
16166 + if ((CURLM_OK == curl_multi_timeout(pool->ch, &max_tout)) && (max_tout > 0)) {
16167 + timeout->tv_sec = max_tout / 1000;
16168 + timeout->tv_usec = (max_tout % 1000) * 1000;
16171 + timeout->tv_sec = 0;
16172 + timeout->tv_usec = 1000;
16173 +#ifdef HAVE_CURL_MULTI_TIMEOUT
16177 +#if HTTP_DEBUG_REQPOOLS
16178 + fprintf(stderr, "Calculating timeout (%lu, %lu) of pool %p\n", (ulong) timeout->tv_sec, (ulong) timeout->tv_usec, pool);
16187 +/* {{{ static int http_request_pool_compare_handles(void *, void *) */
16188 +static int http_request_pool_compare_handles(void *h1, void *h2)
16190 + return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
16194 +#ifdef HTTP_HAVE_EVENT
16195 +/* {{{ static void http_request_pool_timeout_callback(int, short, void *) */
16196 +static void http_request_pool_timeout_callback(int socket, short action, void *event_data)
16198 + http_request_pool *pool = event_data;
16200 + if (pool->useevents) {
16202 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16204 +#if HTTP_DEBUG_REQPOOLS
16205 + fprintf(stderr, "Timeout occurred of pool %p\n", pool);
16208 + while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket(pool->ch, CURL_SOCKET_TIMEOUT, &pool->unfinished)));
16210 + if (CURLM_OK != rc) {
16211 + http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc));
16214 + http_request_pool_responsehandler(pool);
16219 +/* {{{ static void http_request_pool_event_callback(int, short, void *) */
16220 +static void http_request_pool_event_callback(int socket, short action, void *event_data)
16222 + http_request_pool_event *ev = event_data;
16223 + http_request_pool *pool = ev->pool;
16225 + if (pool->useevents) {
16226 + CURLMcode rc = CURLE_OK;
16227 + TSRMLS_FETCH_FROM_CTX(ev->pool->tsrm_ls);
16229 +#if HTTP_DEBUG_REQPOOLS
16231 + static const char event_strings[][20] = {"NONE","TIMEOUT","READ","TIMEOUT|READ","WRITE","TIMEOUT|WRITE","READ|WRITE","TIMEOUT|READ|WRITE","SIGNAL"};
16232 + fprintf(stderr, "Event on socket %d (%s) event %p of pool %p\n", socket, event_strings[action], ev, pool);
16236 + /* don't use 'ev' below this loop as it might 've been freed in the socket callback */
16238 +#ifdef HAVE_CURL_MULTI_SOCKET_ACTION
16239 + switch (action & (EV_READ|EV_WRITE)) {
16241 + rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN, &pool->unfinished);
16244 + rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_OUT, &pool->unfinished);
16246 + case EV_READ|EV_WRITE:
16247 + rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN|CURL_CSELECT_OUT, &pool->unfinished);
16250 + http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown event %d", (int) action);
16254 + rc = curl_multi_socket(pool->ch, socket, &pool->unfinished);
16256 + } while (CURLM_CALL_MULTI_PERFORM == rc);
16259 + case CURLM_BAD_SOCKET:
16261 + fprintf(stderr, "!!! Bad socket: %d (%d)\n", socket, (int) action);
16266 + http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc));
16270 + http_request_pool_responsehandler(pool);
16272 + /* remove timeout if there are no transfers left */
16273 + if (!pool->unfinished && event_initialized(pool->timeout) && event_pending(pool->timeout, EV_TIMEOUT, NULL)) {
16274 + event_del(pool->timeout);
16275 +#if HTTP_DEBUG_REQPOOLS
16276 + fprintf(stderr, "Removed timeout of pool %p\n", pool);
16283 +/* {{{ static int http_request_pool_socket_callback(CURL *, curl_socket_t, int, void *, void *) */
16284 +static int http_request_pool_socket_callback(CURL *easy, curl_socket_t sock, int action, void *socket_data, void *assign_data)
16286 + http_request_pool *pool = socket_data;
16288 + if (pool->useevents) {
16289 + int events = EV_PERSIST;
16290 + http_request_pool_event *ev = assign_data;
16291 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16294 + ev = ecalloc(1, sizeof(http_request_pool_event));
16296 + curl_multi_assign(pool->ch, sock, ev);
16297 + event_base_set(HTTP_G->request.pool.event.base, &ev->evnt);
16299 + event_del(&ev->evnt);
16302 +#if HTTP_DEBUG_REQPOOLS
16304 + static const char action_strings[][8] = {"NONE", "IN", "OUT", "INOUT", "REMOVE"};
16306 + curl_easy_getinfo(easy, CURLINFO_PRIVATE, &r);
16307 + fprintf(stderr, "Callback on socket %2d (%8s) event %p of pool %p (%d)\n", (int) sock, action_strings[action], ev, pool, pool->unfinished);
16311 + switch (action) {
16312 + case CURL_POLL_IN:
16313 + events |= EV_READ;
16315 + case CURL_POLL_OUT:
16316 + events |= EV_WRITE;
16318 + case CURL_POLL_INOUT:
16319 + events |= EV_READ|EV_WRITE;
16322 + case CURL_POLL_REMOVE:
16324 + case CURL_POLL_NONE:
16328 + http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown socket action %d", action);
16332 + event_set(&ev->evnt, sock, events, http_request_pool_event_callback, ev);
16333 + event_add(&ev->evnt, NULL);
16340 +/* {{{ static void http_request_pool_timer_callback(CURLM *, long, void*) */
16341 +static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data)
16343 + http_request_pool *pool = timer_data;
16345 + if (pool->useevents) {
16346 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16347 + struct timeval timeout;
16349 + if (!event_initialized(pool->timeout)) {
16350 + event_set(pool->timeout, -1, 0, http_request_pool_timeout_callback, pool);
16351 + event_base_set(HTTP_G->request.pool.event.base, pool->timeout);
16352 + } else if (event_pending(pool->timeout, EV_TIMEOUT, NULL)) {
16353 + event_del(pool->timeout);
16356 + if (timeout_ms > 0) {
16357 + timeout.tv_sec = timeout_ms / 1000;
16358 + timeout.tv_usec = (timeout_ms % 1000) * 1000;
16360 + http_request_pool_timeout(pool, &timeout);
16363 + event_add(pool->timeout, &timeout);
16365 +#if HTTP_DEBUG_REQPOOLS
16366 + fprintf(stderr, "Updating timeout %lu (%lu, %lu) of pool %p\n", (ulong) timeout_ms, (ulong) timeout.tv_sec, (ulong) timeout.tv_usec, pool);
16371 +#endif /* HTTP_HAVE_EVENT */
16373 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
16377 + * Local variables:
16379 + * c-basic-offset: 4
16381 + * vim600: noet sw=4 ts=4 fdm=marker
16382 + * vim<600: noet sw=4 ts=4
16386 +++ b/ext/http/http_requestdatashare_object.c
16389 + +--------------------------------------------------------------------+
16391 + +--------------------------------------------------------------------+
16392 + | Redistribution and use in source and binary forms, with or without |
16393 + | modification, are permitted provided that the conditions mentioned |
16394 + | in the accompanying LICENSE file are met. |
16395 + +--------------------------------------------------------------------+
16396 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
16397 + +--------------------------------------------------------------------+
16400 +/* $Id: http_requestdatashare_object.c 300299 2010-06-09 06:23:16Z mike $ */
16402 +#define HTTP_WANT_CURL
16403 +#include "php_http.h"
16405 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
16407 +#include "zend_interfaces.h"
16409 +#include "php_http_api.h"
16410 +#include "php_http_exception_object.h"
16411 +#include "php_http_request_api.h"
16412 +#include "php_http_request_object.h"
16413 +#include "php_http_request_datashare_api.h"
16414 +#include "php_http_requestdatashare_object.h"
16416 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestDataShare, method, 0, req_args)
16417 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestDataShare, method, 0)
16418 +#define HTTP_RSHARE_ME(method, visibility) PHP_ME(HttpRequestDataShare, method, HTTP_ARGS(HttpRequestDataShare, method), visibility)
16420 +#if defined(HAVE_SPL) && !defined(WONKY)
16421 +/* SPL doesn't install its headers */
16422 +extern PHPAPI zend_class_entry *spl_ce_Countable;
16425 +HTTP_EMPTY_ARGS(__destruct);
16426 +HTTP_EMPTY_ARGS(count);
16428 +HTTP_BEGIN_ARGS(attach, 1)
16429 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16431 +HTTP_BEGIN_ARGS(detach, 1)
16432 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16435 +HTTP_EMPTY_ARGS(reset);
16437 +HTTP_BEGIN_ARGS(factory, 0)
16438 + HTTP_ARG_VAL(global, 0)
16439 + HTTP_ARG_VAL(class_name, 0)
16443 +HTTP_BEGIN_ARGS(singleton, 0)
16444 + HTTP_ARG_VAL(global, 0)
16449 +#define http_requestdatashare_object_read_prop _http_requestdatashare_object_read_prop
16450 +static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC);
16451 +#define http_requestdatashare_object_write_prop _http_requestdatashare_object_write_prop
16452 +static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC);
16453 +#define http_requestdatashare_instantiate(t, g) _http_requestdatashare_instantiate((t), (g) TSRMLS_CC)
16454 +static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC);
16456 +#define THIS_CE http_requestdatashare_object_ce
16457 +zend_class_entry *http_requestdatashare_object_ce;
16458 +zend_function_entry http_requestdatashare_object_fe[] = {
16459 + HTTP_RSHARE_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
16460 + HTTP_RSHARE_ME(count, ZEND_ACC_PUBLIC)
16461 + HTTP_RSHARE_ME(attach, ZEND_ACC_PUBLIC)
16462 + HTTP_RSHARE_ME(detach, ZEND_ACC_PUBLIC)
16463 + HTTP_RSHARE_ME(reset, ZEND_ACC_PUBLIC)
16464 + HTTP_RSHARE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
16466 + HTTP_RSHARE_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
16468 + EMPTY_FUNCTION_ENTRY
16470 +static zend_object_handlers http_requestdatashare_object_handlers;
16472 +PHP_MINIT_FUNCTION(http_requestdatashare_object)
16474 + HTTP_REGISTER_CLASS_EX(HttpRequestDataShare, http_requestdatashare_object, NULL, 0);
16475 + http_requestdatashare_object_handlers.clone_obj = NULL;
16476 + http_requestdatashare_object_handlers.read_property = http_requestdatashare_object_read_prop;
16477 + http_requestdatashare_object_handlers.write_property = http_requestdatashare_object_write_prop;
16479 +#if defined(HAVE_SPL) && !defined(WONKY)
16480 + zend_class_implements(http_requestdatashare_object_ce TSRMLS_CC, 1, spl_ce_Countable);
16483 + zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
16484 + zend_declare_property_bool(THIS_CE, ZEND_STRS("cookie")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16485 + zend_declare_property_bool(THIS_CE, ZEND_STRS("dns")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16486 + zend_declare_property_bool(THIS_CE, ZEND_STRS("ssl")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16487 + zend_declare_property_bool(THIS_CE, ZEND_STRS("connect")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16492 +zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC)
16494 + return http_requestdatashare_object_new_ex(ce, NULL, NULL);
16497 +zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC)
16499 + zend_object_value ov;
16500 + http_requestdatashare_object *o;
16502 + o = ecalloc(1, sizeof(http_requestdatashare_object));
16506 + o->share = share;
16508 + o->share = http_request_datashare_new();
16515 + ALLOC_HASHTABLE(OBJ_PROP(o));
16516 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
16517 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
16519 + ov.handle = putObject(http_requestdatashare_object, o);
16520 + ov.handlers = &http_requestdatashare_object_handlers;
16525 +void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC)
16527 + http_requestdatashare_object *o = (http_requestdatashare_object *) object;
16529 + if (!o->share->persistent) {
16530 + http_request_datashare_free(&o->share);
16535 +static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC)
16537 + if (type == BP_VAR_W && zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)) {
16538 + zend_error(E_ERROR, "Cannot access HttpRequestDataShare default properties by reference or array key/index");
16542 + return zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC);
16545 +static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC)
16547 + if (zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)) {
16549 + getObjectEx(http_requestdatashare_object, obj, object);
16551 + status = http_request_datashare_set(obj->share, Z_STRVAL_P(member), Z_STRLEN_P(member), (zend_bool) i_zend_is_true(value));
16552 + if (SUCCESS != status) {
16557 + zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC);
16560 +/* {{{ proto void HttpRequestDataShare::__destruct()
16561 + Clean up HttpRequestDataShare object. */
16562 +PHP_METHOD(HttpRequestDataShare, __destruct)
16565 + getObject(http_requestdatashare_object, obj);
16566 + http_request_datashare_detach_all(obj->share);
16571 +/* {{{ proto int HttpRequestDataShare::count()
16572 + Implements Countable::count(). */
16573 +PHP_METHOD(HttpRequestDataShare, count)
16575 + getObject(http_requestdatashare_object, obj);
16579 + RETURN_LONG(zend_llist_count(HTTP_RSHARE_HANDLES(obj->share)));
16583 +PHP_METHOD(HttpRequestDataShare, attach)
16586 + getObject(http_requestdatashare_object, obj);
16588 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
16592 + RETURN_SUCCESS(http_request_datashare_attach(obj->share, request));
16595 +PHP_METHOD(HttpRequestDataShare, detach)
16598 + getObject(http_requestdatashare_object, obj);
16600 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
16604 + RETURN_SUCCESS(http_request_datashare_detach(obj->share, request));
16607 +PHP_METHOD(HttpRequestDataShare, reset)
16610 + getObject(http_requestdatashare_object, obj);
16611 + http_request_datashare_detach_all(obj->share);
16615 +PHP_METHOD(HttpRequestDataShare, factory)
16617 + zend_bool global = 0;
16620 + zend_object_value ov;
16622 + SET_EH_THROW_HTTP();
16623 + if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs", &global, &cn, &cl) &&
16624 + SUCCESS == http_object_new(&ov, cn, cl, _http_requestdatashare_object_new_ex, http_requestdatashare_object_ce, NULL, NULL)) {
16625 + RETVAL_OBJVAL(ov, 0);
16626 + http_requestdatashare_instantiate(return_value, global);
16632 +/* {{{ proto static HttpRequestDataShare HttpRequestDataShare::singleton([bool global = false])
16633 + Get a single instance (differentiates between the global setting). */
16634 +PHP_METHOD(HttpRequestDataShare, singleton)
16636 + zend_bool global = 0;
16637 + zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
16639 + SET_EH_THROW_HTTP();
16640 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) {
16641 + zval **zobj_ptr = NULL, *zobj = NULL;
16643 + if (Z_TYPE_P(instance) == IS_ARRAY) {
16644 + if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) {
16645 + RETVAL_ZVAL(*zobj_ptr, 1, 0);
16647 + zobj = http_requestdatashare_instantiate(NULL, global);
16648 + add_index_zval(instance, global, zobj);
16649 + RETVAL_OBJECT(zobj, 1);
16652 + MAKE_STD_ZVAL(instance);
16653 + array_init(instance);
16655 + zobj = http_requestdatashare_instantiate(NULL, global);
16656 + add_index_zval(instance, global, zobj);
16657 + RETVAL_OBJECT(zobj, 1);
16659 + zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC);
16660 + zval_ptr_dtor(&instance);
16666 +#endif /* !WONKY */
16668 +static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC)
16671 + MAKE_STD_ZVAL(this_ptr);
16672 + Z_TYPE_P(this_ptr) = IS_OBJECT;
16673 + this_ptr->value.obj = http_requestdatashare_object_new_ex(http_requestdatashare_object_ce, global ? http_request_datashare_global_get() : NULL, NULL);
16676 + if (HTTP_G->request.datashare.cookie) {
16677 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("cookie")-1, HTTP_G->request.datashare.cookie TSRMLS_CC);
16679 + if (HTTP_G->request.datashare.dns) {
16680 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("dns")-1, HTTP_G->request.datashare.dns TSRMLS_CC);
16682 + if (HTTP_G->request.datashare.ssl) {
16683 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("ssl")-1, HTTP_G->request.datashare.ssl TSRMLS_CC);
16685 + if (HTTP_G->request.datashare.connect) {
16686 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("connect")-1, HTTP_G->request.datashare.connect TSRMLS_CC);
16692 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
16695 + * Local variables:
16697 + * c-basic-offset: 4
16699 + * vim600: noet sw=4 ts=4 fdm=marker
16700 + * vim<600: noet sw=4 ts=4
16704 +++ b/ext/http/http_requestpool_object.c
16707 + +--------------------------------------------------------------------+
16709 + +--------------------------------------------------------------------+
16710 + | Redistribution and use in source and binary forms, with or without |
16711 + | modification, are permitted provided that the conditions mentioned |
16712 + | in the accompanying LICENSE file are met. |
16713 + +--------------------------------------------------------------------+
16714 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
16715 + +--------------------------------------------------------------------+
16718 +/* $Id: http_requestpool_object.c 300299 2010-06-09 06:23:16Z mike $ */
16720 +#define HTTP_WANT_CURL
16721 +#include "php_http.h"
16723 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
16725 +#include "zend_interfaces.h"
16727 +#include "php_http_api.h"
16728 +#include "php_http_exception_object.h"
16729 +#include "php_http_request_api.h"
16730 +#include "php_http_request_object.h"
16731 +#include "php_http_request_pool_api.h"
16732 +#include "php_http_requestpool_object.h"
16734 +#if defined(HAVE_SPL) && !defined(WONKY)
16735 +/* SPL doesn't install its headers */
16736 +extern PHPAPI zend_class_entry *spl_ce_Countable;
16739 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestPool, method, 0, req_args)
16740 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestPool, method, 0)
16741 +#define HTTP_REQPOOL_ME(method, visibility) PHP_ME(HttpRequestPool, method, HTTP_ARGS(HttpRequestPool, method), visibility)
16743 +HTTP_EMPTY_ARGS(__construct);
16745 +HTTP_EMPTY_ARGS(__destruct);
16746 +HTTP_EMPTY_ARGS(reset);
16748 +HTTP_BEGIN_ARGS(attach, 1)
16749 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16752 +HTTP_BEGIN_ARGS(detach, 1)
16753 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16756 +HTTP_EMPTY_ARGS(send);
16757 +HTTP_EMPTY_ARGS(socketPerform);
16758 +HTTP_BEGIN_ARGS(socketSelect, 0)
16759 + HTTP_ARG_VAL(timeout, 0)
16762 +HTTP_EMPTY_ARGS(valid);
16763 +HTTP_EMPTY_ARGS(current);
16764 +HTTP_EMPTY_ARGS(key);
16765 +HTTP_EMPTY_ARGS(next);
16766 +HTTP_EMPTY_ARGS(rewind);
16768 +HTTP_EMPTY_ARGS(count);
16770 +HTTP_EMPTY_ARGS(getAttachedRequests);
16771 +HTTP_EMPTY_ARGS(getFinishedRequests);
16773 +HTTP_BEGIN_ARGS(enablePipelining, 0)
16774 + HTTP_ARG_VAL(enable, 0)
16777 +HTTP_BEGIN_ARGS(enableEvents, 0)
16778 + HTTP_ARG_VAL(enable, 0)
16781 +zend_class_entry *http_requestpool_object_ce;
16782 +zend_function_entry http_requestpool_object_fe[] = {
16783 + HTTP_REQPOOL_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
16784 + HTTP_REQPOOL_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
16785 + HTTP_REQPOOL_ME(attach, ZEND_ACC_PUBLIC)
16786 + HTTP_REQPOOL_ME(detach, ZEND_ACC_PUBLIC)
16787 + HTTP_REQPOOL_ME(send, ZEND_ACC_PUBLIC)
16788 + HTTP_REQPOOL_ME(reset, ZEND_ACC_PUBLIC)
16790 + HTTP_REQPOOL_ME(socketPerform, ZEND_ACC_PROTECTED)
16791 + HTTP_REQPOOL_ME(socketSelect, ZEND_ACC_PROTECTED)
16793 + /* implements Iterator */
16794 + HTTP_REQPOOL_ME(valid, ZEND_ACC_PUBLIC)
16795 + HTTP_REQPOOL_ME(current, ZEND_ACC_PUBLIC)
16796 + HTTP_REQPOOL_ME(key, ZEND_ACC_PUBLIC)
16797 + HTTP_REQPOOL_ME(next, ZEND_ACC_PUBLIC)
16798 + HTTP_REQPOOL_ME(rewind, ZEND_ACC_PUBLIC)
16800 + /* implmenents Countable */
16801 + HTTP_REQPOOL_ME(count, ZEND_ACC_PUBLIC)
16803 + HTTP_REQPOOL_ME(getAttachedRequests, ZEND_ACC_PUBLIC)
16804 + HTTP_REQPOOL_ME(getFinishedRequests, ZEND_ACC_PUBLIC)
16806 + HTTP_REQPOOL_ME(enablePipelining, ZEND_ACC_PUBLIC)
16807 + HTTP_REQPOOL_ME(enableEvents, ZEND_ACC_PUBLIC)
16809 + EMPTY_FUNCTION_ENTRY
16811 +static zend_object_handlers http_requestpool_object_handlers;
16813 +PHP_MINIT_FUNCTION(http_requestpool_object)
16815 + HTTP_REGISTER_CLASS_EX(HttpRequestPool, http_requestpool_object, NULL, 0);
16816 + http_requestpool_object_handlers.clone_obj = NULL;
16818 +#if defined(HAVE_SPL) && !defined(WONKY)
16819 + zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 2, spl_ce_Countable, zend_ce_iterator);
16821 + zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 1, zend_ce_iterator);
16827 +zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC)
16829 + zend_object_value ov;
16830 + http_requestpool_object *o;
16832 + o = ecalloc(1, sizeof(http_requestpool_object));
16835 + http_request_pool_init(&o->pool);
16837 + ALLOC_HASHTABLE(OBJ_PROP(o));
16838 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
16839 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
16841 + ov.handle = putObject(http_requestpool_object, o);
16842 + ov.handlers = &http_requestpool_object_handlers;
16847 +void _http_requestpool_object_free(zend_object *object TSRMLS_DC)
16849 + http_requestpool_object *o = (http_requestpool_object *) object;
16851 + http_request_pool_dtor(&o->pool);
16855 +#define http_requestpool_object_llist2array _http_requestpool_object_llist2array
16856 +static void _http_requestpool_object_llist2array(zval **req, zval *array TSRMLS_DC)
16858 + ZVAL_ADDREF(*req);
16859 + add_next_index_zval(array, *req);
16862 +/* ### USERLAND ### */
16864 +/* {{{ proto void HttpRequestPool::__construct([HttpRequest request[, ...]])
16865 + Creates a new HttpRequestPool object instance. */
16866 +PHP_METHOD(HttpRequestPool, __construct)
16868 + int argc = ZEND_NUM_ARGS();
16869 + zval ***argv = safe_emalloc(argc, sizeof(zval *), 0);
16870 + getObject(http_requestpool_object, obj);
16872 + SET_EH_THROW_HTTP();
16873 + if (SUCCESS == zend_get_parameters_array_ex(argc, argv)) {
16876 + for (i = 0; i < argc; ++i) {
16877 + if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), http_request_object_ce TSRMLS_CC)) {
16878 + http_request_pool_attach(&obj->pool, *(argv[i]));
16883 + http_final(HTTP_EX_CE(request_pool));
16888 +/* {{{ proto void HttpRequestPool::__destruct()
16889 + Clean up HttpRequestPool object. */
16890 +PHP_METHOD(HttpRequestPool, __destruct)
16892 + getObject(http_requestpool_object, obj);
16896 + http_request_pool_detach_all(&obj->pool);
16900 +/* {{{ proto void HttpRequestPool::reset()
16901 + Detach all attached HttpRequest objects. */
16902 +PHP_METHOD(HttpRequestPool, reset)
16904 + getObject(http_requestpool_object, obj);
16908 + obj->iterator.pos = 0;
16909 + http_request_pool_detach_all(&obj->pool);
16912 +/* {{{ proto bool HttpRequestPool::attach(HttpRequest request)
16913 + Attach an HttpRequest object to this HttpRequestPool. WARNING: set all options prior attaching! */
16914 +PHP_METHOD(HttpRequestPool, attach)
16917 + STATUS status = FAILURE;
16918 + getObject(http_requestpool_object, obj);
16920 + SET_EH_THROW_HTTP();
16921 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
16922 + if (obj->iterator.pos > 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles)) {
16923 + http_error(HE_THROW, HTTP_E_REQUEST_POOL, "Cannot attach to the HttpRequestPool while the iterator is active");
16925 + status = http_request_pool_attach(&obj->pool, request);
16929 + RETURN_SUCCESS(status);
16933 +/* {{{ proto bool HttpRequestPool::detach(HttpRequest request)
16934 + Detach an HttpRequest object from this HttpRequestPool. */
16935 +PHP_METHOD(HttpRequestPool, detach)
16938 + STATUS status = FAILURE;
16939 + getObject(http_requestpool_object, obj);
16941 + SET_EH_THROW_HTTP();
16942 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
16943 + obj->iterator.pos = -1;
16944 + status = http_request_pool_detach(&obj->pool, request);
16947 + RETURN_SUCCESS(status);
16951 +/* {{{ proto bool HttpRequestPool::send()
16952 + Send all attached HttpRequest objects in parallel. */
16953 +PHP_METHOD(HttpRequestPool, send)
16956 + getObject(http_requestpool_object, obj);
16960 + SET_EH_THROW_HTTP();
16961 + status = http_request_pool_send(&obj->pool);
16964 + /* rethrow as HttpRequestPoolException */
16965 + http_final(HTTP_EX_CE(request_pool));
16967 + RETURN_SUCCESS(status);
16971 +/* {{{ proto protected bool HttpRequestPool::socketPerform()
16972 + Returns TRUE until each request has finished its transaction. */
16973 +PHP_METHOD(HttpRequestPool, socketPerform)
16975 + getObject(http_requestpool_object, obj);
16979 + if (0 < http_request_pool_perform(&obj->pool)) {
16987 +/* {{{ proto protected bool HttpRequestPool::socketSelect([double timeout]) */
16988 +PHP_METHOD(HttpRequestPool, socketSelect)
16990 + double timeout = 0;
16991 + struct timeval custom_timeout, *custom_timeout_ptr = NULL;
16992 + getObject(http_requestpool_object, obj);
16994 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|d", &timeout)) {
16997 + if (ZEND_NUM_ARGS() && timeout > 0) {
16998 + custom_timeout.tv_sec = (time_t) timeout;
16999 + custom_timeout.tv_usec = HTTP_USEC(timeout) % HTTP_MCROSEC;
17000 + custom_timeout_ptr = &custom_timeout;
17003 + RETURN_SUCCESS(http_request_pool_select_ex(&obj->pool, custom_timeout_ptr));
17007 +/* {{{ proto bool HttpRequestPool::valid()
17008 + Implements Iterator::valid(). */
17009 +PHP_METHOD(HttpRequestPool, valid)
17013 + if (return_value_used) {
17014 + getObject(http_requestpool_object, obj);
17015 + RETURN_BOOL(obj->iterator.pos >= 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles));
17020 +/* {{{ proto HttpRequest HttpRequestPool::current()
17021 + Implements Iterator::current(). */
17022 +PHP_METHOD(HttpRequestPool, current)
17026 + if (return_value_used) {
17028 + zval **current = NULL;
17029 + zend_llist_position lpos;
17030 + getObject(http_requestpool_object, obj);
17032 + if (obj->iterator.pos < zend_llist_count(&obj->pool.handles)) {
17033 + for ( current = zend_llist_get_first_ex(&obj->pool.handles, &lpos);
17034 + current && obj->iterator.pos != pos++;
17035 + current = zend_llist_get_next_ex(&obj->pool.handles, &lpos));
17037 + RETURN_OBJECT(*current, 1);
17045 +/* {{{ proto int HttpRequestPool::key()
17046 + Implements Iterator::key(). */
17047 +PHP_METHOD(HttpRequestPool, key)
17051 + if (return_value_used) {
17052 + getObject(http_requestpool_object, obj);
17053 + RETURN_LONG(obj->iterator.pos);
17058 +/* {{{ proto void HttpRequestPool::next()
17059 + Implements Iterator::next(). */
17060 +PHP_METHOD(HttpRequestPool, next)
17063 + getObject(http_requestpool_object, obj);
17064 + ++(obj->iterator.pos);
17069 +/* {{{ proto void HttpRequestPool::rewind()
17070 + Implements Iterator::rewind(). */
17071 +PHP_METHOD(HttpRequestPool, rewind)
17074 + getObject(http_requestpool_object, obj);
17075 + obj->iterator.pos = 0;
17080 +/* {{{ proto int HttpRequestPool::count()
17081 + Implements Countable::count(). */
17082 +PHP_METHOD(HttpRequestPool, count)
17085 + getObject(http_requestpool_object, obj);
17086 + RETURN_LONG((long) zend_llist_count(&obj->pool.handles));
17091 +/* {{{ proto array HttpRequestPool::getAttachedRequests()
17092 + Get attached HttpRequest objects. */
17093 +PHP_METHOD(HttpRequestPool, getAttachedRequests)
17095 + getObject(http_requestpool_object, obj);
17099 + array_init(return_value);
17100 + zend_llist_apply_with_argument(&obj->pool.handles,
17101 + (llist_apply_with_arg_func_t) http_requestpool_object_llist2array,
17102 + return_value TSRMLS_CC);
17106 +/* {{{ proto array HttpRequestPool::getFinishedRequests()
17107 + Get attached HttpRequest objects that already have finished their work. */
17108 +PHP_METHOD(HttpRequestPool, getFinishedRequests)
17110 + getObject(http_requestpool_object, obj);
17114 + array_init(return_value);
17115 + zend_llist_apply_with_argument(&obj->pool.finished,
17116 + (llist_apply_with_arg_func_t) http_requestpool_object_llist2array,
17117 + return_value TSRMLS_CC);
17121 +/* {{{ proto bool HttpRequestPool::enablePipelining([bool enable = true])
17122 + Enables pipelining support for all attached requests if support in libcurl is given. */
17123 +PHP_METHOD(HttpRequestPool, enablePipelining)
17125 + zend_bool enable = 1;
17126 +#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0)
17127 + getObject(http_requestpool_object, obj);
17130 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) {
17133 +#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0)
17134 + if (CURLM_OK == curl_multi_setopt(obj->pool.ch, CURLMOPT_PIPELINING, (long) enable)) {
17142 +/* {{{ proto bool HttpRequestPool::enableEvents([bool enable = true])
17143 + Enables event-driven I/O if support in libcurl is given. */
17144 +PHP_METHOD(HttpRequestPool, enableEvents)
17146 + zend_bool enable = 1;
17147 +#if defined(HTTP_HAVE_EVENT)
17148 + getObject(http_requestpool_object, obj);
17151 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) {
17152 +#if defined(HTTP_HAVE_EVENT)
17153 + obj->pool.useevents = enable;
17161 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
17164 + * Local variables:
17166 + * c-basic-offset: 4
17168 + * vim600: noet sw=4 ts=4 fdm=marker
17169 + * vim<600: noet sw=4 ts=4
17173 +++ b/ext/http/http_response_object.c
17176 + +--------------------------------------------------------------------+
17178 + +--------------------------------------------------------------------+
17179 + | Redistribution and use in source and binary forms, with or without |
17180 + | modification, are permitted provided that the conditions mentioned |
17181 + | in the accompanying LICENSE file are met. |
17182 + +--------------------------------------------------------------------+
17183 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
17184 + +--------------------------------------------------------------------+
17187 +/* $Id: http_response_object.c 298891 2010-05-03 08:26:38Z mike $ */
17189 +#define HTTP_WANT_SAPI
17190 +#define HTTP_WANT_MAGIC
17191 +#include "php_http.h"
17193 +/* broken static properties in PHP 5.0 */
17194 +#if defined(ZEND_ENGINE_2) && !defined(WONKY)
17196 +#include "php_ini.h"
17198 +#include "php_http_api.h"
17199 +#include "php_http_cache_api.h"
17200 +#include "php_http_exception_object.h"
17201 +#include "php_http_headers_api.h"
17202 +#include "php_http_response_object.h"
17203 +#include "php_http_send_api.h"
17205 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpResponse, method, 0, req_args)
17206 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpResponse, method, 0)
17207 +#define HTTP_RESPONSE_ME(method, visibility) PHP_ME(HttpResponse, method, HTTP_ARGS(HttpResponse, method), visibility|ZEND_ACC_STATIC)
17208 +#define HTTP_RESPONSE_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpResponse, method))
17210 +HTTP_BEGIN_ARGS(setHeader, 1)
17211 + HTTP_ARG_VAL(name, 0)
17212 + HTTP_ARG_VAL(value, 0)
17213 + HTTP_ARG_VAL(replace, 0)
17216 +HTTP_BEGIN_ARGS(getHeader, 0)
17217 + HTTP_ARG_VAL(name, 0)
17220 +HTTP_EMPTY_ARGS(getETag);
17221 +HTTP_BEGIN_ARGS(setETag, 1)
17222 + HTTP_ARG_VAL(etag, 0)
17225 +HTTP_EMPTY_ARGS(getLastModified);
17226 +HTTP_BEGIN_ARGS(setLastModified, 1)
17227 + HTTP_ARG_VAL(timestamp, 0)
17230 +HTTP_EMPTY_ARGS(getCache);
17231 +HTTP_BEGIN_ARGS(setCache, 1)
17232 + HTTP_ARG_VAL(cache, 0)
17235 +HTTP_EMPTY_ARGS(getGzip);
17236 +HTTP_BEGIN_ARGS(setGzip, 1)
17237 + HTTP_ARG_VAL(gzip, 0)
17240 +HTTP_EMPTY_ARGS(getCacheControl);
17241 +HTTP_BEGIN_ARGS(setCacheControl, 1)
17242 + HTTP_ARG_VAL(cache_control, 0)
17243 + HTTP_ARG_VAL(max_age, 0)
17244 + HTTP_ARG_VAL(must_revalidate, 0)
17247 +HTTP_EMPTY_ARGS(getContentType);
17248 +HTTP_BEGIN_ARGS(setContentType, 1)
17249 + HTTP_ARG_VAL(content_type, 0)
17252 +HTTP_BEGIN_ARGS(guessContentType, 1)
17253 + HTTP_ARG_VAL(magic_file, 0)
17254 + HTTP_ARG_VAL(magic_mode, 0)
17257 +HTTP_EMPTY_ARGS(getContentDisposition);
17258 +HTTP_BEGIN_ARGS(setContentDisposition, 1)
17259 + HTTP_ARG_VAL(filename, 0)
17260 + HTTP_ARG_VAL(send_inline, 0)
17263 +HTTP_EMPTY_ARGS(getThrottleDelay);
17264 +HTTP_BEGIN_ARGS(setThrottleDelay, 1)
17265 + HTTP_ARG_VAL(seconds, 0)
17268 +HTTP_EMPTY_ARGS(getBufferSize);
17269 +HTTP_BEGIN_ARGS(setBufferSize, 1)
17270 + HTTP_ARG_VAL(bytes, 0)
17273 +HTTP_EMPTY_ARGS(getData);
17274 +HTTP_BEGIN_ARGS(setData, 1)
17275 + HTTP_ARG_VAL(data, 0)
17278 +HTTP_EMPTY_ARGS(getStream);
17279 +HTTP_BEGIN_ARGS(setStream, 1)
17280 + HTTP_ARG_VAL(stream, 0)
17283 +HTTP_EMPTY_ARGS(getFile);
17284 +HTTP_BEGIN_ARGS(setFile, 1)
17285 + HTTP_ARG_VAL(filepath, 0)
17288 +HTTP_BEGIN_ARGS(send, 0)
17289 + HTTP_ARG_VAL(clean_ob, 0)
17292 +HTTP_EMPTY_ARGS(capture);
17294 +HTTP_BEGIN_ARGS(redirect, 0)
17295 + HTTP_ARG_VAL(url, 0)
17296 + HTTP_ARG_VAL(params, 0)
17297 + HTTP_ARG_VAL(session, 0)
17298 + HTTP_ARG_VAL(permanent, 0)
17301 +HTTP_BEGIN_ARGS(status, 1)
17302 + HTTP_ARG_VAL(code, 0)
17305 +HTTP_EMPTY_ARGS(getRequestHeaders);
17306 +HTTP_EMPTY_ARGS(getRequestBody);
17307 +HTTP_EMPTY_ARGS(getRequestBodyStream);
17309 +#define THIS_CE http_response_object_ce
17310 +zend_class_entry *http_response_object_ce;
17311 +zend_function_entry http_response_object_fe[] = {
17313 + HTTP_RESPONSE_ME(setHeader, ZEND_ACC_PUBLIC)
17314 + HTTP_RESPONSE_ME(getHeader, ZEND_ACC_PUBLIC)
17316 + HTTP_RESPONSE_ME(setETag, ZEND_ACC_PUBLIC)
17317 + HTTP_RESPONSE_ME(getETag, ZEND_ACC_PUBLIC)
17319 + HTTP_RESPONSE_ME(setLastModified, ZEND_ACC_PUBLIC)
17320 + HTTP_RESPONSE_ME(getLastModified, ZEND_ACC_PUBLIC)
17322 + HTTP_RESPONSE_ME(setContentDisposition, ZEND_ACC_PUBLIC)
17323 + HTTP_RESPONSE_ME(getContentDisposition, ZEND_ACC_PUBLIC)
17325 + HTTP_RESPONSE_ME(setContentType, ZEND_ACC_PUBLIC)
17326 + HTTP_RESPONSE_ME(getContentType, ZEND_ACC_PUBLIC)
17328 + HTTP_RESPONSE_ME(guessContentType, ZEND_ACC_PUBLIC)
17330 + HTTP_RESPONSE_ME(setCache, ZEND_ACC_PUBLIC)
17331 + HTTP_RESPONSE_ME(getCache, ZEND_ACC_PUBLIC)
17333 + HTTP_RESPONSE_ME(setCacheControl, ZEND_ACC_PUBLIC)
17334 + HTTP_RESPONSE_ME(getCacheControl, ZEND_ACC_PUBLIC)
17336 + HTTP_RESPONSE_ME(setGzip, ZEND_ACC_PUBLIC)
17337 + HTTP_RESPONSE_ME(getGzip, ZEND_ACC_PUBLIC)
17339 + HTTP_RESPONSE_ME(setThrottleDelay, ZEND_ACC_PUBLIC)
17340 + HTTP_RESPONSE_ME(getThrottleDelay, ZEND_ACC_PUBLIC)
17342 + HTTP_RESPONSE_ME(setBufferSize, ZEND_ACC_PUBLIC)
17343 + HTTP_RESPONSE_ME(getBufferSize, ZEND_ACC_PUBLIC)
17345 + HTTP_RESPONSE_ME(setData, ZEND_ACC_PUBLIC)
17346 + HTTP_RESPONSE_ME(getData, ZEND_ACC_PUBLIC)
17348 + HTTP_RESPONSE_ME(setFile, ZEND_ACC_PUBLIC)
17349 + HTTP_RESPONSE_ME(getFile, ZEND_ACC_PUBLIC)
17351 + HTTP_RESPONSE_ME(setStream, ZEND_ACC_PUBLIC)
17352 + HTTP_RESPONSE_ME(getStream, ZEND_ACC_PUBLIC)
17354 + HTTP_RESPONSE_ME(send, ZEND_ACC_PUBLIC)
17355 + HTTP_RESPONSE_ME(capture, ZEND_ACC_PUBLIC)
17357 + HTTP_RESPONSE_ALIAS(redirect, http_redirect)
17358 + HTTP_RESPONSE_ALIAS(status, http_send_status)
17359 + HTTP_RESPONSE_ALIAS(getRequestHeaders, http_get_request_headers)
17360 + HTTP_RESPONSE_ALIAS(getRequestBody, http_get_request_body)
17361 + HTTP_RESPONSE_ALIAS(getRequestBodyStream, http_get_request_body_stream)
17363 + EMPTY_FUNCTION_ENTRY
17366 +PHP_MINIT_FUNCTION(http_response_object)
17368 + HTTP_REGISTER_CLASS(HttpResponse, http_response_object, NULL, 0);
17370 + zend_declare_property_bool(THIS_CE, ZEND_STRS("sent")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17371 + zend_declare_property_bool(THIS_CE, ZEND_STRS("catch")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17372 + zend_declare_property_long(THIS_CE, ZEND_STRS("mode")-1, -1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17373 + zend_declare_property_long(THIS_CE, ZEND_STRS("stream")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17374 + zend_declare_property_null(THIS_CE, ZEND_STRS("file")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17375 + zend_declare_property_null(THIS_CE, ZEND_STRS("data")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17376 + zend_declare_property_bool(THIS_CE, ZEND_STRS("cache")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17377 + zend_declare_property_bool(THIS_CE, ZEND_STRS("gzip")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17378 + zend_declare_property_null(THIS_CE, ZEND_STRS("eTag")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17379 + zend_declare_property_long(THIS_CE, ZEND_STRS("lastModified")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17380 + zend_declare_property_null(THIS_CE, ZEND_STRS("cacheControl")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17381 + zend_declare_property_null(THIS_CE, ZEND_STRS("contentType")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17382 + zend_declare_property_null(THIS_CE, ZEND_STRS("contentDisposition")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17383 + zend_declare_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17384 + zend_declare_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, 0.0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17387 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT")-1, HTTP_REDIRECT TSRMLS_CC);
17388 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PERM")-1, HTTP_REDIRECT_PERM TSRMLS_CC);
17389 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_FOUND")-1, HTTP_REDIRECT_FOUND TSRMLS_CC);
17390 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_POST")-1, HTTP_REDIRECT_POST TSRMLS_CC);
17391 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PROXY")-1, HTTP_REDIRECT_PROXY TSRMLS_CC);
17392 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_TEMP")-1, HTTP_REDIRECT_TEMP TSRMLS_CC);
17393 +#endif /* WONKY */
17398 +/* ### USERLAND ### */
17400 +/* {{{ proto static bool HttpResponse::setHeader(string name[, mixed value[, bool replace = true]])
17401 + Send an HTTP header. */
17402 +PHP_METHOD(HttpResponse, setHeader)
17404 + zend_bool replace = 1;
17406 + int name_len = 0;
17407 + zval *value = NULL;
17409 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/!b", &name, &name_len, &value, &replace)) {
17412 + if (SG(headers_sent)) {
17413 + http_error(HE_WARNING, HTTP_E_HEADER, "Cannot add another header when headers have already been sent");
17417 + http_error(HE_WARNING, HTTP_E_HEADER, "Cannot send anonymous headers");
17420 + http_send_header_zval_ex(name, name_len, &value, replace);
17425 +/* {{{ proto static mixed HttpResponse::getHeader([string name])
17426 + Get header(s) about to be sent. */
17427 +PHP_METHOD(HttpResponse, getHeader)
17429 + char *name = NULL;
17430 + int name_len = 0;
17432 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len)) {
17436 + if (name && name_len) {
17438 + HashTable headers_ht;
17440 + zend_hash_init(&headers_ht, sizeof(zval *), NULL, ZVAL_PTR_DTOR, 0);
17441 + if ( (SUCCESS == http_get_response_headers(&headers_ht)) &&
17442 + (SUCCESS == zend_hash_find(&headers_ht, name, name_len + 1, (void *) &header))) {
17443 + RETVAL_ZVAL(*header, 1, 0);
17447 + zend_hash_destroy(&headers_ht);
17449 + array_init(return_value);
17450 + http_get_response_headers(Z_ARRVAL_P(return_value));
17455 +/* {{{ proto static bool HttpResponse::setCache(bool cache)
17456 + Whether it should be attempted to cache the entity. */
17457 +PHP_METHOD(HttpResponse, setCache)
17459 + zend_bool do_cache = 0;
17461 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
17465 + RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("cache")-1, do_cache TSRMLS_CC));
17469 +/* {{{ proto static bool HttpResponse::getCache()
17470 + Get current caching setting. */
17471 +PHP_METHOD(HttpResponse, getCache)
17475 + if (return_value_used) {
17476 + zval *cache = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17477 + RETVAL_ZVAL(cache, 1, 1);
17482 +/* {{{ proto static bool HttpResponse::setGzip(bool gzip)
17483 + Enable on-thy-fly gzipping of the sent entity. */
17484 +PHP_METHOD(HttpResponse, setGzip)
17486 + zend_bool do_gzip = 0;
17488 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
17492 + RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("gzip")-1, do_gzip TSRMLS_CC));
17496 +/* {{{ proto static bool HttpResponse::getGzip()
17497 + Get current gzipping setting. */
17498 +PHP_METHOD(HttpResponse, getGzip)
17502 + if (return_value_used) {
17503 + zval *gzip = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17504 + RETVAL_ZVAL(gzip, 1, 1);
17509 +/* {{{ proto static bool HttpResponse::setCacheControl(string control[, int max_age = 0[, bool must_revalidate = true]])
17510 + 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. */
17511 +PHP_METHOD(HttpResponse, setCacheControl)
17513 + char *ccontrol, *cctl;
17515 + long max_age = 0;
17516 + zend_bool must_revalidate = 1;
17518 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &ccontrol, &cc_len, &max_age, &must_revalidate)) {
17522 + if (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache")) {
17523 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
17526 + size_t cctl_len = spprintf(&cctl, 0, "%s,%s max-age=%ld", ccontrol, must_revalidate?" must-revalidate,":"", max_age);
17527 + RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("cacheControl")-1, cctl, cctl_len TSRMLS_CC));
17533 +/* {{{ proto static string HttpResponse::getCacheControl()
17534 + Get current Cache-Control header setting. */
17535 +PHP_METHOD(HttpResponse, getCacheControl)
17539 + if (return_value_used) {
17540 + zval *cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17541 + RETVAL_ZVAL(cctl, 1, 1);
17546 +/* {{{ proto static bool HttpResponse::setContentType(string content_type)
17547 + Set the content-type of the sent entity. */
17548 +PHP_METHOD(HttpResponse, setContentType)
17553 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
17557 + HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
17558 + RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentType")-1, ctype, ctype_len TSRMLS_CC));
17562 +/* {{{ proto static string HttpResponse::getContentType()
17563 + Get current Content-Type header setting. */
17564 +PHP_METHOD(HttpResponse, getContentType)
17568 + if (return_value_used) {
17569 + zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17570 + RETVAL_ZVAL(ctype, 1, 1);
17575 +/* {{{ proto static string HttpResponse::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
17576 + Attempts to guess the content type of supplied payload through libmagic. */
17577 +PHP_METHOD(HttpResponse, guessContentType)
17579 +#ifdef HTTP_HAVE_MAGIC
17580 + char *magic_file, *ct = NULL;
17581 + int magic_file_len;
17582 + long magic_mode = MAGIC_MIME;
17585 + SET_EH_THROW_HTTP();
17586 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
17587 + switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
17590 + zval *data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
17591 + ct = http_guess_content_type(magic_file, magic_mode, Z_STRVAL_P(data), Z_STRLEN_P(data), SEND_DATA);
17598 + zval *z = *zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
17599 + z->type = IS_RESOURCE;
17600 + php_stream_from_zval(s, &z);
17601 + ct = http_guess_content_type(magic_file, magic_mode, s, 0, SEND_RSRC);
17606 + 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);
17610 + zend_update_static_property_string(THIS_CE, ZEND_STRS("contentType")-1, ct TSRMLS_CC);
17611 + RETVAL_STRING(ct, 0);
17616 + http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
17622 +/* {{{ proto static bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
17623 + Set the Content-Disposition. */
17624 +PHP_METHOD(HttpResponse, setContentDisposition)
17629 + zend_bool send_inline = 0;
17631 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &send_inline)) {
17635 + cd_len = spprintf(&cd, 0, "%s; filename=\"%s\"", send_inline ? "inline" : "attachment", file);
17636 + RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentDisposition")-1, cd, cd_len TSRMLS_CC));
17641 +/* {{{ proto static string HttpResponse::getContentDisposition()
17642 + Get current Content-Disposition setting. */
17643 +PHP_METHOD(HttpResponse, getContentDisposition)
17647 + if (return_value_used) {
17648 + zval *cdisp = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17649 + RETVAL_ZVAL(cdisp, 1, 1);
17654 +/* {{{ proto static bool HttpResponse::setETag(string etag)
17655 + Set a custom ETag. Use this only if you know what you're doing. */
17656 +PHP_METHOD(HttpResponse, setETag)
17661 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
17665 + RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("eTag")-1, etag, etag_len TSRMLS_CC));
17669 +/* {{{ proto static string HttpResponse::getETag()
17670 + Get calculated or previously set custom ETag. */
17671 +PHP_METHOD(HttpResponse, getETag)
17675 + if (return_value_used) {
17676 + zval *etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17677 + RETVAL_ZVAL(etag, 1, 1);
17682 +/* {{{ proto static bool HttpResponse::setLastModified(int timestamp)
17683 + Set a custom Last-Modified date. */
17684 +PHP_METHOD(HttpResponse, setLastModified)
17688 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lm)) {
17692 + RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, lm TSRMLS_CC));
17696 +/* {{{ proto static int HttpResponse::getLastModified()
17697 + Get calculated or previously set custom Last-Modified date. */
17698 +PHP_METHOD(HttpResponse, getLastModified)
17702 + if (return_value_used) {
17703 + zval *lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17704 + RETVAL_ZVAL(lmod, 1, 1);
17709 +/* {{{ proto static bool HttpResponse::setThrottleDelay(double seconds)
17710 + Sets the throttle delay for use with HttpResponse::setBufferSize(). */
17711 +PHP_METHOD(HttpResponse, setThrottleDelay)
17715 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) {
17718 + RETURN_SUCCESS(zend_update_static_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, seconds TSRMLS_CC));
17722 +/* {{{ proto static double HttpResponse::getThrottleDelay()
17723 + Get the current throttle delay. */
17724 +PHP_METHOD(HttpResponse, getThrottleDelay)
17728 + if (return_value_used) {
17729 + zval *tdel = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17730 + RETVAL_ZVAL(tdel, 1, 1);
17735 +/* {{{ proto static bool HttpResponse::setBufferSize(int bytes)
17736 + Sets the send buffer size for use with HttpResponse::setThrottleDelay(). */
17737 +PHP_METHOD(HttpResponse, setBufferSize)
17741 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) {
17744 + RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, bytes TSRMLS_CC));
17748 +/* {{{ proto static int HttpResponse::getBufferSize()
17749 + Get current buffer size. */
17750 +PHP_METHOD(HttpResponse, getBufferSize)
17754 + if (return_value_used) {
17755 + zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17756 + RETVAL_ZVAL(bsize, 1, 1);
17761 +/* {{{ proto static bool HttpResponse::setData(mixed data)
17762 + Set the data to be sent. */
17763 +PHP_METHOD(HttpResponse, setData)
17768 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) {
17771 + if (Z_TYPE_P(the_data) != IS_STRING) {
17772 + convert_to_string(the_data);
17775 + if ( (SUCCESS != zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC)) ||
17776 + (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_DATA TSRMLS_CC))) {
17780 + zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_data, SEND_DATA) TSRMLS_CC);
17781 + if ((etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA))) {
17782 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
17790 +/* {{{ proto static string HttpResponse::getData()
17791 + Get the previously set data to be sent. */
17792 +PHP_METHOD(HttpResponse, getData)
17796 + if (return_value_used) {
17797 + zval *the_data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
17799 + RETURN_ZVAL(the_data, 1, 0);
17804 +/* {{{ proto static bool HttpResponse::setStream(resource stream)
17805 + Set the resource to be sent. */
17806 +PHP_METHOD(HttpResponse, setStream)
17809 + zval *the_stream;
17810 + php_stream *the_real_stream;
17811 + php_stream_statbuf ssb;
17813 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
17817 + php_stream_from_zval(the_real_stream, &the_stream);
17818 + if (php_stream_stat(the_real_stream, &ssb)) {
17822 + if ( (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("stream")-1, Z_LVAL_P(the_stream) TSRMLS_CC)) ||
17823 + (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_RSRC TSRMLS_CC))) {
17826 + zend_list_addref(Z_LVAL_P(the_stream));
17828 + zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_real_stream, SEND_RSRC) TSRMLS_CC);
17829 + if ((etag = http_etag(the_real_stream, 0, SEND_RSRC))) {
17830 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
17838 +/* {{{ proto static resource HttpResponse::getStream()
17839 + Get the previously set resource to be sent. */
17840 +PHP_METHOD(HttpResponse, getStream)
17844 + if (return_value_used) {
17845 + zval *stream = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17846 + RETVAL_RESOURCE(Z_LVAL_P(stream));
17847 + zval_ptr_dtor(&stream);
17852 +/* {{{ proto static bool HttpResponse::setFile(string file)
17853 + Set the file to be sent. */
17854 +PHP_METHOD(HttpResponse, setFile)
17856 + char *the_file, *etag;
17858 + php_stream_statbuf ssb;
17860 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &the_file, &file_len)) {
17864 + if (php_stream_stat_path(the_file, &ssb)) {
17868 + if ( (SUCCESS != zend_update_static_property_stringl(THIS_CE, ZEND_STRS("file")-1, the_file, file_len TSRMLS_CC)) ||
17869 + (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, -1 TSRMLS_CC))) {
17873 + zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_file, -1) TSRMLS_CC);
17874 + if ((etag = http_etag(the_file, 0, -1))) {
17875 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
17883 +/* {{{ proto static string HttpResponse::getFile()
17884 + Get the previously set file to be sent. */
17885 +PHP_METHOD(HttpResponse, getFile)
17889 + if (return_value_used) {
17890 + zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17891 + RETVAL_ZVAL(file, 1, 1);
17896 +/* {{{ proto static bool HttpResponse::send([bool clean_ob = true])
17897 + Finally send the entity. */
17898 +PHP_METHOD(HttpResponse, send)
17901 + zend_bool clean_ob = 1;
17903 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) {
17907 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
17909 + sent = *zend_std_get_static_property(THIS_CE, ZEND_STRS("sent")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
17910 + if (Z_LVAL_P(sent)) {
17911 + http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, response has already been sent");
17914 + Z_LVAL_P(sent) = 1;
17917 + /* capture mode */
17918 + if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("catch")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
17919 + zval *zetag, *the_data;
17921 + MAKE_STD_ZVAL(the_data);
17922 + php_ob_get_buffer(the_data TSRMLS_CC);
17923 + zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC);
17924 + ZVAL_LONG(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC), SEND_DATA);
17926 + zetag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17927 + if (!Z_STRLEN_P(zetag)) {
17928 + char *etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA);
17930 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
17934 + zval_ptr_dtor(&the_data);
17935 + zval_ptr_dtor(&zetag);
17941 + /* interrupt on-the-fly etag generation */
17942 + HTTP_G->etag.started = 0;
17943 + /* discard previous output buffers */
17944 + php_end_ob_buffers(0 TSRMLS_CC);
17948 + if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
17949 + zval *cctl, *etag, *lmod;
17951 + lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17952 + etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17953 + cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17955 + if (Z_LVAL_P(lmod) || Z_STRLEN_P(etag)) {
17956 + if (Z_STRLEN_P(cctl)) {
17957 + http_send_cache_control(Z_STRVAL_P(cctl), Z_STRLEN_P(cctl));
17959 + http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
17961 + if (Z_STRLEN_P(etag)) {
17962 + http_send_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag));
17964 + if (Z_LVAL_P(lmod)) {
17965 + http_send_last_modified(Z_LVAL_P(lmod));
17969 + zval_ptr_dtor(&etag);
17970 + zval_ptr_dtor(&lmod);
17971 + zval_ptr_dtor(&cctl);
17974 + /* content type */
17976 + zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17977 + if (Z_STRLEN_P(ctype)) {
17978 + http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
17980 + char *ctypes = INI_STR("default_mimetype");
17981 + size_t ctlen = ctypes ? strlen(ctypes) : 0;
17984 + http_send_content_type(ctypes, ctlen);
17986 + http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
17989 + zval_ptr_dtor(&ctype);
17992 + /* content disposition */
17994 + zval *cd = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17995 + if (Z_STRLEN_P(cd)) {
17996 + http_send_header_ex("Content-Disposition", lenof("Content-Disposition"), Z_STRVAL_P(cd), Z_STRLEN_P(cd), 1, NULL);
17998 + zval_ptr_dtor(&cd);
18003 + zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18004 + zval *delay = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18005 + HTTP_G->send.buffer_size = Z_LVAL_P(bsize);
18006 + HTTP_G->send.throttle_delay = Z_DVAL_P(delay);
18007 + zval_ptr_dtor(&bsize);
18008 + zval_ptr_dtor(&delay);
18012 + 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));
18015 + switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
18018 + zval *zdata = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18019 + RETVAL_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
18020 + zval_ptr_dtor(&zdata);
18026 + php_stream *the_real_stream;
18027 + 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)));
18028 + the_stream->type = IS_RESOURCE;
18029 + php_stream_from_zval(the_real_stream, &the_stream);
18030 + RETVAL_SUCCESS(http_send_stream(the_real_stream));
18031 + zval_ptr_dtor(&the_stream);
18037 + zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18038 + RETVAL_SUCCESS(http_send_file(Z_STRVAL_P(file)));
18039 + zval_ptr_dtor(&file);
18046 +/* {{{ proto static void HttpResponse::capture()
18047 + Capture script output.
18049 +PHP_METHOD(HttpResponse, capture)
18053 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
18055 + zend_update_static_property_long(THIS_CE, ZEND_STRS("catch")-1, 1 TSRMLS_CC);
18057 + php_end_ob_buffers(0 TSRMLS_CC);
18058 + php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC);
18060 + /* register shutdown function */
18062 + zval func, retval, arg, *argp[1];
18064 + INIT_PZVAL(&arg);
18065 + INIT_PZVAL(&func);
18066 + INIT_PZVAL(&retval);
18067 + ZVAL_STRINGL(&func, "register_shutdown_function", lenof("register_shutdown_function"), 0);
18069 + array_init(&arg);
18070 + add_next_index_stringl(&arg, "HttpResponse", lenof("HttpResponse"), 1);
18071 + add_next_index_stringl(&arg, "send", lenof("send"), 1);
18073 + call_user_function(EG(function_table), NULL, &func, &retval, 1, argp TSRMLS_CC);
18079 +#endif /* ZEND_ENGINE_2 && !WONKY */
18082 + * Local variables:
18084 + * c-basic-offset: 4
18086 + * vim600: noet sw=4 ts=4 fdm=marker
18087 + * vim<600: noet sw=4 ts=4
18091 +++ b/ext/http/http_send_api.c
18094 + +--------------------------------------------------------------------+
18096 + +--------------------------------------------------------------------+
18097 + | Redistribution and use in source and binary forms, with or without |
18098 + | modification, are permitted provided that the conditions mentioned |
18099 + | in the accompanying LICENSE file are met. |
18100 + +--------------------------------------------------------------------+
18101 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
18102 + +--------------------------------------------------------------------+
18105 +/* $Id: http_send_api.c 300299 2010-06-09 06:23:16Z mike $ */
18107 +#define HTTP_WANT_SAPI
18108 +#define HTTP_WANT_ZLIB
18109 +#define HTTP_WANT_MAGIC
18110 +#include "php_http.h"
18112 +#include "php_streams.h"
18114 +#include "php_http_api.h"
18115 +#include "php_http_cache_api.h"
18116 +#include "php_http_date_api.h"
18117 +#include "php_http_encoding_api.h"
18118 +#include "php_http_headers_api.h"
18119 +#include "php_http_send_api.h"
18121 +/* {{{ http_flush() */
18122 +#define http_flush(d, l) _http_flush(NULL, (d), (l) TSRMLS_CC)
18123 +static inline void _http_flush(void *nothing, const char *data, size_t data_len TSRMLS_DC)
18125 + PHPWRITE(data, data_len);
18126 + /* we really only need to flush when throttling is enabled,
18127 + because we push the data as fast as possible anyway if not */
18128 + if (HTTP_G->send.throttle_delay >= HTTP_DIFFSEC) {
18129 + if (OG(ob_nesting_level)) {
18130 + php_end_ob_buffer(1, 1 TSRMLS_CC);
18132 + if (!OG(implicit_flush)) {
18133 + sapi_flush(TSRMLS_C);
18135 + http_sleep(HTTP_G->send.throttle_delay);
18140 +/* {{{ http_send_response_start */
18141 +#define http_send_response_start(b, cl) _http_send_response_start((b), (cl) TSRMLS_CC)
18142 +static inline void _http_send_response_start(void **buffer, size_t content_length TSRMLS_DC)
18146 + if ((encoding = http_encoding_response_start(content_length, 0))) {
18147 +#ifdef HTTP_HAVE_ZLIB
18148 + *((http_encoding_stream **) buffer) = http_encoding_deflate_stream_init(NULL,
18149 + (encoding == HTTP_ENCODING_GZIP) ?
18150 + HTTP_DEFLATE_TYPE_GZIP : HTTP_DEFLATE_TYPE_ZLIB);
18153 + /* flush headers */
18154 + sapi_flush(TSRMLS_C);
18158 +/* {{{ http_send_response_data_plain */
18159 +#define http_send_response_data_plain(b, d, dl) _http_send_response_data_plain((b), (d), (dl) TSRMLS_CC)
18160 +static inline void _http_send_response_data_plain(void **buffer, const char *data, size_t data_len TSRMLS_DC)
18162 + if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) {
18163 +#ifdef HTTP_HAVE_ZLIB
18165 + size_t encoded_len;
18166 + http_encoding_stream *s = *((http_encoding_stream **) buffer);
18168 + http_encoding_deflate_stream_update(s, data, data_len, &encoded, &encoded_len);
18169 + if (HTTP_G->send.buffer_size) {
18170 + phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC);
18172 + http_flush(encoded, encoded_len);
18176 + http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug");
18178 + } else if (HTTP_G->send.buffer_size) {
18179 + phpstr_chunked_output((phpstr **) buffer, data, data_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC);
18181 + http_flush(data, data_len);
18186 +/* {{{ http_send_response_data_fetch */
18187 +#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)
18188 +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)
18190 + long bsz, got, len = end - begin;
18192 + if (!(bsz = HTTP_G->send.buffer_size)) {
18193 + bsz = HTTP_SENDBUF_SIZE;
18197 + case SEND_RSRC: {
18198 + php_stream *s = (php_stream *) data;
18199 + if (SUCCESS == php_stream_seek(s, begin, SEEK_SET)) {
18200 + char *buf = emalloc(bsz);
18202 + while (len > 0) {
18203 + got = php_stream_read(s, buf, MIN(len, bsz));
18204 + http_send_response_data_plain(buffer, buf, got);
18212 + case SEND_DATA: {
18213 + const char *buf = ((const char *) data) + begin;
18214 + while (len > 0) {
18215 + got = MIN(len, bsz);
18216 + http_send_response_data_plain(buffer, buf, got);
18222 + EMPTY_SWITCH_DEFAULT_CASE();
18227 +/* {{{ http_send_response_finish */
18228 +#define http_send_response_finish(b) _http_send_response_finish((b) TSRMLS_CC)
18229 +static inline void _http_send_response_finish(void **buffer TSRMLS_DC)
18231 + if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) {
18232 +#ifdef HTTP_HAVE_ZLIB
18233 + char *encoded = NULL;
18234 + size_t encoded_len = 0;
18235 + http_encoding_stream *s = *((http_encoding_stream **) buffer);
18237 + http_encoding_deflate_stream_finish(s, &encoded, &encoded_len);
18238 + if (HTTP_G->send.buffer_size) {
18239 + phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, 0, _http_flush, NULL TSRMLS_CC);
18241 + http_flush(encoded, encoded_len);
18243 + http_encoding_deflate_stream_free(&s);
18244 + STR_FREE(encoded);
18246 + http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug");
18248 + } else if (HTTP_G->send.buffer_size) {
18249 + phpstr_chunked_output((phpstr **) buffer, NULL, 0, 0, _http_flush, NULL TSRMLS_CC);
18255 +PHP_MINIT_FUNCTION(http_send)
18257 + HTTP_LONG_CONSTANT("HTTP_REDIRECT", HTTP_REDIRECT);
18258 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_PERM", HTTP_REDIRECT_PERM);
18259 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_FOUND", HTTP_REDIRECT_FOUND);
18260 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_POST", HTTP_REDIRECT_POST);
18261 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_PROXY", HTTP_REDIRECT_PROXY);
18262 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_TEMP", HTTP_REDIRECT_TEMP);
18268 +/* {{{ http_find_header */
18272 +} http_response_header_t;
18274 +static int http_find_header(void *data, void *arg)
18276 + http_response_header_t *h = arg;
18277 + sapi_header_struct *s = data;
18279 + return (!strncasecmp(s->header, h->h, h->l)) && s->header[h->l] == ':';
18283 +/* {{{ void http_hide_header(char *) */
18284 +PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC)
18286 + http_response_header_t h = {name, name_len};
18287 + zend_llist_del_element(&SG(sapi_headers).headers, (void *) &h, http_find_header);
18291 +/* {{{ void http_send_header_zval(char*, zval **, zend_bool) */
18292 +PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC)
18294 + if (!val || !*val || Z_TYPE_PP(val) == IS_NULL || (Z_TYPE_PP(val) == IS_STRING && !Z_STRLEN_PP(val))) {
18295 + http_hide_header_ex(name, name_len);
18296 + } else if (Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT) {
18297 + zend_bool first = replace;
18299 + HashPosition pos;
18301 + FOREACH_HASH_VAL(pos, HASH_OF(*val), data_ptr) {
18302 + zval *data = http_zsep(IS_STRING, *data_ptr);
18304 + http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), first, NULL);
18305 + zval_ptr_dtor(&data);
18309 + zval *data = http_zsep(IS_STRING, *val);
18311 + http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), replace, NULL);
18312 + zval_ptr_dtor(&data);
18317 +/* {{{ STATUS http_send_header(char *, char *, zend_bool) */
18318 +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)
18322 + if (value && value_len) {
18323 + size_t header_len = sizeof(": ") + name_len + value_len + 1;
18324 + char *header = emalloc(header_len + 1);
18326 + header[header_len] = '\0';
18327 + header_len = snprintf(header, header_len, "%s: %s", name, value);
18328 + ret = http_send_header_string_ex(header, header_len, replace);
18329 + if (sent_header) {
18330 + *sent_header = header;
18335 + http_hide_header_ex(name, name_len);
18342 +/* {{{ STATUS http_send_status_header(int, char *) */
18343 +PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC)
18346 + sapi_header_line h = {(char *) header, header_len, status};
18347 + if (SUCCESS != (ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, &h TSRMLS_CC))) {
18348 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status);
18354 +/* {{{ STATUS http_send_last_modified(int) */
18355 +PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC)
18358 + char *date = http_date(t);
18364 + ret = http_send_header_ex("Last-Modified", lenof("Last-Modified"), date, strlen(date), 1, sent_header);
18368 + HTTP_G->send.last_modified = t;
18374 +/* {{{ STATUS http_send_etag(char *, size_t) */
18375 +PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC)
18378 + char *etag_header;
18379 + size_t etag_header_len;
18382 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G->send.unquoted_etag);
18386 + etag_header_len = spprintf(&etag_header, 0, "ETag: \"%s\"", etag);
18387 + status = http_send_header_string_ex(etag_header, etag_header_len, 1);
18390 + STR_SET(HTTP_G->send.unquoted_etag, estrndup(etag, etag_len));
18392 + if (sent_header) {
18393 + *sent_header = etag_header;
18395 + efree(etag_header);
18402 +/* {{{ STATUS http_send_content_type(char *, size_t) */
18403 +PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC)
18405 + HTTP_CHECK_CONTENT_TYPE(content_type, return FAILURE);
18407 + /* remember for multiple ranges */
18408 + STR_FREE(HTTP_G->send.content_type);
18409 + HTTP_G->send.content_type = estrndup(content_type, ct_len);
18411 + return http_send_header_ex("Content-Type", lenof("Content-Type"), content_type, ct_len, 1, NULL);
18415 +/* {{{ STATUS http_send_content_disposition(char *, size_t, zend_bool) */
18416 +PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC)
18421 + if (send_inline) {
18422 + cd_header = ecalloc(1, sizeof("Content-Disposition: inline; filename=\"\"") + f_len);
18423 + sprintf(cd_header, "Content-Disposition: inline; filename=\"%s\"", filename);
18425 + cd_header = ecalloc(1, sizeof("Content-Disposition: attachment; filename=\"\"") + f_len);
18426 + sprintf(cd_header, "Content-Disposition: attachment; filename=\"%s\"", filename);
18429 + status = http_send_header_string(cd_header);
18430 + efree(cd_header);
18435 +/* {{{ STATUS http_send(void *, size_t, http_send_mode) */
18436 +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)
18439 + HashTable ranges;
18440 + http_range_status range_status;
18445 + if (!data_size) {
18449 + /* enable partial dl and resume */
18450 + http_send_header_string("Accept-Ranges: bytes");
18452 + zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0);
18453 + range_status = http_get_request_ranges(&ranges, data_size);
18455 + switch (range_status) {
18458 + zend_hash_destroy(&ranges);
18459 + http_send_status(416);
18464 + /* Range Request - only send ranges if entity hasn't changed */
18465 + if ( http_got_server_var("HTTP_IF_RANGE") &&
18466 + !http_match_etag("HTTP_IF_RANGE", HTTP_G->send.unquoted_etag) &&
18467 + !http_match_last_modified("HTTP_IF_RANGE", HTTP_G->send.last_modified)) {
18468 + /* fallthrough to send full entity with 200 Ok */
18470 + } else if ( !http_match_etag_ex("HTTP_IF_MATCH", HTTP_G->send.unquoted_etag, 0) ||
18471 + !http_match_last_modified_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G->send.last_modified, 0) ||
18472 + !http_match_last_modified_ex("HTTP_UNLESS_MODIFIED_SINCE", HTTP_G->send.last_modified, 0)) {
18473 + /* 412 Precondition failed */
18474 + zend_hash_destroy(&ranges);
18475 + http_send_status(412);
18477 + } else if (zend_hash_num_elements(&ranges) == 1) {
18478 + /* single range */
18479 + zval **range, **begin, **end;
18481 + if ( SUCCESS != zend_hash_index_find(&ranges, 0, (void *) &range) ||
18482 + SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) ||
18483 + SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) {
18484 + /* this should never happen */
18485 + zend_hash_destroy(&ranges);
18486 + http_send_status(500);
18491 + phpstr_init(&header);
18492 + phpstr_appendf(&header, "Content-Range: bytes %ld-%ld/%zu", Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size);
18493 + phpstr_fix(&header);
18494 + http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
18495 + phpstr_dtor(&header);
18496 + http_send_response_start(&s, Z_LVAL_PP(end)-Z_LVAL_PP(begin)+1);
18497 + http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1);
18498 + http_send_response_finish(&s);
18499 + zend_hash_destroy(&ranges);
18503 + /* multi range */
18504 + HashPosition pos;
18505 + zval **range, **begin, **end;
18506 + const char *content_type = HTTP_G->send.content_type;
18507 + char boundary_str[32];
18508 + size_t boundary_len;
18509 + phpstr header, preface;
18511 + boundary_len = http_boundary(boundary_str, sizeof(boundary_str));
18512 + phpstr_init(&header);
18513 + phpstr_appendf(&header, "Content-Type: multipart/byteranges; boundary=%s", boundary_str);
18514 + phpstr_fix(&header);
18515 + http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
18516 + phpstr_dtor(&header);
18517 + http_send_response_start(&s, 0);
18519 + if (!content_type) {
18520 + content_type = "application/x-octetstream";
18523 + phpstr_init(&preface);
18524 + FOREACH_HASH_VAL(pos, &ranges, range) {
18525 + if ( SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) &&
18526 + SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) {
18528 +#define HTTP_RANGE_PREFACE \
18529 + HTTP_CRLF "--%s" \
18530 + HTTP_CRLF "Content-Type: %s" \
18531 + HTTP_CRLF "Content-Range: bytes %ld-%ld/%zu" \
18532 + HTTP_CRLF HTTP_CRLF
18534 + phpstr_appendf(&preface, HTTP_RANGE_PREFACE, boundary_str, content_type, Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size);
18535 + phpstr_fix(&preface);
18536 + http_send_response_data_plain(&s, PHPSTR_VAL(&preface), PHPSTR_LEN(&preface));
18537 + phpstr_reset(&preface);
18538 + http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1);
18541 + phpstr_dtor(&preface);
18543 + http_send_response_data_plain(&s, HTTP_CRLF "--", lenof(HTTP_CRLF "--"));
18544 + http_send_response_data_plain(&s, boundary_str, boundary_len);
18545 + http_send_response_data_plain(&s, "--", lenof("--"));
18547 + http_send_response_finish(&s);
18548 + zend_hash_destroy(&ranges);
18554 + zend_hash_destroy(&ranges);
18556 + /* send 304 Not Modified if etag matches - DON'T return on ETag generation failure */
18557 + if (!no_cache && (http_interrupt_ob_etaghandler() || (HTTP_G->send.unquoted_etag != NULL))) {
18558 + char *etag = NULL;
18560 + if (HTTP_G->send.unquoted_etag) {
18561 + etag = estrdup(HTTP_G->send.unquoted_etag);
18564 + if (etag || (etag = http_etag(data_ptr, data_size, data_mode))) {
18565 + char *sent_header = NULL;
18567 + http_send_etag_ex(etag, strlen(etag), &sent_header);
18568 + if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
18569 + return http_exit_ex(304, sent_header, NULL, 0);
18571 + STR_FREE(sent_header);
18572 + /* no caching for Last-Modified if ETags really don't match */
18573 + no_cache = http_got_server_var("HTTP_IF_NONE_MATCH");
18579 + /* send 304 Not Modified if last modified matches */
18580 + if (!no_cache && HTTP_G->send.last_modified && http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G->send.last_modified)) {
18581 + char *sent_header = NULL;
18582 + http_send_last_modified_ex(HTTP_G->send.last_modified, &sent_header);
18583 + return http_exit_ex(304, sent_header, NULL, 0);
18586 + /* send full response */
18587 + http_send_response_start(&s, data_size);
18588 + http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, 0, data_size);
18589 + http_send_response_finish(&s);
18597 +/* {{{ STATUS http_send_stream(php_stream *) */
18598 +PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file, zend_bool close_stream, zend_bool no_cache TSRMLS_DC)
18601 + php_stream_statbuf ssb;
18604 + if ((!file) || php_stream_stat(file, &ssb)) {
18605 + char *defct = sapi_get_default_content_type(TSRMLS_C);
18607 + http_hide_header("Content-Disposition");
18608 + http_send_content_type(defct, strlen(defct));
18609 + http_error(HE_WARNING, HTTP_E_RESPONSE, "File not found; stat failed");
18612 + if (HTTP_G->send.not_found_404) {
18613 + http_exit_ex(404, NULL, estrdup("File not found\n"), 0);
18618 + orig_flags = file->flags;
18619 + file->flags |= PHP_STREAM_FLAG_NO_BUFFER;
18620 + status = http_send_ex(file, ssb.sb.st_size, SEND_RSRC, no_cache);
18621 + file->flags = orig_flags;
18623 + if (close_stream) {
18624 + php_stream_close(file);
18631 +/* {{{ char *http_guess_content_type(char *magic_file, long magic_mode, void *data, size_t size, http_send_mode mode) */
18632 +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)
18636 +#ifdef HTTP_HAVE_MAGIC
18637 + struct magic_set *magic = NULL;
18639 + HTTP_CHECK_OPEN_BASEDIR(magicfile, return NULL);
18642 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Supplied payload is empty");
18643 + } else if (!(magic = magic_open(magicmode &~ MAGIC_MIME))) {
18644 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid magic mode: %ld", magicmode);
18645 + } else if (-1 == magic_load(magic, magicfile)) {
18646 + http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to load magic database '%s' (%s)", magicfile, magic_error(magic));
18648 + const char *ctype = NULL;
18650 + magic_setflags(magic, magicmode);
18652 + switch (data_mode) {
18658 + b_len = php_stream_copy_to_mem(data_ptr, &buffer, 65536, 0);
18659 + ctype = magic_buffer(magic, buffer, b_len);
18665 + ctype = magic_buffer(magic, data_ptr, data_len);
18669 + HTTP_CHECK_OPEN_BASEDIR(data_ptr, magic_close(magic); return NULL);
18670 + ctype = magic_file(magic, data_ptr);
18675 + ct = estrdup(ctype);
18677 + http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to guess Content-Type: %s", magic_error(magic));
18681 + magic_close(magic);
18684 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
18692 + * Local variables:
18694 + * c-basic-offset: 4
18696 + * vim600: sw=4 ts=4 fdm=marker
18697 + * vim<600: sw=4 ts=4
18701 +++ b/ext/http/http_url_api.c
18704 + +--------------------------------------------------------------------+
18706 + +--------------------------------------------------------------------+
18707 + | Redistribution and use in source and binary forms, with or without |
18708 + | modification, are permitted provided that the conditions mentioned |
18709 + | in the accompanying LICENSE file are met. |
18710 + +--------------------------------------------------------------------+
18711 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
18712 + +--------------------------------------------------------------------+
18715 +/* $Id: http_url_api.c 292841 2009-12-31 08:48:57Z mike $ */
18717 +#define HTTP_WANT_SAPI
18718 +#define HTTP_WANT_NETDB
18719 +#include "php_http.h"
18721 +#include "zend_ini.h"
18722 +#include "php_output.h"
18723 +#include "ext/standard/php_string.h"
18725 +#include "php_http_api.h"
18726 +#include "php_http_querystring_api.h"
18727 +#include "php_http_url_api.h"
18729 +static inline char *localhostname(void)
18731 + char hostname[1024] = {0};
18734 + if (SUCCESS == gethostname(hostname, lenof(hostname))) {
18735 + return estrdup(hostname);
18737 +#elif defined(HAVE_GETHOSTNAME)
18738 + if (SUCCESS == gethostname(hostname, lenof(hostname))) {
18739 +# if defined(HAVE_GETDOMAINNAME)
18740 + size_t hlen = strlen(hostname);
18741 + if (hlen <= lenof(hostname) - lenof("(none)")) {
18742 + hostname[hlen++] = '.';
18743 + if (SUCCESS == getdomainname(&hostname[hlen], lenof(hostname) - hlen)) {
18744 + if (!strcmp(&hostname[hlen], "(none)")) {
18745 + hostname[hlen - 1] = '\0';
18747 + return estrdup(hostname);
18751 + if (strcmp(hostname, "(none)")) {
18752 + return estrdup(hostname);
18756 + return estrndup("localhost", lenof("localhost"));
18759 +PHP_MINIT_FUNCTION(http_url)
18761 + HTTP_LONG_CONSTANT("HTTP_URL_REPLACE", HTTP_URL_REPLACE);
18762 + HTTP_LONG_CONSTANT("HTTP_URL_JOIN_PATH", HTTP_URL_JOIN_PATH);
18763 + HTTP_LONG_CONSTANT("HTTP_URL_JOIN_QUERY", HTTP_URL_JOIN_QUERY);
18764 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_USER", HTTP_URL_STRIP_USER);
18765 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PASS", HTTP_URL_STRIP_PASS);
18766 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_AUTH", HTTP_URL_STRIP_AUTH);
18767 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PORT", HTTP_URL_STRIP_PORT);
18768 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PATH", HTTP_URL_STRIP_PATH);
18769 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_QUERY", HTTP_URL_STRIP_QUERY);
18770 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_FRAGMENT", HTTP_URL_STRIP_FRAGMENT);
18771 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_ALL", HTTP_URL_STRIP_ALL);
18772 + HTTP_LONG_CONSTANT("HTTP_URL_FROM_ENV", HTTP_URL_FROM_ENV);
18776 +PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC)
18778 + char *abs = NULL;
18779 + php_url *purl = NULL;
18782 + purl = php_url_parse(abs = estrdup(url));
18783 + STR_SET(abs, NULL);
18785 + http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", url);
18790 + http_build_url(flags, purl, NULL, NULL, &abs, NULL);
18793 + php_url_free(purl);
18799 +/* {{{ void http_build_url(int flags, const php_url *, const php_url *, php_url **, char **, size_t *) */
18800 +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)
18802 +#if defined(HAVE_GETSERVBYPORT) || defined(HAVE_GETSERVBYNAME)
18803 + struct servent *se;
18805 + php_url *url = ecalloc(1, sizeof(php_url));
18807 +#define __URLSET(u,n) \
18809 +#define __URLCPY(n) \
18810 + url->n = __URLSET(new_url,n) ? estrdup(new_url->n) : (__URLSET(old_url,n) ? estrdup(old_url->n) : NULL)
18812 + if (!(flags & HTTP_URL_STRIP_PORT)) {
18813 + url->port = __URLSET(new_url, port) ? new_url->port : ((old_url) ? old_url->port : 0);
18815 + if (!(flags & HTTP_URL_STRIP_USER)) {
18818 + if (!(flags & HTTP_URL_STRIP_PASS)) {
18822 + __URLCPY(scheme);
18825 + if (!(flags & HTTP_URL_STRIP_PATH)) {
18826 + if ((flags & HTTP_URL_JOIN_PATH) && __URLSET(old_url, path) && __URLSET(new_url, path) && *new_url->path != '/') {
18827 + size_t old_path_len = strlen(old_url->path), new_path_len = strlen(new_url->path);
18829 + url->path = ecalloc(1, old_path_len + new_path_len + 1 + 1);
18831 + strcat(url->path, old_url->path);
18832 + if (url->path[old_path_len - 1] != '/') {
18833 + php_dirname(url->path, old_path_len);
18834 + strcat(url->path, "/");
18836 + strcat(url->path, new_url->path);
18841 + if (!(flags & HTTP_URL_STRIP_QUERY)) {
18842 + if ((flags & HTTP_URL_JOIN_QUERY) && __URLSET(new_url, query) && __URLSET(old_url, query)) {
18845 + INIT_PZVAL(&qstr);
18846 + INIT_PZVAL(&qarr);
18847 + array_init(&qarr);
18849 + ZVAL_STRING(&qstr, old_url->query, 0);
18850 + http_querystring_modify(&qarr, &qstr);
18851 + ZVAL_STRING(&qstr, new_url->query, 0);
18852 + http_querystring_modify(&qarr, &qstr);
18854 + ZVAL_NULL(&qstr);
18855 + http_querystring_update(&qarr, &qstr);
18856 + url->query = Z_STRVAL(qstr);
18857 + zval_dtor(&qarr);
18862 + if (!(flags & HTTP_URL_STRIP_FRAGMENT)) {
18863 + __URLCPY(fragment);
18866 + if (!url->scheme) {
18867 + if (flags & HTTP_URL_FROM_ENV) {
18868 + zval *https = http_get_server_var("HTTPS", 1);
18869 + if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) {
18870 + url->scheme = estrndup("https", lenof("https"));
18871 + } else switch (url->port) {
18873 + url->scheme = estrndup("https", lenof("https"));
18876 +#ifndef HAVE_GETSERVBYPORT
18881 + url->scheme = estrndup("http", lenof("http"));
18884 +#ifdef HAVE_GETSERVBYPORT
18886 + if ((se = getservbyport(htons(url->port), "tcp")) && se->s_name) {
18887 + url->scheme = estrdup(se->s_name);
18889 + url->scheme = estrndup("http", lenof("http"));
18895 + url->scheme = estrndup("http", lenof("http"));
18899 + if (!url->host) {
18900 + if (flags & HTTP_URL_FROM_ENV) {
18903 + if ((((zhost = http_get_server_var("HTTP_HOST", 1)) ||
18904 + (zhost = http_get_server_var("SERVER_NAME", 1)))) && Z_STRLEN_P(zhost)) {
18905 + url->host = estrndup(Z_STRVAL_P(zhost), Z_STRLEN_P(zhost));
18907 + url->host = localhostname();
18910 + url->host = estrndup("localhost", lenof("localhost"));
18914 + if (!url->path) {
18915 + if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) {
18916 + const char *q = strchr(SG(request_info).request_uri, '?');
18919 + url->path = estrndup(SG(request_info).request_uri, q - SG(request_info).request_uri);
18921 + url->path = estrdup(SG(request_info).request_uri);
18924 + url->path = estrndup("/", 1);
18926 + } else if (url->path[0] != '/') {
18927 + if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) {
18928 + size_t ulen = strlen(SG(request_info).request_uri);
18929 + size_t plen = strlen(url->path);
18932 + if (SG(request_info).request_uri[ulen-1] != '/') {
18933 + for (--ulen; ulen && SG(request_info).request_uri[ulen - 1] != '/'; --ulen);
18936 + path = emalloc(ulen + plen + 1);
18937 + memcpy(path, SG(request_info).request_uri, ulen);
18938 + memcpy(path + ulen, url->path, plen);
18939 + path[ulen + plen] = '\0';
18940 + STR_SET(url->path, path);
18942 + size_t plen = strlen(url->path);
18943 + char *path = emalloc(plen + 1 + 1);
18946 + memcpy(&path[1], url->path, plen + 1);
18947 + STR_SET(url->path, path);
18950 + /* replace directory references if path is not a single slash */
18951 + if (url->path[0] && (url->path[0] != '/' || url->path[1])) {
18952 + char *ptr, *end = url->path + strlen(url->path) + 1;
18954 + for (ptr = strstr(url->path, "/."); ptr; ptr = strstr(ptr, "/.")) {
18955 + switch (ptr[2]) {
18961 + memmove(&ptr[1], &ptr[3], end - &ptr[3]);
18965 + if (ptr[3] == '/') {
18966 + char *pos = &ptr[4];
18967 + while (ptr != url->path) {
18968 + if (*--ptr == '/') {
18972 + memmove(&ptr[1], pos, end - pos);
18974 + } else if (!ptr[3]) {
18975 + /* .. at the end */
18978 + /* fallthrough */
18981 + /* something else */
18989 + if ( ((url->port == 80) && !strcmp(url->scheme, "http"))
18990 + || ((url->port ==443) && !strcmp(url->scheme, "https"))
18991 +#ifdef HAVE_GETSERVBYNAME
18992 + || ((se = getservbyname(url->scheme, "tcp")) && se->s_port &&
18993 + (url->port == ntohs(se->s_port)))
19003 + *url_str = emalloc(HTTP_URL_MAXLEN + 1);
19005 + **url_str = '\0';
19006 + strlcat(*url_str, url->scheme, HTTP_URL_MAXLEN);
19007 + strlcat(*url_str, "://", HTTP_URL_MAXLEN);
19009 + if (url->user && *url->user) {
19010 + strlcat(*url_str, url->user, HTTP_URL_MAXLEN);
19011 + if (url->pass && *url->pass) {
19012 + strlcat(*url_str, ":", HTTP_URL_MAXLEN);
19013 + strlcat(*url_str, url->pass, HTTP_URL_MAXLEN);
19015 + strlcat(*url_str, "@", HTTP_URL_MAXLEN);
19018 + strlcat(*url_str, url->host, HTTP_URL_MAXLEN);
19021 + char port_str[8];
19023 + snprintf(port_str, sizeof(port_str), "%d", (int) url->port);
19024 + strlcat(*url_str, ":", HTTP_URL_MAXLEN);
19025 + strlcat(*url_str, port_str, HTTP_URL_MAXLEN);
19028 + strlcat(*url_str, url->path, HTTP_URL_MAXLEN);
19030 + if (url->query && *url->query) {
19031 + strlcat(*url_str, "?", HTTP_URL_MAXLEN);
19032 + strlcat(*url_str, url->query, HTTP_URL_MAXLEN);
19035 + if (url->fragment && *url->fragment) {
19036 + strlcat(*url_str, "#", HTTP_URL_MAXLEN);
19037 + strlcat(*url_str, url->fragment, HTTP_URL_MAXLEN);
19040 + if (HTTP_URL_MAXLEN == (len = strlen(*url_str))) {
19041 + http_error(HE_NOTICE, HTTP_E_URL, "Length of URL exceeds HTTP_URL_MAXLEN");
19051 + php_url_free(url);
19056 +/* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
19057 +PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep,
19058 + char *pre_encoded_data, size_t pre_encoded_len,
19059 + char **encoded_data, size_t *encoded_len TSRMLS_DC)
19062 + size_t arg_sep_len;
19063 + phpstr *qstr = phpstr_new();
19065 + if (override_argsep || !(arg_sep_len = strlen(arg_sep = INI_STR("arg_separator.output")))) {
19066 + arg_sep = HTTP_URL_ARGSEP;
19067 + arg_sep_len = lenof(HTTP_URL_ARGSEP);
19070 + if (pre_encoded_len && pre_encoded_data) {
19071 + phpstr_append(qstr, pre_encoded_data, pre_encoded_len);
19074 + if (SUCCESS != http_urlencode_hash_recursive(hash, qstr, arg_sep, arg_sep_len, NULL, 0)) {
19075 + phpstr_free(&qstr);
19079 + phpstr_data(qstr, encoded_data, encoded_len);
19080 + phpstr_free(&qstr);
19086 +/* {{{ http_urlencode_hash_recursive */
19087 +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)
19089 + HashKey key = initHashKey(0);
19090 + zval **data = NULL;
19091 + HashPosition pos;
19093 + if (!ht || !str) {
19094 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters");
19097 + if (ht->nApplyCount > 0) {
19101 + FOREACH_HASH_KEYVAL(pos, ht, key, data) {
19102 + char *encoded_key;
19104 + phpstr new_prefix;
19106 + if (!data || !*data) {
19107 + phpstr_dtor(str);
19111 + if (key.type == HASH_KEY_IS_STRING) {
19113 + /* only public properties */
19116 + if (key.len && key.str[key.len - 1] == '\0') {
19119 + encoded_key = php_url_encode(key.str, key.len, &encoded_len);
19121 + encoded_len = spprintf(&encoded_key, 0, "%ld", key.num);
19125 + phpstr_init(&new_prefix);
19126 + if (prefix && prefix_len) {
19127 + phpstr_append(&new_prefix, prefix, prefix_len);
19128 + phpstr_appends(&new_prefix, "%5B");
19131 + phpstr_append(&new_prefix, encoded_key, encoded_len);
19132 + efree(encoded_key);
19134 + if (prefix && prefix_len) {
19135 + phpstr_appends(&new_prefix, "%5D");
19137 + phpstr_fix(&new_prefix);
19140 + if (Z_TYPE_PP(data) == IS_ARRAY || Z_TYPE_PP(data) == IS_OBJECT) {
19142 + ++ht->nApplyCount;
19143 + status = http_urlencode_hash_recursive(HASH_OF(*data), str, arg_sep, arg_sep_len, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
19144 + --ht->nApplyCount;
19145 + if (SUCCESS != status) {
19146 + phpstr_dtor(&new_prefix);
19147 + phpstr_dtor(str);
19151 + zval *val = http_zsep(IS_STRING, *data);
19153 + if (PHPSTR_LEN(str)) {
19154 + phpstr_append(str, arg_sep, arg_sep_len);
19156 + phpstr_append(str, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
19157 + phpstr_appends(str, "=");
19159 + if (Z_STRLEN_P(val) && Z_STRVAL_P(val)) {
19160 + char *encoded_val;
19163 + encoded_val = php_url_encode(Z_STRVAL_P(val), Z_STRLEN_P(val), &encoded_len);
19164 + phpstr_append(str, encoded_val, encoded_len);
19165 + efree(encoded_val);
19168 + zval_ptr_dtor(&val);
19170 + phpstr_dtor(&new_prefix);
19177 + * Local variables:
19179 + * c-basic-offset: 4
19181 + * vim600: noet sw=4 ts=4 fdm=marker
19182 + * vim<600: noet sw=4 ts=4
19186 +++ b/ext/http/http_util_object.c
19189 + +--------------------------------------------------------------------+
19191 + +--------------------------------------------------------------------+
19192 + | Redistribution and use in source and binary forms, with or without |
19193 + | modification, are permitted provided that the conditions mentioned |
19194 + | in the accompanying LICENSE file are met. |
19195 + +--------------------------------------------------------------------+
19196 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
19197 + +--------------------------------------------------------------------+
19200 +/* $Id: http_util_object.c 292841 2009-12-31 08:48:57Z mike $ */
19202 +#include "php_http.h"
19204 +#ifdef ZEND_ENGINE_2
19206 +#include "ext/standard/php_http.h"
19208 +#include "php_http_util_object.h"
19210 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpUtil, method, 0, req_args)
19211 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpUtil, method, 0)
19213 +#define HTTP_UTIL_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpUtil, method))
19215 +HTTP_BEGIN_ARGS(date, 0)
19216 + HTTP_ARG_VAL(timestamp, 0)
19219 +HTTP_BEGIN_ARGS(buildStr, 1)
19220 + HTTP_ARG_VAL(query, 0)
19221 + HTTP_ARG_VAL(prefix, 0)
19222 + HTTP_ARG_VAL(arg_sep, 0)
19225 +HTTP_BEGIN_ARGS(buildUrl, 1)
19226 + HTTP_ARG_VAL(url, 0)
19227 + HTTP_ARG_VAL(parts, 0)
19228 + HTTP_ARG_VAL(flags, 0)
19229 + HTTP_ARG_VAL(composed, 1)
19232 +HTTP_BEGIN_ARGS(negotiateLanguage, 1)
19233 + HTTP_ARG_VAL(supported, 0)
19234 + HTTP_ARG_VAL(result, 1)
19237 +HTTP_BEGIN_ARGS(negotiateCharset, 1)
19238 + HTTP_ARG_VAL(supported, 0)
19239 + HTTP_ARG_VAL(result, 1)
19242 +HTTP_BEGIN_ARGS(negotiateContentType, 1)
19243 + HTTP_ARG_VAL(supported, 0)
19244 + HTTP_ARG_VAL(result, 1)
19247 +HTTP_BEGIN_ARGS(matchModified, 1)
19248 + HTTP_ARG_VAL(last_modified, 0)
19249 + HTTP_ARG_VAL(for_range, 0)
19252 +HTTP_BEGIN_ARGS(matchEtag, 1)
19253 + HTTP_ARG_VAL(plain_etag, 0)
19254 + HTTP_ARG_VAL(for_range, 0)
19257 +HTTP_BEGIN_ARGS(matchRequestHeader, 2)
19258 + HTTP_ARG_VAL(header_name, 0)
19259 + HTTP_ARG_VAL(header_value, 0)
19260 + HTTP_ARG_VAL(case_sensitive, 0)
19263 +HTTP_BEGIN_ARGS(parseMessage, 1)
19264 + HTTP_ARG_VAL(message_string, 0)
19267 +HTTP_BEGIN_ARGS(parseHeaders, 1)
19268 + HTTP_ARG_VAL(headers_string, 0)
19271 +HTTP_BEGIN_ARGS(parseCookie, 1)
19272 + HTTP_ARG_VAL(cookie_string, 0)
19275 +HTTP_BEGIN_ARGS(buildCookie, 1)
19276 + HTTP_ARG_VAL(cookie_array, 0)
19279 +HTTP_BEGIN_ARGS(parseParams, 1)
19280 + HTTP_ARG_VAL(param_string, 0)
19281 + HTTP_ARG_VAL(flags, 0)
19284 +HTTP_BEGIN_ARGS(chunkedDecode, 1)
19285 + HTTP_ARG_VAL(encoded_string, 0)
19288 +#ifdef HTTP_HAVE_ZLIB
19289 +HTTP_BEGIN_ARGS(deflate, 1)
19290 + HTTP_ARG_VAL(plain, 0)
19291 + HTTP_ARG_VAL(flags, 0)
19294 +HTTP_BEGIN_ARGS(inflate, 1)
19295 + HTTP_ARG_VAL(encoded, 0)
19299 +HTTP_BEGIN_ARGS(support, 0)
19300 + HTTP_ARG_VAL(feature, 0)
19303 +zend_class_entry *http_util_object_ce;
19304 +zend_function_entry http_util_object_fe[] = {
19305 + HTTP_UTIL_ALIAS(date, http_date)
19306 + HTTP_UTIL_ALIAS(buildUrl, http_build_url)
19307 + HTTP_UTIL_ALIAS(buildStr, http_build_str)
19308 + HTTP_UTIL_ALIAS(negotiateLanguage, http_negotiate_language)
19309 + HTTP_UTIL_ALIAS(negotiateCharset, http_negotiate_charset)
19310 + HTTP_UTIL_ALIAS(negotiateContentType, http_negotiate_content_type)
19311 + HTTP_UTIL_ALIAS(matchModified, http_match_modified)
19312 + HTTP_UTIL_ALIAS(matchEtag, http_match_etag)
19313 + HTTP_UTIL_ALIAS(matchRequestHeader, http_match_request_header)
19314 + HTTP_UTIL_ALIAS(parseMessage, http_parse_message)
19315 + HTTP_UTIL_ALIAS(parseHeaders, http_parse_headers)
19316 + HTTP_UTIL_ALIAS(parseCookie, http_parse_cookie)
19317 + HTTP_UTIL_ALIAS(buildCookie, http_build_cookie)
19318 + HTTP_UTIL_ALIAS(parseParams, http_parse_params)
19319 + HTTP_UTIL_ALIAS(chunkedDecode, http_chunked_decode)
19320 +#ifdef HTTP_HAVE_ZLIB
19321 + HTTP_UTIL_ALIAS(deflate, http_deflate)
19322 + HTTP_UTIL_ALIAS(inflate, http_inflate)
19323 +#endif /* HTTP_HAVE_ZLIB */
19324 + HTTP_UTIL_ALIAS(support, http_support)
19326 + EMPTY_FUNCTION_ENTRY
19329 +PHP_MINIT_FUNCTION(http_util_object)
19331 + HTTP_REGISTER_CLASS(HttpUtil, http_util_object, NULL, 0);
19335 +#endif /* ZEND_ENGINE_2 */
19338 + * Local variables:
19340 + * c-basic-offset: 4
19342 + * vim600: noet sw=4 ts=4 fdm=marker
19343 + * vim<600: noet sw=4 ts=4
19347 +++ b/ext/http/lib/BigGet.php
19352 + * BigGet - download big files efficiently
19353 + * $Id: BigGet.php 220502 2006-09-25 08:27:32Z mike $
19355 + * @copyright Michael Wallner, <mike@iworks.at>
19356 + * @license BSD, revised
19357 + * @version $Revision: 220502 $
19359 +class BigGet extends HttpRequestPool
19362 + * File split size
19364 + const SIZE = 1048576;
19367 + * Parallel Request count
19372 + * Whether to output debug messages
19376 + public $dbg = false;
19386 + * Temp file prefix
19393 + * Size of requested resource
19400 + * Whether the requests have been sent
19404 + private $sent = false;
19407 + * Request counter
19411 + private $count = 0;
19414 + * Static constructor
19416 + * @param string $url
19417 + * @param string $tmp
19419 + * @throws Exception
19421 + public static function url($url, $tmp = '/tmp')
19423 + $head = new HttpRequest($url, HttpRequest::METH_HEAD);
19424 + $headers = $head->send()->getHeaders();
19426 + if (200 != $head->getResponseCode()) {
19427 + throw new HttpException("Did not receive '200 Ok' from HEAD $url");
19429 + if (!isset($headers['Accept-Ranges'])) {
19430 + throw new HttpException("Did not receive an Accept-Ranges header from HEAD $url");
19432 + if (!isset($headers['Content-Length'])) {
19433 + throw new HttpException("Did not receive a Content-Length header from HEAD $url");
19436 + $bigget = new BigGet;
19437 + $bigget->url = $url;
19438 + $bigget->tmp = tempnam($tmp, 'BigGet.');
19439 + $bigget->size = $headers['Content-Length'];
19444 + * Save the resource to a file
19446 + * @param string $file
19448 + * @throws Exception
19450 + public function saveTo($file)
19452 + $this->sent or $this->send();
19454 + if ($w = fopen($this->tmp, 'wb')) {
19456 + $this->dbg && print "\nCopying temp files to $file ...\n";
19458 + foreach (glob($this->tmp .".????") as $tmp) {
19460 + $this->dbg && print "\t$tmp\n";
19462 + if ($r = fopen($tmp, 'rb')) {
19463 + stream_copy_to_stream($r, $w);
19469 + rename($this->tmp, $file);
19471 + $this->dbg && print "\nDone.\n";
19479 + * Overrides HttpRequestPool::send()
19482 + * @throws Exception
19484 + public function send()
19486 + $this->sent = true;
19488 + // use max RMAX simultanous requests with a req size of SIZE
19489 + while ($this->count < self::RMAX && -1 != $offset = $this->getRangeOffset()) {
19490 + $this->attachNew($offset);
19493 + while ($this->socketPerform()) {
19494 + if (!$this->socketSelect()) {
19495 + throw new HttpSocketException;
19501 + * Overrides HttpRequestPool::socketPerform()
19505 + protected function socketPerform()
19507 + $rs = parent::socketPerform();
19509 + foreach ($this->getFinishedRequests() as $r) {
19510 + $this->detach($r);
19512 + if (206 != $rc = $r->getResponseCode()) {
19513 + throw new HttpException("Unexpected response code: $rc");
19516 + file_put_contents(sprintf("%s.%04d", $this->tmp, $r->id), $r->getResponseBody());
19518 + if (-1 != $offset = $this->getRangeOffset()) {
19519 + $this->attachNew($offset);
19526 + private function attachNew($offset)
19528 + $stop = min($this->count * self::SIZE + self::SIZE, $this->size) - 1;
19530 + $this->dbg && print "Attaching new request to get range: $offset-$stop\n";
19532 + $req = new BigGetRequest(
19534 + HttpRequest::METH_GET,
19536 + 'headers' => array(
19537 + 'Range' => "bytes=$offset-$stop"
19541 + $this->attach($req);
19542 + $req->id = $this->count++;
19545 + private function getRangeOffset()
19547 + return ($this->size >= $start = $this->count * self::SIZE) ? $start : -1;
19556 +class BigGetRequest extends HttpRequest
19563 +++ b/ext/http/lib/FeedAggregator.php
19568 + * Simple Feed Aggregator
19569 + * $Id: FeedAggregator.php 208774 2006-03-06 16:07:19Z mike $
19571 + * @copyright Michael Wallner, <mike@iworks.at>
19572 + * @license BSD, revised
19573 + * @package pecl/http
19574 + * @version $Revision: 208774 $
19576 +class FeedAggregator
19579 + * Cache directory
19583 + public $directory;
19590 + protected $feeds = array();
19595 + * @param string $directory
19597 + public function __construct($directory = 'feeds')
19599 + $this->setDirectory($directory);
19603 + * Set cache directory
19605 + * @param string $directory
19607 + public function setDirectory($directory)
19609 + $this->directory = $directory;
19610 + foreach (glob($this->directory .'/*.xml') as $feed) {
19611 + $this->feeds[basename($feed, '.xml')] = filemtime($feed);
19616 + * Strips all special chars
19618 + * @param string $url
19621 + public function url2name($url)
19623 + return preg_replace('/[^\w\.-]+/', '_', $url);
19627 + * Checks if $url is a known feed
19629 + * @param string $url
19632 + public function hasFeed($url)
19634 + return isset($this->feeds[$this->url2name($url)]);
19638 + * Add an URL as feed
19640 + * @param string $url
19642 + * @throws Exception
19644 + public function addFeed($url)
19646 + $r = $this->setupRequest($url);
19648 + $this->handleResponse($r);
19652 + * Add several URLs as feeds
19654 + * @param array $urls
19656 + * @throws Exception
19658 + public function addFeeds(array $urls)
19660 + $pool = new HttpRequestPool;
19661 + foreach ($urls as $url) {
19662 + $pool->attach($r = $this->setupRequest($url));
19666 + foreach ($pool as $request) {
19667 + $this->handleResponse($request);
19672 + * Load a feed (from cache)
19674 + * @param string $url
19676 + * @throws Exception
19678 + public function getFeed($url)
19680 + $this->addFeed($url);
19681 + return $this->loadFeed($this->url2name($url));
19685 + * Load several feeds (from cache)
19687 + * @param array $urls
19689 + * @throws Exception
19691 + public function getFeeds(array $urls)
19693 + $feeds = array();
19694 + $this->addFeeds($urls);
19695 + foreach ($urls as $url) {
19696 + $feeds[] = $this->loadFeed($this->url2name($url));
19701 + protected function saveFeed($file, $contents)
19703 + if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) {
19704 + $this->feeds[$file] = time();
19706 + throw new Exception("Could not save feed contents to $file.xml");
19710 + protected function loadFeed($file)
19712 + if (isset($this->feeds[$file])) {
19713 + if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) {
19716 + throw new Exception("Could not load feed contents from $file.xml");
19719 + throw new Exception("Unknown feed/file $file.xml");
19723 + protected function setupRequest($url, $escape = true)
19725 + $r = new HttpRequest($url);
19726 + $r->setOptions(array('redirect' => true));
19728 + $file = $escape ? $this->url2name($url) : $url;
19730 + if (isset($this->feeds[$file])) {
19731 + $r->setOptions(array('lastmodified' => $this->feeds[$file]));
19737 + protected function handleResponse(HttpRequest $r)
19739 + if ($r->getResponseCode() != 304) {
19740 + if ($r->getResponseCode() != 200) {
19741 + throw new Exception("Unexpected response code ". $r->getResponseCode());
19743 + if (!strlen($body = $r->getResponseBody())) {
19744 + throw new Exception("Received empty feed from ". $r->getUrl());
19746 + $this->saveFeed($this->url2name($r->getUrl()), $body);
19753 +++ b/ext/http/lib/PgLobStream.php
19758 + * PostgreSQL LOB stream
19759 + * $Id: PgLobStream.php 210232 2006-03-27 17:41:25Z mike $
19763 + * // GET /image.php?image=1234
19764 + * if (PgLobStream::$loId = (int) $_GET['image']) {
19765 + * if ($lob = fopen('pglob://dbname=database user=mike', 'r')) {
19766 + * HttpResponse::setContentType('image/jpeg');
19767 + * HttpResponse::setStream($lob);
19768 + * HttpResponse::send();
19773 + * @copyright Michael Wallner, <mike@iworks.at>
19774 + * @license BSD, revised
19775 + * @package pecl/http
19776 + * @version $Revision: 210232 $
19783 + private $size = 0;
19785 + public static $loId;
19787 + function stream_open($path, $mode)
19789 + $path = trim(parse_url($path, PHP_URL_HOST));
19792 + if ($this->dbh = pg_connect($path)) {
19793 + if (pg_query($this->dbh, 'BEGIN')) {
19794 + if (is_resource($this->loh = pg_lo_open($this->dbh, $this->lon = self::$loId, $mode))) {
19795 + pg_lo_seek($this->loh, 0, PGSQL_SEEK_END);
19796 + $this->size = (int) pg_lo_tell($this->loh);
19797 + pg_lo_seek($this->loh, 0, PGSQL_SEEK_SET);
19806 + function stream_read($length)
19808 + return pg_lo_read($this->loh, $length);
19811 + function stream_seek($offset, $whence = PGSQL_SEEK_SET)
19813 + return pg_lo_seek($this->loh, $offset, $whence);
19816 + function stream_tell()
19818 + return pg_lo_tell($this->loh);
19821 + function stream_eof()
19823 + return pg_lo_tell($this->loh) >= $this->size;
19826 + function stream_flush()
19831 + function stream_stat()
19833 + return array('size' => $this->size, 'ino' => $this->lon);
19836 + function stream_write($data)
19838 + return pg_lo_write($this->loh, $data);
19841 + function stream_close()
19843 + if (pg_lo_close($this->loh)) {
19844 + return pg_query($this->dbh, 'COMMIT');
19846 + pg_query($this->dbh, 'ROLLBACK');
19852 +stream_register_wrapper('pglob', 'PgLobStream');
19856 +++ b/ext/http/lib/XmlRpcClient.php
19861 + * XMLRPC Client, very KISS
19862 + * $Id: XmlRpcClient.php 227268 2007-01-15 08:01:35Z mike $
19864 + * NOTE: requires ext/xmlrpc
19869 + * $rpc = new XmlRpcClient('http://mike:secret@example.com/cgi-bin/vpop-xmlrpc');
19870 + * $rpc->__request->setOptions(array('compress' => true));
19872 + * print_r($rpc->vpop->listdomain(array('domain' => 'example.com')));
19873 + * } catch (Exception $ex) {
19879 + * @copyright Michael Wallner, <mike@iworks.at>
19880 + * @license BSD, revised
19881 + * @package pecl/http
19882 + * @version $Revision: 227268 $
19884 +class XmlRpcClient
19891 + public $__namespace;
19894 + * HttpRequest instance
19896 + * @var HttpRequest
19898 + public $__request;
19905 + public $__encoding = "iso-8859-1";
19912 + public $__options;
19917 + * @param string $url RPC endpoint
19918 + * @param string $namespace RPC namespace
19919 + * @param array $options HttpRequest options
19921 + public function __construct($url, $namespace = '', array $options = null)
19923 + $this->__request = new HttpRequest($url, HttpRequest::METH_POST, (array) $options);
19924 + $this->__namespace = $namespace;
19928 + * RPC method proxy
19930 + * @param string $method RPC method name
19931 + * @param array $params RPC method arguments
19932 + * @return mixed decoded RPC response
19933 + * @throws Exception
19935 + public function __call($method, array $params)
19937 + if (strlen($this->__namespace)) {
19938 + $method = $this->__namespace .'.'. $method;
19940 + $this->__request->setContentType("text/xml");
19941 + $this->__request->setRawPostData(
19942 + xmlrpc_encode_request($method, $params,
19943 + array("encoding" => $this->__encoding) + (array) $this->__options));
19944 + $response = $this->__request->send();
19945 + if ($response->getResponseCode() != 200) {
19946 + throw new Exception(
19947 + $response->getResponseStatus(),
19948 + $response->getResponseCode()
19952 + $data = xmlrpc_decode($response->getBody(), $this->__encoding);
19953 + if (xmlrpc_is_fault($data)) {
19954 + throw new Exception(
19955 + (string) $data['faultString'],
19956 + (int) $data['faultCode']
19964 + * Returns self, where namespace is set to variable name
19966 + * @param string $ns
19967 + * @return XmlRpcRequest
19969 + public function __get($ns)
19971 + $this->__namespace = $ns;
19978 +++ b/ext/http/lib/XmlRpcServer.php
19982 +XmlRpcServer::setContentType("text/xml");
19983 +XmlRpcServer::capture();
19986 + * XMLRPC Server, very KISS
19987 + * $Id: XmlRpcServer.php 227268 2007-01-15 08:01:35Z mike $
19989 + * NOTE: requires ext/xmlrpc
19994 + * class Handler extends XmlRpcRequestHandlerStub {
19995 + * public function xmlrpcPing(array $values) {
20000 + * XmlRpcServer::factory("namespace")->registerHandler(new Handler);
20001 + * XmlRpcServer::run();
20002 + * } catch (Exception $ex) {
20003 + * XmlRpcServer::error($ex->getCode(), $ex->getMessage());
20007 + * @copyright Michael Wallner, <mike@iworks.at>
20008 + * @license BSD, revised
20009 + * @package pecl/http
20010 + * @version $Revision: 227268 $
20013 +class XmlRpcServer extends HttpResponse
20020 + public static $encoding = "iso-8859-1";
20027 + public $namespace;
20030 + * RPC handler attached to this server instance
20032 + * @var XmlRpcRequestHandler
20034 + protected $handler;
20036 + private static $xmlreq;
20037 + private static $xmlrpc;
20038 + private static $refcnt = 0;
20039 + private static $handle = array();
20042 + * Create a new XmlRpcServer instance
20044 + * @param string $namespace
20045 + * @param string $encoding
20047 + public function __construct($namespace)
20049 + $this->namespace = $namespace;
20050 + self::initialize();
20056 + public function __destruct()
20058 + if (self::$refcnt && !--self::$refcnt) {
20059 + xmlrpc_server_destroy(self::$xmlrpc);
20066 + * @param string $namespace
20067 + * @return XmlRpcServer
20069 + public static function factory($namespace)
20071 + return new XmlRpcServer($namespace);
20075 + * Run all servers and send response
20077 + * @param array $options
20079 + public static function run(array $options = null)
20081 + self::initialize(false, true);
20082 + self::setContentType("text/xml; charset=". self::$encoding);
20083 + echo xmlrpc_server_call_method(self::$xmlrpc, self::$xmlreq, null,
20084 + array("encoding" => self::$encoding) + (array) $options);
20088 + * Test hook; call instead of XmlRpcServer::run()
20090 + * @param string $method
20091 + * @param array $params
20092 + * @param array $request_options
20093 + * @param array $response_options
20095 + public static function test($method, array $params, array $request_options = null, array $response_options = null)
20097 + self::$xmlreq = xmlrpc_encode_request($method, $params, $request_options);
20098 + self::run($response_options);
20102 + * Optional XMLRPC error handler
20104 + * @param int $code
20105 + * @param string $msg
20107 + public static function error($code, $msg, array $options = null)
20109 + echo xmlrpc_encode(array("faultCode" => $code, "faultString" => $msg),
20110 + array("encoding" => self::$encoding) + (array) $options);
20114 + * Register a single method
20116 + * @param string $name
20117 + * @param mixed $callback
20118 + * @param mixed $dispatch
20119 + * @param array $spec
20121 + public function registerMethod($name, $callback, $dispatch = null, array $spec = null)
20123 + if (!is_callable($callback, false, $cb_name)) {
20124 + throw new Exception("$cb_name is not a valid callback");
20126 + if (isset($dispatch)) {
20127 + if (!is_callable($dispatch, false, $cb_name)) {
20128 + throw new Exception("$cb_name is not a valid callback");
20130 + xmlrpc_server_register_method(self::$xmlrpc, $name, $dispatch);
20131 + self::$handle[$name] = $callback;
20133 + xmlrpc_server_register_method(self::$xmlrpc, $name, $callback);
20136 + if (isset($spec)) {
20137 + xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
20142 + * Register an XmlRpcRequestHandler for this server instance
20144 + * @param XmlRpcRequestHandler $handler
20146 + public function registerHandler(XmlRpcRequestHandler $handler)
20148 + $this->handler = $handler;
20150 + foreach (get_class_methods($handler) as $method) {
20151 + if (!strncmp($method, "xmlrpc", 6)) {
20152 + $this->registerMethod(
20153 + $this->method($method, $handler->getNamespace()),
20154 + array($handler, $method), array($this, "dispatch"));
20158 + $handler->getIntrospectionData($spec);
20159 + if (is_array($spec)) {
20160 + xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
20164 + private function method($method, $namespace = null)
20166 + if (!strlen($namespace)) {
20167 + $namespace = strlen($this->namespace) ? $this->namespace : "xmlrpc";
20169 + return $namespace .".". strtolower($method[6]) . substr($method, 7);
20172 + private function dispatch($method, array $params = null)
20174 + if (array_key_exists($method, self::$handle)) {
20175 + return call_user_func(self::$handle[$method], $params);
20177 + throw new Exception("Unknown XMLRPC method: $method");
20180 + private static function initialize($server = true, $data = false)
20183 + if (!self::$xmlreq && !(self::$xmlreq = http_get_request_body())) {
20184 + throw new Exception("Failed to fetch XMLRPC request body");
20188 + if (!self::$xmlrpc && !(self::$xmlrpc = xmlrpc_server_create())) {
20189 + throw new Exception("Failed to initialize XMLRPC server");
20197 + * XmlRpcRequestHandler
20199 + * Define XMLRPC methods with an "xmlrpc" prefix, eg:
20201 + * class IntOp implements XmlRpcRequestHandler {
20202 + * public function getNamespace() {
20205 + * public function getInstrospectionData(array &$spec = null) {
20207 + * // XMLRPC method name: int.sumValues
20208 + * public function xmlrpcSumValues(array $values) {
20209 + * return array_sum($values);
20214 +interface XmlRpcRequestHandler
20216 + public function getNamespace();
20217 + public function getIntrospectionData(array &$spec = null);
20221 + * XmlRpcRequestHandlerStub
20223 +abstract class XmlRpcRequestHandlerStub implements XmlRpcRequestHandler
20225 + public function getNamespace()
20228 + public function getIntrospectionData(array &$spec = null)
20235 +++ b/ext/http/missing.c
20238 + +--------------------------------------------------------------------+
20240 + +--------------------------------------------------------------------+
20241 + | Redistribution and use in source and binary forms, with or without |
20242 + | modification, are permitted provided that the conditions mentioned |
20243 + | in the accompanying LICENSE file are met. |
20244 + +--------------------------------------------------------------------+
20245 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20246 + +--------------------------------------------------------------------+
20249 +/* $Id: missing.c 292841 2009-12-31 08:48:57Z mike $ */
20251 +#ifdef HAVE_CONFIG_H
20252 +# include "config.h"
20256 +#include "missing.h"
20259 +int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC)
20261 + zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS);
20262 + INIT_PZVAL(property);
20263 + ZVAL_DOUBLE(property, value);
20264 + return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
20267 +void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC)
20269 + zval *tmp = ecalloc(1, sizeof(zval));
20270 + ZVAL_DOUBLE(tmp, value);
20271 + zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
20274 +int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC)
20276 + zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS);
20277 + INIT_PZVAL(property);
20278 + ZVAL_BOOL(property, value);
20279 + return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
20282 +void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC)
20284 + zval *tmp = ecalloc(1, sizeof(zval));
20285 + ZVAL_BOOL(tmp, value);
20286 + zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
20289 +void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC)
20295 + tmp->refcount = 0;
20296 + ZVAL_STRINGL(tmp, value, value_len, 1);
20297 + zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
20303 + * Local variables:
20305 + * c-basic-offset: 4
20307 + * vim600: noet sw=4 ts=4 fdm=marker
20308 + * vim<600: noet sw=4 ts=4
20312 +++ b/ext/http/missing.h
20315 + +--------------------------------------------------------------------+
20317 + +--------------------------------------------------------------------+
20318 + | Redistribution and use in source and binary forms, with or without |
20319 + | modification, are permitted provided that the conditions mentioned |
20320 + | in the accompanying LICENSE file are met. |
20321 + +--------------------------------------------------------------------+
20322 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20323 + +--------------------------------------------------------------------+
20326 +/* $Id: missing.h 298892 2010-05-03 08:29:31Z mike $ */
20328 +#ifndef PHP_HTTP_MISSING
20329 +#define PHP_HTTP_MISSING
20331 +#include "php_version.h"
20333 +#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50399)
20334 +# define ZEND_LITERAL_KEY_DC , const zend_literal *_zend_literal_key
20335 +# define ZEND_LITERAL_KEY_CC , _zend_literal_key
20336 +# define ZEND_LITERAL_NIL_CC , NULL
20337 +# define HTTP_CHECK_OPEN_BASEDIR(file, act) \
20338 + if ((PG(open_basedir) && *PG(open_basedir))) \
20340 + const char *tmp = file; \
20342 + if (!strncasecmp(tmp, "file:", lenof("file:"))) { \
20343 + tmp += lenof("file:"); \
20344 + while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \
20347 + if ( (tmp != file || !strstr(file, "://")) && \
20348 + (!*tmp || php_check_open_basedir(tmp TSRMLS_CC))) { \
20354 +# define ZEND_LITERAL_KEY_DC
20355 +# define ZEND_LITERAL_KEY_CC
20356 +# define ZEND_LITERAL_NIL_CC
20357 +# define HTTP_CHECK_OPEN_BASEDIR(file, act) \
20358 + if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) \
20360 + const char *tmp = file; \
20362 + if (!strncasecmp(tmp, "file:", lenof("file:"))) { \
20363 + tmp += lenof("file:"); \
20364 + while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \
20367 + if ( (tmp != file || !strstr(file, "://")) && \
20368 + (!*tmp || php_check_open_basedir(tmp TSRMLS_CC) || \
20369 + (PG(safe_mode) && !php_checkuid(tmp, "rb+", CHECKUID_CHECK_MODE_PARAM)))) { \
20376 +#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)
20377 +# define HTTP_ZAPI_HASH_TSRMLS_CC TSRMLS_CC
20378 +# define HTTP_ZAPI_HASH_TSRMLS_DC TSRMLS_DC
20379 +# define HTTP_ZAPI_CONST_CAST(t) (const t)
20380 +# define GLOBAL_ERROR_HANDLING EG(error_handling)
20381 +# define GLOBAL_EXCEPTION_CLASS EG(exception_class)
20382 +# define IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp) TSRMLS_CC)
20383 +# define HTTP_STATIC_ARG_INFO
20385 +# define HTTP_ZAPI_HASH_TSRMLS_CC
20386 +# define HTTP_ZAPI_HASH_TSRMLS_DC
20387 +# define HTTP_ZAPI_CONST_CAST(t) (t)
20388 +# define GLOBAL_ERROR_HANDLING PG(error_handling)
20389 +# define GLOBAL_EXCEPTION_CLASS PG(exception_class)
20390 +# define IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp))
20391 +# define HTTP_STATIC_ARG_INFO static
20394 +#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION == 0)
20398 +#ifndef pemalloc_rel
20399 +# define pemalloc_rel(size, persistent) ((persistent)?malloc(size):emalloc_rel(size))
20402 +#ifndef ZEND_ACC_DEPRECATED
20403 +# define ZEND_ACC_DEPRECATED 0
20406 +#if PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10
20407 +# define php_url_parse_ex(u, l) php_url_parse(u)
20410 +#ifndef TSRMLS_FETCH_FROM_CTX
20412 +# define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
20414 +# define TSRMLS_FETCH_FROM_CTX(ctx)
20418 +#ifndef TSRMLS_SET_CTX
20420 +# define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
20422 +# define TSRMLS_SET_CTX(ctx)
20426 +#ifndef ZVAL_ADDREF
20427 +# define ZVAL_ADDREF Z_ADDREF_P
20430 +#ifndef SEPARATE_ARG_IF_REF
20431 +#define SEPARATE_ARG_IF_REF(zv) \
20432 + if (PZVAL_IS_REF(zv)) { \
20434 + ALLOC_INIT_ZVAL(zv); \
20435 + Z_TYPE_P(zv) = Z_TYPE_P(ov); \
20436 + zv->value = ov->value; \
20437 + zval_copy_ctor(zv); \
20439 + ZVAL_ADDREF(zv); \
20444 +#define ZVAL_ZVAL(z, zv, copy, dtor) { \
20445 + int is_ref, refcount; \
20446 + is_ref = (z)->is_ref; \
20447 + refcount = (z)->refcount; \
20450 + zval_copy_ctor(z); \
20456 + zval_ptr_dtor(&zv); \
20458 + (z)->is_ref = is_ref; \
20459 + (z)->refcount = refcount; \
20462 +#ifndef RETVAL_ZVAL
20463 +# define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
20465 +#ifndef RETURN_ZVAL
20466 +# define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
20470 +# define ZEND_MN(name) ZEND_FN(name)
20474 +extern int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC);
20475 +extern void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC);
20477 +extern int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);
20478 +extern void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC);
20480 +extern void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC);
20486 + * Local variables:
20488 + * c-basic-offset: 4
20490 + * vim600: noet sw=4 ts=4 fdm=marker
20491 + * vim<600: noet sw=4 ts=4
20495 +++ b/ext/http/php_http.h
20498 + +--------------------------------------------------------------------+
20500 + +--------------------------------------------------------------------+
20501 + | Redistribution and use in source and binary forms, with or without |
20502 + | modification, are permitted provided that the conditions mentioned |
20503 + | in the accompanying LICENSE file are met. |
20504 + +--------------------------------------------------------------------+
20505 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20506 + +--------------------------------------------------------------------+
20509 +/* $Id: php_http.h 310776 2011-05-05 06:35:46Z mike $ */
20511 +#ifndef PHP_EXT_HTTP_H
20512 +#define PHP_EXT_HTTP_H
20514 +#define PHP_HTTP_VERSION "1.7.1"
20516 +#ifdef HAVE_CONFIG_H
20517 +# include "config.h"
20519 +# ifndef PHP_WIN32
20520 +# include "php_config.h"
20525 +#include "missing.h"
20526 +#include "php_http_std_defs.h"
20527 +#include "phpstr/phpstr.h"
20529 +#ifdef HTTP_WANT_SAPI
20530 +# if PHP_API_VERSION > 20041225
20531 +# define HTTP_HAVE_SAPI_RTIME
20533 +# include "SAPI.h"
20536 +#ifdef HTTP_WANT_NETDB
20538 +# define HTTP_HAVE_NETDB
20539 +# include <winsock2.h>
20540 +# elif defined(HAVE_NETDB_H)
20541 +# define HTTP_HAVE_NETDB
20542 +# include <netdb.h>
20543 +# ifdef HAVE_UNISTD_H
20544 +# include <unistd.h>
20549 +#if defined(HTTP_WANT_CURL) && defined(HTTP_HAVE_CURL)
20551 +# include <winsock2.h>
20552 +# define CURL_STATICLIB
20554 +# include <curl/curl.h>
20555 +# define HTTP_CURL_VERSION(x, y, z) (LIBCURL_VERSION_NUM >= (((x)<<16) + ((y)<<8) + (z)))
20557 +# if defined(HTTP_WANT_EVENT) && defined(HTTP_HAVE_EVENT)
20558 +# include <event.h>
20562 +#if defined(HTTP_WANT_MAGIC) && defined(HTTP_HAVE_MAGIC)
20563 +# if defined(PHP_WIN32) && !defined(USE_MAGIC_DLL) && !defined(USE_MAGIC_STATIC)
20564 +# define USE_MAGIC_STATIC
20566 +# include <magic.h>
20569 +#if defined(HTTP_WANT_ZLIB) && defined(HTTP_HAVE_ZLIB)
20570 +# include <zlib.h>
20573 +#include <ctype.h>
20574 +#define HTTP_IS_CTYPE(type, c) is##type((int) (unsigned char) (c))
20575 +#define HTTP_TO_CTYPE(type, c) to##type((int) (unsigned char) (c))
20577 +extern zend_module_entry http_module_entry;
20578 +#define phpext_http_ptr &http_module_entry
20580 +extern int http_module_number;
20582 +ZEND_BEGIN_MODULE_GLOBALS(http)
20584 + struct _http_globals_etag {
20587 + zend_bool started;
20590 + struct _http_globals_log {
20594 + char *allowed_methods;
20598 + struct _http_globals_send {
20599 + double throttle_delay;
20600 + size_t buffer_size;
20601 + char *content_type;
20602 + char *unquoted_etag;
20603 + time_t last_modified;
20604 + struct _http_globals_send_deflate {
20605 + zend_bool response;
20606 + zend_bool start_auto;
20607 + long start_flags;
20611 + struct _http_globals_send_inflate {
20612 + zend_bool start_auto;
20613 + long start_flags;
20616 + zend_bool not_found_404;
20619 + struct _http_globals_request {
20621 + HashTable *headers;
20622 + struct _http_globals_request_methods {
20623 + HashTable registered;
20627 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
20628 + struct _http_globals_request_datashare {
20629 + zend_llist handles;
20630 + zend_bool cookie;
20633 + zend_bool connect;
20636 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_EVENT)
20637 + struct _http_globals_request_pool {
20638 + struct _http_globals_request_pool_event {
20645 + struct _http_globals_persistent {
20646 + struct _http_globals_persistent_handles {
20648 + struct _http_globals_persistent_handles_ident {
20656 +#ifdef ZEND_ENGINE_2
20657 + zend_bool only_exceptions;
20660 + zend_bool force_exit;
20661 + zend_bool read_post_data;
20662 + zval *server_var;
20664 +ZEND_END_MODULE_GLOBALS(http)
20666 +ZEND_EXTERN_MODULE_GLOBALS(http);
20669 +# include "TSRM.h"
20670 +# define HTTP_G ((zend_http_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(http_globals_id)])
20672 +# define HTTP_G (&http_globals)
20675 +#if defined(HAVE_ICONV) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_ICONV))
20676 +# define HTTP_HAVE_ICONV
20679 +#if defined(HAVE_PHP_SESSION) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_SESSION))
20680 +# define HTTP_HAVE_SESSION
20683 +#if defined(HAVE_HASH_EXT) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_HASH)) && defined(HTTP_HAVE_PHP_HASH_H)
20684 +# define HTTP_HAVE_HASH
20687 +#if defined(HAVE_SPL)
20688 +# define HTTP_HAVE_SPL
20691 +PHP_FUNCTION(http_date);
20692 +PHP_FUNCTION(http_build_url);
20693 +PHP_FUNCTION(http_build_str);
20694 +PHP_FUNCTION(http_negotiate_language);
20695 +PHP_FUNCTION(http_negotiate_charset);
20696 +PHP_FUNCTION(http_negotiate_content_type);
20697 +PHP_FUNCTION(http_negotiate);
20698 +PHP_FUNCTION(http_redirect);
20699 +PHP_FUNCTION(http_throttle);
20700 +PHP_FUNCTION(http_send_status);
20701 +PHP_FUNCTION(http_send_last_modified);
20702 +PHP_FUNCTION(http_send_content_type);
20703 +PHP_FUNCTION(http_send_content_disposition);
20704 +PHP_FUNCTION(http_match_modified);
20705 +PHP_FUNCTION(http_match_etag);
20706 +PHP_FUNCTION(http_cache_last_modified);
20707 +PHP_FUNCTION(http_cache_etag);
20708 +PHP_FUNCTION(http_send_data);
20709 +PHP_FUNCTION(http_send_file);
20710 +PHP_FUNCTION(http_send_stream);
20711 +PHP_FUNCTION(http_chunked_decode);
20712 +PHP_FUNCTION(http_parse_message);
20713 +PHP_FUNCTION(http_parse_headers);
20714 +PHP_FUNCTION(http_parse_cookie);
20715 +PHP_FUNCTION(http_build_cookie);
20716 +PHP_FUNCTION(http_parse_params);
20717 +PHP_FUNCTION(http_get_request_headers);
20718 +PHP_FUNCTION(http_get_request_body);
20719 +PHP_FUNCTION(http_get_request_body_stream);
20720 +PHP_FUNCTION(http_match_request_header);
20721 +PHP_FUNCTION(http_persistent_handles_count);
20722 +PHP_FUNCTION(http_persistent_handles_clean);
20723 +PHP_FUNCTION(http_persistent_handles_ident);
20724 +#ifdef HTTP_HAVE_CURL
20725 +PHP_FUNCTION(http_get);
20726 +PHP_FUNCTION(http_head);
20727 +PHP_FUNCTION(http_post_data);
20728 +PHP_FUNCTION(http_post_fields);
20729 +PHP_FUNCTION(http_put_data);
20730 +PHP_FUNCTION(http_put_file);
20731 +PHP_FUNCTION(http_put_stream);
20732 +PHP_FUNCTION(http_request);
20733 +PHP_FUNCTION(http_request_body_encode);
20734 +#endif /* HTTP_HAVE_CURL */
20735 +PHP_FUNCTION(http_request_method_register);
20736 +PHP_FUNCTION(http_request_method_unregister);
20737 +PHP_FUNCTION(http_request_method_exists);
20738 +PHP_FUNCTION(http_request_method_name);
20739 +PHP_FUNCTION(ob_etaghandler);
20740 +#ifdef HTTP_HAVE_ZLIB
20741 +PHP_FUNCTION(http_deflate);
20742 +PHP_FUNCTION(http_inflate);
20743 +PHP_FUNCTION(ob_deflatehandler);
20744 +PHP_FUNCTION(ob_inflatehandler);
20746 +PHP_FUNCTION(http_support);
20748 +#endif /* PHP_HTTP_H */
20751 + * Local variables:
20753 + * c-basic-offset: 4
20755 + * vim600: noet sw=4 ts=4 fdm=marker
20756 + * vim<600: noet sw=4 ts=4
20760 +++ b/ext/http/php_http_api.h
20763 + +--------------------------------------------------------------------+
20765 + +--------------------------------------------------------------------+
20766 + | Redistribution and use in source and binary forms, with or without |
20767 + | modification, are permitted provided that the conditions mentioned |
20768 + | in the accompanying LICENSE file are met. |
20769 + +--------------------------------------------------------------------+
20770 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20771 + +--------------------------------------------------------------------+
20774 +/* $Id: php_http_api.h 298891 2010-05-03 08:26:38Z mike $ */
20776 +#ifndef PHP_HTTP_API_H
20777 +#define PHP_HTTP_API_H
20779 +#define HTTP_SUPPORT 0x01L
20780 +#define HTTP_SUPPORT_REQUESTS 0x02L
20781 +#define HTTP_SUPPORT_MAGICMIME 0x04L
20782 +#define HTTP_SUPPORT_ENCODINGS 0x08L
20783 +#define HTTP_SUPPORT_SSLREQUESTS 0x20L
20784 +#define HTTP_SUPPORT_PERSISTENCE 0x40L
20785 +#define HTTP_SUPPORT_EVENTS 0x80L
20787 +#define HTTP_PARAMS_ALLOW_COMMA 0x01
20788 +#define HTTP_PARAMS_ALLOW_FAILURE 0x02
20789 +#define HTTP_PARAMS_RAISE_ERROR 0x04
20790 +#define HTTP_PARAMS_DEFAULT (HTTP_PARAMS_ALLOW_COMMA|HTTP_PARAMS_ALLOW_FAILURE|HTTP_PARAMS_RAISE_ERROR)
20791 +#define HTTP_PARAMS_COLON_SEPARATOR 0x10
20793 +extern PHP_MINIT_FUNCTION(http_support);
20795 +#define http_support(f) _http_support(f)
20796 +PHP_HTTP_API long _http_support(long feature);
20798 +#define pretty_key(key, key_len, uctitle, xhyphen) _http_pretty_key(key, key_len, uctitle, xhyphen)
20799 +extern char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen);
20801 +#define http_boundary(b, l) _http_boundary((b), (l) TSRMLS_CC)
20802 +extern size_t _http_boundary(char *buf, size_t len TSRMLS_DC);
20804 +#define http_error(type, code, string) _http_error_ex(type, code, "%s", string)
20805 +#define http_error_ex _http_error_ex
20806 +extern void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...);
20809 +#ifdef ZEND_ENGINE_2
20810 +#define http_exception_wrap(o, n, ce) _http_exception_wrap((o), (n), (ce) TSRMLS_CC)
20811 +extern zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC);
20813 +#define http_try \
20815 + zval *old_exception = EG(exception); \
20816 + EG(exception) = NULL;
20817 +#define http_catch(ex_ce) \
20818 + if (EG(exception) && old_exception) { \
20819 + EG(exception) = http_exception_wrap(old_exception, EG(exception), ex_ce); \
20822 +#define http_final(ex_ce) \
20823 + if (EG(exception)) { \
20824 + EG(exception) = http_exception_wrap(EG(exception), NULL, ex_ce); \
20827 +typedef zend_object_value (*http_object_new_t)(zend_class_entry *ce, void *, void ** TSRMLS_DC);
20829 +#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)
20830 +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);
20831 +#endif /* ZEND_ENGINE_2 */
20834 +#define HTTP_CHECK_CURL_INIT(ch, init, action) \
20835 + if ((!(ch)) && (!((ch) = init))) { \
20836 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initialize curl"); \
20839 +#define HTTP_CHECK_CONTENT_TYPE(ct, action) \
20840 + if (!strchr((ct), '/')) { \
20841 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, \
20842 + "Content type \"%s\" does not seem to contain a primary and a secondary part", (ct)); \
20845 +#define HTTP_CHECK_MESSAGE_TYPE_RESPONSE(msg, action) \
20846 + if (!HTTP_MSG_TYPE(RESPONSE, (msg))) { \
20847 + http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_RESPONSE"); \
20850 +#define HTTP_CHECK_MESSAGE_TYPE_REQUEST(msg, action) \
20851 + if (!HTTP_MSG_TYPE(REQUEST, (msg))) { \
20852 + http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST"); \
20855 +#define HTTP_CHECK_GZIP_LEVEL(level, action) \
20856 + if (level < -1 || level > 9) { \
20857 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid compression level (-1 to 9): %d", level); \
20861 +#define HTTP_CHECK_HEADERS_SENT(action) \
20862 + if (SG(headers_sent) && !SG(request_info).no_headers) { \
20863 + char *output_start_filename = php_get_output_start_filename(TSRMLS_C); \
20864 + int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); \
20866 + if (output_start_filename) { \
20867 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent by (output started at %s:%d)", \
20868 + output_start_filename, output_start_lineno); \
20870 + http_error(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent"); \
20875 +#define http_log(f, i, m) _http_log_ex((f), (i), (m) TSRMLS_CC)
20876 +extern void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC);
20878 +#define http_exit(s, h) http_exit_ex((s), (h), NULL, 1)
20879 +#define http_exit_ex(s, h, b, e) _http_exit_ex((s), (h), (b), (e) TSRMLS_CC)
20880 +extern STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC);
20882 +#define http_check_method(m) http_check_method_ex((m), HTTP_KNOWN_METHODS)
20883 +#define http_check_method_ex(m, a) _http_check_method_ex((m), (a))
20884 +extern STATUS _http_check_method_ex(const char *method, const char *methods);
20886 +#define http_got_server_var(v) (NULL != http_get_server_var_ex((v), strlen(v), 1))
20887 +#define http_get_server_var(v, c) http_get_server_var_ex((v), strlen(v), (c))
20888 +#define http_get_server_var_ex(v, l, c) _http_get_server_var_ex((v), (l), (c) TSRMLS_CC)
20889 +PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC);
20891 +#define http_get_request_body(b, l) _http_get_request_body_ex((b), (l), 1 TSRMLS_CC)
20892 +#define http_get_request_body_ex(b, l, d) _http_get_request_body_ex((b), (l), (d) TSRMLS_CC)
20893 +PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC);
20895 +#define http_get_request_body_stream() _http_get_request_body_stream(TSRMLS_C)
20896 +PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D);
20899 +typedef void (*http_parse_params_callback)(void *cb_arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC);
20901 +#define http_parse_params_default_callback _http_parse_params_default_callback
20902 +PHP_HTTP_API void _http_parse_params_default_callback(void *ht, const char *key, int keylen, const char *val, int vallen TSRMLS_DC);
20904 +#define http_parse_params(s, f, ht) _http_parse_params_ex((s), (f), _http_parse_params_default_callback, (ht) TSRMLS_CC)
20905 +#define http_parse_params_ex(s, f, cb, a) _http_parse_params_ex((s), (f), (cb), (a) TSRMLS_CC)
20906 +PHP_HTTP_API STATUS _http_parse_params_ex(const char *params, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC);
20909 +#define http_sleep(s) _http_sleep(s)
20910 +static inline void _http_sleep(double s)
20912 +#define HTTP_DIFFSEC (0.001)
20913 +#define HTTP_MLLISEC (1000)
20914 +#define HTTP_MCROSEC (1000 * 1000)
20915 +#define HTTP_NANOSEC (1000 * 1000 * 1000)
20916 +#define HTTP_MSEC(s) ((long)(s * HTTP_MLLISEC))
20917 +#define HTTP_USEC(s) ((long)(s * HTTP_MCROSEC))
20918 +#define HTTP_NSEC(s) ((long)(s * HTTP_NANOSEC))
20920 +#if defined(PHP_WIN32)
20921 + Sleep((DWORD) HTTP_MSEC(s));
20922 +#elif defined(HAVE_USLEEP)
20923 + usleep(HTTP_USEC(s));
20924 +#elif defined(HAVE_NANOSLEEP)
20925 + struct timespec req, rem;
20927 + req.tv_sec = (time_t) s;
20928 + req.tv_nsec = HTTP_NSEC(s) % HTTP_NANOSEC;
20930 + while (nanosleep(&req, &rem) && (errno == EINTR) && (HTTP_NSEC(rem.tv_sec) + rem.tv_nsec) > HTTP_NSEC(HTTP_DIFFSEC))) {
20931 + req.tv_sec = rem.tv_sec;
20932 + req.tv_nsec = rem.tv_nsec;
20935 + struct timeval timeout;
20937 + timeout.tv.sec = (time_t) s;
20938 + timeout.tv_usec = HTTP_USEC(s) % HTTP_MCROSEC;
20940 + select(0, NULL, NULL, NULL, &timeout);
20944 +#define http_locate_str _http_locate_str
20945 +static inline const char *_http_locate_str(const char *h, size_t h_len, const char *n, size_t n_len)
20947 + const char *p, *e;
20949 + if (n_len && h_len) {
20953 + for (p = n; *p == h[p-n]; ++p) {
20954 + if (p == n+n_len-1) {
20959 + } while (h++ != e);
20965 +#define http_locate_body _http_locate_body
20966 +static inline const char *_http_locate_body(const char *message)
20968 + const char *body = NULL, *msg = message;
20971 + if (*msg == '\n') {
20972 + if (*(msg+1) == '\n') {
20975 + } else if (*(msg+1) == '\r' && *(msg+2) == '\n') {
20985 +#define http_locate_eol _http_locate_eol
20986 +static inline const char *_http_locate_eol(const char *line, int *eol_len)
20988 + const char *eol = strpbrk(line, "\r\n");
20991 + *eol_len = eol ? ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1) : 0;
20996 +#define http_zset(t, z) _http_zset((t), (z))
20997 +static inline zval *_http_zset(int type, zval *z)
20999 + if (Z_TYPE_P(z) != type) {
21001 + case IS_NULL: convert_to_null(z); break;
21002 + case IS_BOOL: convert_to_boolean(z); break;
21003 + case IS_LONG: convert_to_long(z); break;
21004 + case IS_DOUBLE: convert_to_double(z); break;
21005 + case IS_STRING: convert_to_string(z); break;
21006 + case IS_ARRAY: convert_to_array(z); break;
21007 + case IS_OBJECT: convert_to_object(z); break;
21012 +#define http_zsep(t, z) _http_zsep_ex((t), (z), NULL)
21013 +#define http_zsep_ex(t, z, p) _http_zsep_ex((t), (z), (p))
21014 +static inline zval *_http_zsep_ex(int type, zval *z, zval **p) {
21015 + SEPARATE_ARG_IF_REF(z);
21016 + if (Z_TYPE_P(z) != type) {
21018 + case IS_NULL: convert_to_null_ex(&z); break;
21019 + case IS_BOOL: convert_to_boolean_ex(&z); break;
21020 + case IS_LONG: convert_to_long_ex(&z); break;
21021 + case IS_DOUBLE: convert_to_double_ex(&z); break;
21022 + case IS_STRING: convert_to_string_ex(&z); break;
21023 + case IS_ARRAY: convert_to_array_ex(&z); break;
21024 + case IS_OBJECT: convert_to_object_ex(&z); break;
21033 +typedef struct _HashKey {
21040 +#define initHashKey(dup) {NULL, 0, 0, (dup), 0}
21042 +#define FOREACH_VAL(pos, array, val) FOREACH_HASH_VAL(pos, Z_ARRVAL_P(array), val)
21043 +#define FOREACH_HASH_VAL(pos, hash, val) \
21044 + for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
21045 + zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
21046 + zend_hash_move_forward_ex(hash, &pos))
21048 +#define FOREACH_KEY(pos, array, key) FOREACH_HASH_KEY(pos, Z_ARRVAL_P(array), key)
21049 +#define FOREACH_HASH_KEY(pos, hash, _key) \
21050 + for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
21051 + ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT; \
21052 + zend_hash_move_forward_ex(hash, &pos)) \
21054 +#define FOREACH_KEYVAL(pos, array, key, val) FOREACH_HASH_KEYVAL(pos, Z_ARRVAL_P(array), key, val)
21055 +#define FOREACH_HASH_KEYVAL(pos, hash, _key, val) \
21056 + for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
21057 + ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT && \
21058 + zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
21059 + zend_hash_move_forward_ex(hash, &pos))
21061 +#define array_copy(src, dst) zend_hash_copy(dst, src, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *))
21062 +#define ARRAY_JOIN_STRONLY 1
21063 +#define ARRAY_JOIN_PRETTIFY 2
21064 +#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)
21066 +extern int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
21067 +extern int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
21072 + * Local variables:
21074 + * c-basic-offset: 4
21076 + * vim600: noet sw=4 ts=4 fdm=marker
21077 + * vim<600: noet sw=4 ts=4
21081 +++ b/ext/http/php_http_cache_api.h
21084 + +--------------------------------------------------------------------+
21086 + +--------------------------------------------------------------------+
21087 + | Redistribution and use in source and binary forms, with or without |
21088 + | modification, are permitted provided that the conditions mentioned |
21089 + | in the accompanying LICENSE file are met. |
21090 + +--------------------------------------------------------------------+
21091 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21092 + +--------------------------------------------------------------------+
21095 +/* $Id: php_http_cache_api.h 292841 2009-12-31 08:48:57Z mike $ */
21097 +#ifndef PHP_HTTP_CACHE_API_H
21098 +#define PHP_HTTP_CACHE_API_H
21100 +#include "php_http_send_api.h"
21102 +#include "ext/standard/crc32.h"
21103 +#include "ext/standard/sha1.h"
21104 +#include "ext/standard/md5.h"
21106 +#ifdef HTTP_HAVE_HASH
21107 +# include "php_hash.h"
21110 +#define http_etag_digest(d, l) _http_etag_digest((d), (l))
21111 +static inline char *_http_etag_digest(const unsigned char *digest, int len)
21113 + static const char hexdigits[17] = "0123456789abcdef";
21115 + char *hex = emalloc(len * 2 + 1);
21118 + for (i = 0; i < len; ++i) {
21119 + *ptr++ = hexdigits[digest[i] >> 4];
21120 + *ptr++ = hexdigits[digest[i] & 0xF];
21127 +#define http_etag_init() _http_etag_init(TSRMLS_C)
21128 +static inline void *_http_etag_init(TSRMLS_D)
21130 + void *ctx = NULL;
21131 + char *mode = HTTP_G->etag.mode;
21133 +#ifdef HTTP_HAVE_HASH
21134 + const php_hash_ops *eho = NULL;
21136 + if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
21137 + ctx = emalloc(eho->context_size);
21138 + eho->hash_init(ctx);
21141 + if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
21142 + ctx = emalloc(sizeof(uint));
21143 + *((uint *) ctx) = ~0;
21144 + } else if (mode && !strcasecmp(mode, "sha1")) {
21145 + PHP_SHA1Init(ctx = emalloc(sizeof(PHP_SHA1_CTX)));
21147 + PHP_MD5Init(ctx = emalloc(sizeof(PHP_MD5_CTX)));
21153 +#define http_etag_finish(c) _http_etag_finish((c) TSRMLS_CC)
21154 +static inline char *_http_etag_finish(void *ctx TSRMLS_DC)
21156 + unsigned char digest[128] = {0};
21157 + char *etag = NULL, *mode = HTTP_G->etag.mode;
21159 +#ifdef HTTP_HAVE_HASH
21160 + const php_hash_ops *eho = NULL;
21162 + if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
21163 + eho->hash_final(digest, ctx);
21164 + etag = http_etag_digest(digest, eho->digest_size);
21167 + if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
21168 + *((uint *) ctx) = ~*((uint *) ctx);
21169 + etag = http_etag_digest((const unsigned char *) ctx, sizeof(uint));
21170 + } else if (mode && (!strcasecmp(mode, "sha1"))) {
21171 + PHP_SHA1Final(digest, ctx);
21172 + etag = http_etag_digest(digest, 20);
21174 + PHP_MD5Final(digest, ctx);
21175 + etag = http_etag_digest(digest, 16);
21182 +#define http_etag_update(c, d, l) _http_etag_update((c), (d), (l) TSRMLS_CC)
21183 +static inline void _http_etag_update(void *ctx, const char *data_ptr, size_t data_len TSRMLS_DC)
21185 + char *mode = HTTP_G->etag.mode;
21186 +#ifdef HTTP_HAVE_HASH
21187 + const php_hash_ops *eho = NULL;
21189 + if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
21190 + eho->hash_update(ctx, (const unsigned char *) data_ptr, data_len);
21193 + if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
21194 + uint i, c = *((uint *) ctx);
21195 + for (i = 0; i < data_len; ++i) {
21196 + CRC32(c, data_ptr[i]);
21198 + *((uint *)ctx) = c;
21199 + } else if (mode && (!strcasecmp(mode, "sha1"))) {
21200 + PHP_SHA1Update(ctx, (const unsigned char *) data_ptr, data_len);
21202 + PHP_MD5Update(ctx, (const unsigned char *) data_ptr, data_len);
21206 +#define http_ob_etaghandler(o, l, ho, hl, m) _http_ob_etaghandler((o), (l), (ho), (hl), (m) TSRMLS_CC)
21207 +extern void _http_ob_etaghandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC);
21209 +#define http_etag(p, l, m) _http_etag((p), (l), (m) TSRMLS_CC)
21210 +PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC);
21212 +#define http_last_modified(p, m) _http_last_modified((p), (m) TSRMLS_CC)
21213 +PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC);
21215 +#define http_match_last_modified(entry, modified) _http_match_last_modified_ex((entry), (modified), 1 TSRMLS_CC)
21216 +#define http_match_last_modified_ex(entry, modified, ep) _http_match_last_modified_ex((entry), (modified), (ep) TSRMLS_CC)
21217 +PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC);
21219 +#define http_match_etag(entry, etag) _http_match_etag_ex((entry), (etag), 1 TSRMLS_CC)
21220 +#define http_match_etag_ex(entry, etag, ep) _http_match_etag_ex((entry), (etag), (ep) TSRMLS_CC)
21221 +PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC);
21223 +#define http_cache_last_modified(l, s, cc, ccl) _http_cache_last_modified((l), (s), (cc), (ccl) TSRMLS_CC)
21224 +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);
21226 +#define http_cache_etag(e, el, cc, ccl) _http_cache_etag((e), (el), (cc), (ccl) TSRMLS_CC)
21227 +PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len, const char *cache_control, size_t cc_len TSRMLS_DC);
21229 +#define http_start_ob_etaghandler() _http_start_ob_etaghandler(TSRMLS_C)
21230 +PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D);
21231 +#define http_interrupt_ob_etaghandler() _http_interrupt_ob_etaghandler(TSRMLS_C)
21232 +PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D);
21237 + * Local variables:
21239 + * c-basic-offset: 4
21241 + * vim600: noet sw=4 ts=4 fdm=marker
21242 + * vim<600: noet sw=4 ts=4
21246 +++ b/ext/http/php_http_cookie_api.h
21249 + +--------------------------------------------------------------------+
21251 + +--------------------------------------------------------------------+
21252 + | Redistribution and use in source and binary forms, with or without |
21253 + | modification, are permitted provided that the conditions mentioned |
21254 + | in the accompanying LICENSE file are met. |
21255 + +--------------------------------------------------------------------+
21256 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21257 + +--------------------------------------------------------------------+
21260 +/* $Id: php_http_cookie_api.h 292841 2009-12-31 08:48:57Z mike $ */
21262 +#ifndef PHP_HTTP_COOKIE_API_H
21263 +#define PHP_HTTP_COOKIE_API_H
21265 +#define HTTP_COOKIE_SECURE 0x10L
21266 +#define HTTP_COOKIE_HTTPONLY 0x20L
21268 +#define HTTP_COOKIE_PARSE_RAW 0x01L
21270 +extern PHP_MINIT_FUNCTION(http_cookie);
21273 + generally a netscape cookie compliant struct, recognizing httpOnly attribute, too;
21274 + cookie params like those from rfc2109 and rfc2965 are just put into extras, if
21275 + one specifies them in allowed extras, else they're treated like cookies themself
21277 +typedef struct _http_cookie_list_t {
21278 + HashTable cookies;
21279 + HashTable extras;
21284 +} http_cookie_list;
21286 +#define http_cookie_list_new() _http_cookie_list_init(NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
21287 +#define http_cookie_list_init(l) _http_cookie_list_init((l) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
21288 +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);
21290 +#define http_cookie_list_dtor(l) _http_cookie_list_dtor((l) TSRMLS_CC)
21291 +PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC);
21293 +#define http_cookie_list_free(l) _http_cookie_list_free((l) TSRMLS_CC)
21294 +PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC);
21296 +#define http_cookie_list_has_cookie(list, name, name_len) zend_hash_exists(&(list)->cookies, (name), (name_len)+1)
21297 +#define http_cookie_list_has_extra(list, name, name_len) zend_hash_exists(&(list)->extras, (name), (name_len)+1)
21299 +#define http_cookie_list_add_cookie(l, n, nl, v, vl) _http_cookie_list_add_cookie((l), (n), (nl), (v), (vl) TSRMLS_CC)
21300 +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);
21302 +#define http_cookie_list_add_extra(l, n , nl, v, vl) _http_cookie_list_add_extra((l), (n), (nl), (v), (vl) TSRMLS_CC)
21303 +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);
21305 +#define http_cookie_list_get_cookie(l, n, nl) _http_cookie_list_get_cookie((l), (n), (nl) TSRMLS_CC)
21306 +PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC);
21308 +#define http_cookie_list_get_extra(l, n, nl) _http_cookie_list_get_extra((l), (n), (nl) TSRMLS_CC)
21309 +PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC);
21311 +#define http_parse_cookie(s) _http_parse_cookie_ex(NULL, (s), 0, NULL TSRMLS_CC)
21312 +#define http_parse_cookie_ex(l, s, f, a) _http_parse_cookie_ex((l), (s), (f), (a) TSRMLS_CC)
21313 +PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list * list, const char *string, long flags, char **allowed_extras TSRMLS_DC);
21315 +#define http_cookie_list_tostruct(l, s) _http_cookie_list_tostruct((l), (s) TSRMLS_CC)
21316 +PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC);
21318 +#define http_cookie_list_fromstruct(l, s) _http_cookie_list_fromstruct((l), (s) TSRMLS_CC)
21319 +PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC);
21321 +#define http_cookie_list_tostring(l, str, len) _http_cookie_list_tostring((l), (str), (len) TSRMLS_CC)
21322 +PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC);
21327 + * Local variables:
21329 + * c-basic-offset: 4
21331 + * vim600: noet sw=4 ts=4 fdm=marker
21332 + * vim<600: noet sw=4 ts=4
21335 +++ b/ext/http/php_http_date_api.h
21338 + +--------------------------------------------------------------------+
21340 + +--------------------------------------------------------------------+
21341 + | Redistribution and use in source and binary forms, with or without |
21342 + | modification, are permitted provided that the conditions mentioned |
21343 + | in the accompanying LICENSE file are met. |
21344 + +--------------------------------------------------------------------+
21345 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21346 + +--------------------------------------------------------------------+
21349 +/* $Id: php_http_date_api.h 292841 2009-12-31 08:48:57Z mike $ */
21351 +#ifndef PHP_HTTP_DATE_API_H
21352 +#define PHP_HTTP_DATE_API_H
21354 +#define http_date(t) _http_date((t) TSRMLS_CC)
21355 +PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC);
21357 +#define http_parse_date(d) _http_parse_date_ex((d), 0 TSRMLS_CC)
21358 +#define http_parse_date_ex(d, s) _http_parse_date_ex((d), (s) TSRMLS_CC)
21359 +PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC);
21364 + * Local variables:
21366 + * c-basic-offset: 4
21368 + * vim600: noet sw=4 ts=4 fdm=marker
21369 + * vim<600: noet sw=4 ts=4
21373 +++ b/ext/http/php_http_deflatestream_object.h
21376 + +--------------------------------------------------------------------+
21378 + +--------------------------------------------------------------------+
21379 + | Redistribution and use in source and binary forms, with or without |
21380 + | modification, are permitted provided that the conditions mentioned |
21381 + | in the accompanying LICENSE file are met. |
21382 + +--------------------------------------------------------------------+
21383 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21384 + +--------------------------------------------------------------------+
21387 +/* $Id: php_http_deflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */
21389 +#ifndef PHP_HTTP_DEFLATESTREAM_OBJECT_H
21390 +#define PHP_HTTP_DEFLATESTREAM_OBJECT_H
21391 +#ifdef HTTP_HAVE_ZLIB
21392 +#ifdef ZEND_ENGINE_2
21394 +typedef struct _http_deflatestream_object_t {
21396 + http_encoding_stream *stream;
21397 +} http_deflatestream_object;
21399 +extern zend_class_entry *http_deflatestream_object_ce;
21400 +extern zend_function_entry http_deflatestream_object_fe[];
21402 +extern PHP_MINIT_FUNCTION(http_deflatestream_object);
21404 +#define http_deflatestream_object_new(ce) _http_deflatestream_object_new((ce) TSRMLS_CC)
21405 +extern zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC);
21406 +#define http_deflatestream_object_new_ex(ce, s, ptr) _http_deflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
21407 +extern zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC);
21408 +#define http_deflatestream_object_clone(zobj) _http_deflatestream_object_clone_obj(zobj TSRMLS_CC)
21409 +extern zend_object_value _http_deflatestream_object_clone_obj(zval *object TSRMLS_DC);
21410 +#define http_deflatestream_object_free(o) _http_deflatestream_object_free((o) TSRMLS_CC)
21411 +extern void _http_deflatestream_object_free(zend_object *object TSRMLS_DC);
21413 +PHP_METHOD(HttpDeflateStream, __construct);
21414 +PHP_METHOD(HttpDeflateStream, factory);
21415 +PHP_METHOD(HttpDeflateStream, update);
21416 +PHP_METHOD(HttpDeflateStream, flush);
21417 +PHP_METHOD(HttpDeflateStream, finish);
21424 + * Local variables:
21426 + * c-basic-offset: 4
21428 + * vim600: noet sw=4 ts=4 fdm=marker
21429 + * vim<600: noet sw=4 ts=4
21433 +++ b/ext/http/php_http_encoding_api.h
21436 + +--------------------------------------------------------------------+
21438 + +--------------------------------------------------------------------+
21439 + | Redistribution and use in source and binary forms, with or without |
21440 + | modification, are permitted provided that the conditions mentioned |
21441 + | in the accompanying LICENSE file are met. |
21442 + +--------------------------------------------------------------------+
21443 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21444 + +--------------------------------------------------------------------+
21447 +/* $Id: php_http_encoding_api.h 292841 2009-12-31 08:48:57Z mike $ */
21449 +#ifndef PHP_HTTP_ENCODING_API_H
21450 +#define PHP_HTTP_ENCODING_API_H
21452 +#define http_encoding_dechunk(e, el, d, dl) _http_encoding_dechunk((e), (el), (d), (dl) TSRMLS_CC)
21453 +PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC);
21455 +#define http_encoding_response_start(cl, i) _http_encoding_response_start((cl), (i) TSRMLS_CC)
21456 +PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC);
21458 +#ifdef HTTP_HAVE_ZLIB
21460 +extern PHP_MINIT_FUNCTION(http_encoding);
21461 +extern PHP_RINIT_FUNCTION(http_encoding);
21462 +extern PHP_RSHUTDOWN_FUNCTION(http_encoding);
21464 +typedef enum _http_encoding_type_t {
21465 + HTTP_ENCODING_NONE,
21466 + HTTP_ENCODING_GZIP,
21467 + HTTP_ENCODING_DEFLATE,
21468 +} http_encoding_type;
21470 +#define HTTP_INFLATE_ROUNDS 100
21472 +#define HTTP_DEFLATE_BUFFER_SIZE_GUESS(S) \
21473 + (((size_t) ((double) S * (double) 1.015)) + 10 + 8 + 4 + 1)
21474 +#define HTTP_INFLATE_BUFFER_SIZE_GUESS(S) \
21476 +#define HTTP_INFLATE_BUFFER_SIZE_ALIGN(S) \
21477 + ((S) += (S) >> (3))
21479 +#define HTTP_DEFLATE_BUFFER_SIZE 0x8000
21480 +#define HTTP_INFLATE_BUFFER_SIZE 0x1000
21482 +#define HTTP_DEFLATE_LEVEL_DEF 0x00000000
21483 +#define HTTP_DEFLATE_LEVEL_MIN 0x00000001
21484 +#define HTTP_DEFLATE_LEVEL_MAX 0x00000009
21485 +#define HTTP_DEFLATE_TYPE_ZLIB 0x00000000
21486 +#define HTTP_DEFLATE_TYPE_GZIP 0x00000010
21487 +#define HTTP_DEFLATE_TYPE_RAW 0x00000020
21488 +#define HTTP_DEFLATE_STRATEGY_DEF 0x00000000
21489 +#define HTTP_DEFLATE_STRATEGY_FILT 0x00000100
21490 +#define HTTP_DEFLATE_STRATEGY_HUFF 0x00000200
21491 +#define HTTP_DEFLATE_STRATEGY_RLE 0x00000300
21492 +#define HTTP_DEFLATE_STRATEGY_FIXED 0x00000400
21494 +#define HTTP_DEFLATE_LEVEL_SET(flags, level) \
21495 + switch (flags & 0xf) \
21498 + if ((flags & 0xf) < 10) { \
21499 + level = flags & 0xf; \
21502 + case HTTP_DEFLATE_LEVEL_DEF: \
21503 + level = Z_DEFAULT_COMPRESSION; \
21507 +#define HTTP_DEFLATE_WBITS_SET(flags, wbits) \
21508 + switch (flags & 0xf0) \
21510 + case HTTP_DEFLATE_TYPE_GZIP: \
21511 + wbits = HTTP_WINDOW_BITS_GZIP; \
21513 + case HTTP_DEFLATE_TYPE_RAW: \
21514 + wbits = HTTP_WINDOW_BITS_RAW; \
21517 + wbits = HTTP_WINDOW_BITS_ZLIB; \
21521 +#define HTTP_INFLATE_WBITS_SET(flags, wbits) \
21522 + if (flags & HTTP_INFLATE_TYPE_RAW) { \
21523 + wbits = HTTP_WINDOW_BITS_RAW; \
21525 + wbits = HTTP_WINDOW_BITS_ANY; \
21528 +#define HTTP_DEFLATE_STRATEGY_SET(flags, strategy) \
21529 + switch (flags & 0xf00) \
21531 + case HTTP_DEFLATE_STRATEGY_FILT: \
21532 + strategy = Z_FILTERED; \
21534 + case HTTP_DEFLATE_STRATEGY_HUFF: \
21535 + strategy = Z_HUFFMAN_ONLY; \
21537 + case HTTP_DEFLATE_STRATEGY_RLE: \
21538 + strategy = Z_RLE; \
21540 + case HTTP_DEFLATE_STRATEGY_FIXED: \
21541 + strategy = Z_FIXED; \
21544 + strategy = Z_DEFAULT_STRATEGY; \
21548 +#define HTTP_WINDOW_BITS_ZLIB 0x0000000f
21549 +#define HTTP_WINDOW_BITS_GZIP 0x0000001f
21550 +#define HTTP_WINDOW_BITS_ANY 0x0000002f
21551 +#define HTTP_WINDOW_BITS_RAW -0x000000f
21554 +/* Z_FIXED does not exist prior 1.2.2.2 */
21555 +# define Z_FIXED 0
21558 +#define HTTP_INFLATE_TYPE_ZLIB 0x00000000
21559 +#define HTTP_INFLATE_TYPE_GZIP 0x00000000
21560 +#define HTTP_INFLATE_TYPE_RAW 0x00000001
21562 +#define HTTP_ENCODING_STREAM_FLUSH_NONE 0x00000000
21563 +#define HTTP_ENCODING_STREAM_FLUSH_SYNC 0x00100000
21564 +#define HTTP_ENCODING_STREAM_FLUSH_FULL 0x00200000
21566 +#define HTTP_ENCODING_STREAM_FLUSH_FLAG(f) \
21567 + (((f) & HTTP_ENCODING_STREAM_FLUSH_FULL) ? Z_FULL_FLUSH : \
21568 + (((f) & HTTP_ENCODING_STREAM_FLUSH_SYNC) ? Z_SYNC_FLUSH : Z_NO_FLUSH))
21570 +#define HTTP_ENCODING_STREAM_PERSISTENT 0x01000000
21572 +typedef struct _http_encoding_stream_t {
21576 +} http_encoding_stream;
21578 +#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)
21579 +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);
21580 +#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)
21581 +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);
21583 +#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)
21584 +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);
21585 +#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)
21586 +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);
21587 +#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)
21588 +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);
21589 +#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)
21590 +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);
21591 +#define http_encoding_deflate_stream_dtor(s) _http_encoding_deflate_stream_dtor((s) TSRMLS_CC)
21592 +PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
21593 +#define http_encoding_deflate_stream_free(s) _http_encoding_deflate_stream_free((s) TSRMLS_CC)
21594 +PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC);
21596 +#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)
21597 +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);
21598 +#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)
21599 +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);
21600 +#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)
21601 +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);
21602 +#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)
21603 +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);
21604 +#define http_encoding_inflate_stream_dtor(s) _http_encoding_inflate_stream_dtor((s) TSRMLS_CC)
21605 +PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
21606 +#define http_encoding_inflate_stream_free(s) _http_encoding_inflate_stream_free((s) TSRMLS_CC)
21607 +PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC);
21609 +#define http_ob_deflatehandler(o, ol, h, hl, m) _http_ob_deflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC)
21610 +extern void _http_ob_deflatehandler(char *, uint, char **, uint *, int TSRMLS_DC);
21612 +#define http_ob_inflatehandler(o, ol, h, hl, m) _http_ob_inflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC)
21613 +extern void _http_ob_inflatehandler(char *, uint, char **, uint *, int TSRMLS_DC);
21615 +#endif /* HTTP_HAVE_ZLIB */
21620 + * Local variables:
21622 + * c-basic-offset: 4
21624 + * vim600: noet sw=4 ts=4 fdm=marker
21625 + * vim<600: noet sw=4 ts=4
21628 +++ b/ext/http/php_http_exception_object.h
21631 + +--------------------------------------------------------------------+
21633 + +--------------------------------------------------------------------+
21634 + | Redistribution and use in source and binary forms, with or without |
21635 + | modification, are permitted provided that the conditions mentioned |
21636 + | in the accompanying LICENSE file are met. |
21637 + +--------------------------------------------------------------------+
21638 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21639 + +--------------------------------------------------------------------+
21642 +/* $Id: php_http_exception_object.h 292841 2009-12-31 08:48:57Z mike $ */
21644 +#ifndef PHP_HTTP_EXCEPTION_OBJECT_H
21645 +#define PHP_HTTP_EXCEPTION_OBJECT_H
21646 +#ifdef ZEND_ENGINE_2
21648 +#include "zend_exceptions.h"
21650 +PHP_MINIT_FUNCTION(http_exception_object);
21652 +#define HTTP_EX_DEF_CE http_exception_object_ce
21653 +#define HTTP_EX_CE(name) http_ ##name## _exception_object_ce
21655 +extern zend_class_entry *http_exception_object_ce;
21656 +extern zend_class_entry *HTTP_EX_CE(runtime);
21657 +extern zend_class_entry *HTTP_EX_CE(header);
21658 +extern zend_class_entry *HTTP_EX_CE(malformed_headers);
21659 +extern zend_class_entry *HTTP_EX_CE(request_method);
21660 +extern zend_class_entry *HTTP_EX_CE(message_type);
21661 +extern zend_class_entry *HTTP_EX_CE(invalid_param);
21662 +extern zend_class_entry *HTTP_EX_CE(encoding);
21663 +extern zend_class_entry *HTTP_EX_CE(request);
21664 +extern zend_class_entry *HTTP_EX_CE(request_pool);
21665 +extern zend_class_entry *HTTP_EX_CE(socket);
21666 +extern zend_class_entry *HTTP_EX_CE(response);
21667 +extern zend_class_entry *HTTP_EX_CE(url);
21668 +extern zend_function_entry http_exception_object_fe[];
21670 +#define http_exception_get_default _http_exception_get_default
21671 +extern zend_class_entry *_http_exception_get_default();
21673 +#define http_exception_get_for_code(c) _http_exception_get_for_code(c)
21674 +extern zend_class_entry *_http_exception_get_for_code(long code);
21676 +PHP_METHOD(HttpException, __toString);
21682 + * Local variables:
21684 + * c-basic-offset: 4
21686 + * vim600: noet sw=4 ts=4 fdm=marker
21687 + * vim<600: noet sw=4 ts=4
21691 +++ b/ext/http/php_http_filter_api.h
21694 + +--------------------------------------------------------------------+
21696 + +--------------------------------------------------------------------+
21697 + | Redistribution and use in source and binary forms, with or without |
21698 + | modification, are permitted provided that the conditions mentioned |
21699 + | in the accompanying LICENSE file are met. |
21700 + +--------------------------------------------------------------------+
21701 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21702 + +--------------------------------------------------------------------+
21705 +/* $Id: php_http_filter_api.h 292841 2009-12-31 08:48:57Z mike $ */
21707 +#ifndef PHP_HTTP_FILTER_API_H
21708 +#define PHP_HTTP_FILTER_API_H
21709 +#ifdef ZEND_ENGINE_2
21711 +extern php_stream_filter_factory http_filter_factory;
21712 +PHP_MINIT_FUNCTION(http_filter);
21718 + * Local variables:
21720 + * c-basic-offset: 4
21722 + * vim600: noet sw=4 ts=4 fdm=marker
21723 + * vim<600: noet sw=4 ts=4
21727 +++ b/ext/http/php_http_headers_api.h
21730 + +--------------------------------------------------------------------+
21732 + +--------------------------------------------------------------------+
21733 + | Redistribution and use in source and binary forms, with or without |
21734 + | modification, are permitted provided that the conditions mentioned |
21735 + | in the accompanying LICENSE file are met. |
21736 + +--------------------------------------------------------------------+
21737 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21738 + +--------------------------------------------------------------------+
21741 +/* $Id: php_http_headers_api.h 300300 2010-06-09 07:29:35Z mike $ */
21743 +#ifndef PHP_HTTP_HEADERS_API_H
21744 +#define PHP_HTTP_HEADERS_API_H
21746 +#include "php_http_info_api.h"
21748 +typedef enum http_range_status_t {
21752 +} http_range_status;
21754 +#define http_parse_headers(h, a) _http_parse_headers_ex((h), Z_ARRVAL_P(a), 1, http_info_default_callback, NULL TSRMLS_CC)
21755 +#define http_parse_headers_ex(h, ht, p) _http_parse_headers_ex((h), (ht), (p), http_info_default_callback, NULL TSRMLS_CC)
21756 +#define http_parse_headers_cb(h, ht, p, f, d) _http_parse_headers_ex((h), (ht), (p), (f), (d) TSRMLS_CC)
21757 +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);
21759 +typedef char *(*negotiate_func_t)(const char *test, double *quality, HashTable *supported TSRMLS_DC);
21761 +#define http_negotiate_language_func _http_negotiate_language_func
21762 +extern char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
21763 +#define http_negotiate_content_type_func _http_negotiate_default_func
21764 +#define http_negotiate_encoding_func _http_negotiate_default_func
21765 +#define http_negotiate_charset_func _http_negotiate_default_func
21766 +#define http_negotiate_default_func _http_negotiate_default_func
21767 +extern char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
21769 +#define http_negotiate_language(zsupported) http_negotiate_language_ex(Z_ARRVAL_P(zsupported))
21770 +#define http_negotiate_language_ex(supported) http_negotiate_q("HTTP_ACCEPT_LANGUAGE", (supported), http_negotiate_language_func)
21771 +#define http_negotiate_charset(zsupported) http_negotiate_charset_ex(Z_ARRVAL_P(zsupported))
21772 +#define http_negotiate_charset_ex(supported) http_negotiate_q("HTTP_ACCEPT_CHARSET", (supported), http_negotiate_charset_func)
21773 +#define http_negotiate_encoding(zsupported) http_negotiate_encoding_ex(Z_ARRVAL_P(zsupported))
21774 +#define http_negotiate_encoding_ex(supported) http_negotiate_q("HTTP_ACCEPT_ENCODING", (supported), http_negotiate_encoding_func)
21775 +#define http_negotiate_content_type(zsupported) http_negotiate_content_type_ex(Z_ARRVAL_P(zsupported))
21776 +#define http_negotiate_content_type_ex(supported) http_negotiate_q("HTTP_ACCEPT", (supported), http_negotiate_content_type_func)
21777 +#define http_negotiate_q(e, s, n) _http_negotiate_q((e), (s), (n) TSRMLS_CC)
21778 +PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC);
21779 +#define http_negotiate_z(z, s, n) _http_negotiate_z((z), (s), (n) TSRMLS_CC)
21780 +PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC);
21782 +#define http_get_request_ranges(r, l) _http_get_request_ranges((r), (l) TSRMLS_CC)
21783 +PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC);
21785 +#define http_get_request_headers(h) _http_get_request_headers((h) TSRMLS_CC)
21786 +PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC);
21788 +#define http_get_response_headers(h) _http_get_response_headers((h) TSRMLS_CC)
21789 +PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC);
21791 +#define http_match_request_header(h, v) http_match_request_header_ex((h), (v), 0)
21792 +#define http_match_request_header_ex(h, v, c) _http_match_request_header_ex((h), (v), (c) TSRMLS_CC)
21793 +PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC);
21798 + * Local variables:
21800 + * c-basic-offset: 4
21802 + * vim600: noet sw=4 ts=4 fdm=marker
21803 + * vim<600: noet sw=4 ts=4
21807 +++ b/ext/http/php_http_inflatestream_object.h
21810 + +--------------------------------------------------------------------+
21812 + +--------------------------------------------------------------------+
21813 + | Redistribution and use in source and binary forms, with or without |
21814 + | modification, are permitted provided that the conditions mentioned |
21815 + | in the accompanying LICENSE file are met. |
21816 + +--------------------------------------------------------------------+
21817 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21818 + +--------------------------------------------------------------------+
21821 +/* $Id: php_http_inflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */
21823 +#ifndef PHP_HTTP_INFLATESTREAM_OBJECT_H
21824 +#define PHP_HTTP_INFLATESTREAM_OBJECT_H
21825 +#ifdef HTTP_HAVE_ZLIB
21826 +#ifdef ZEND_ENGINE_2
21828 +typedef struct _http_inflatestream_object_t {
21830 + http_encoding_stream *stream;
21831 +} http_inflatestream_object;
21833 +extern zend_class_entry *http_inflatestream_object_ce;
21834 +extern zend_function_entry http_inflatestream_object_fe[];
21836 +extern PHP_MINIT_FUNCTION(http_inflatestream_object);
21838 +#define http_inflatestream_object_new(ce) _http_inflatestream_object_new((ce) TSRMLS_CC)
21839 +extern zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC);
21840 +#define http_inflatestream_object_new_ex(ce, s, ptr) _http_inflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
21841 +extern zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC);
21842 +#define http_inflatestream_object_clone(zobj) _http_inflatestream_object_clone_obj(zobj TSRMLS_CC)
21843 +extern zend_object_value _http_inflatestream_object_clone_obj(zval *object TSRMLS_DC);
21844 +#define http_inflatestream_object_free(o) _http_inflatestream_object_free((o) TSRMLS_CC)
21845 +extern void _http_inflatestream_object_free(zend_object *object TSRMLS_DC);
21847 +PHP_METHOD(HttpInflateStream, __construct);
21848 +PHP_METHOD(HttpInflateStream, factory);
21849 +PHP_METHOD(HttpInflateStream, update);
21850 +PHP_METHOD(HttpInflateStream, flush);
21851 +PHP_METHOD(HttpInflateStream, finish);
21858 + * Local variables:
21860 + * c-basic-offset: 4
21862 + * vim600: noet sw=4 ts=4 fdm=marker
21863 + * vim<600: noet sw=4 ts=4
21867 +++ b/ext/http/php_http_info_api.h
21870 + +--------------------------------------------------------------------+
21872 + +--------------------------------------------------------------------+
21873 + | Redistribution and use in source and binary forms, with or without |
21874 + | modification, are permitted provided that the conditions mentioned |
21875 + | in the accompanying LICENSE file are met. |
21876 + +--------------------------------------------------------------------+
21877 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21878 + +--------------------------------------------------------------------+
21881 +/* $Id: php_http_info_api.h 292841 2009-12-31 08:48:57Z mike $ */
21883 +#ifndef PHP_HTTP_INFO_API_H
21884 +#define PHP_HTTP_INFO_API_H
21886 +#define IS_HTTP_REQUEST 1
21887 +#define IS_HTTP_RESPONSE 2
21889 +#define HTTP_INFO(ptr) (ptr)->http.info
21891 +#define HTTP_INFO_REQUEST_FMT_ARGS(_http_ptr, _EOL) "%s %s HTTP/%1.1f" _EOL, \
21892 + (_http_ptr)->info.request.method?(_http_ptr)->info.request.method:"UNKNOWN", \
21893 + (_http_ptr)->info.request.url?(_http_ptr)->info.request.url:"/", \
21894 + (_http_ptr)->version>0.0?(_http_ptr)->version:1.1
21896 +#define HTTP_INFO_RESPONSE_FMT_ARGS(_http_ptr, _EOL) "HTTP/%1.1f %d%s%s" _EOL, \
21897 + (_http_ptr)->version>0.0?(_http_ptr)->version:1.1, \
21898 + (_http_ptr)->info.response.code?(_http_ptr)->info.response.code:200, \
21899 + (_http_ptr)->info.response.status&&*(_http_ptr)->info.response.status ? " ":"", \
21900 + STR_PTR((_http_ptr)->info.response.status)
21902 +typedef struct _http_request_info_t {
21905 +} http_request_info;
21907 +typedef struct _http_response_info_t {
21910 +} http_response_info;
21912 +typedef union _http_info_union_t {
21913 + http_request_info request;
21914 + http_response_info response;
21915 +} http_info_union;
21917 +struct http_info {
21918 + http_info_union info;
21922 +typedef struct _http_info_t {
21923 + struct http_info http;
21927 +typedef void (*http_info_callback)(void **callback_data, HashTable **headers, http_info *info TSRMLS_DC);
21929 +#define http_info_default_callback _http_info_default_callback
21930 +PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC);
21931 +#define http_info_dtor _http_info_dtor
21932 +PHP_HTTP_API void _http_info_dtor(http_info *info);
21933 +#define http_info_parse(p, i) _http_info_parse_ex((p), (i), 1 TSRMLS_CC)
21934 +#define http_info_parse_ex(p, i, s) _http_info_parse_ex((p), (i), (s) TSRMLS_CC)
21935 +PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info , zend_bool silent TSRMLS_DC);
21940 + * Local variables:
21942 + * c-basic-offset: 4
21944 + * vim600: noet sw=4 ts=4 fdm=marker
21945 + * vim<600: noet sw=4 ts=4
21949 +++ b/ext/http/php_http_message_api.h
21952 + +--------------------------------------------------------------------+
21954 + +--------------------------------------------------------------------+
21955 + | Redistribution and use in source and binary forms, with or without |
21956 + | modification, are permitted provided that the conditions mentioned |
21957 + | in the accompanying LICENSE file are met. |
21958 + +--------------------------------------------------------------------+
21959 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21960 + +--------------------------------------------------------------------+
21963 +/* $Id: php_http_message_api.h 292841 2009-12-31 08:48:57Z mike $ */
21965 +#ifndef PHP_HTTP_MESSAGE_API_H
21966 +#define PHP_HTTP_MESSAGE_API_H
21968 +#include "php_http_info_api.h"
21970 +typedef enum _http_message_type_t {
21971 + HTTP_MSG_NONE = 0,
21972 + HTTP_MSG_REQUEST = IS_HTTP_REQUEST,
21973 + HTTP_MSG_RESPONSE = IS_HTTP_RESPONSE,
21974 +} http_message_type;
21976 +typedef struct _http_message_t http_message;
21978 +struct _http_message_t {
21981 + http_message_type type;
21982 + struct http_info http;
21983 + http_message *parent;
21986 +/* required minimum length of an HTTP message "HTTP/1.1" */
21987 +#define HTTP_MSG_MIN_SIZE 8
21989 +/* shorthand for type checks */
21990 +#define HTTP_MSG_TYPE(TYPE, msg) ((msg) && ((msg)->type == HTTP_MSG_ ##TYPE))
21992 +#define http_message_new() http_message_init_ex(NULL, 0)
21993 +#define http_message_init(m) http_message_init_ex((m), 0)
21994 +#define http_message_init_ex(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
21995 +#define http_message_init_rel(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
21996 +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);
21997 +#define http_message_init_env(m, t) _http_message_init_env((m), (t) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
21998 +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);
22000 +#define http_message_set_type(m, t) _http_message_set_type((m), (t))
22001 +PHP_HTTP_API void _http_message_set_type(http_message *m, http_message_type t);
22003 +#define http_message_set_info(m, i) _http_message_set_info((m), (i))
22004 +PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info);
22006 +#define http_message_header(m, h) _http_message_header_ex((m), (h), sizeof(h), 1)
22007 +#define http_message_header_ex _http_message_header_ex
22008 +static inline zval *_http_message_header_ex(http_message *msg, char *key_str, size_t key_len, int join)
22011 + if (SUCCESS == zend_hash_find(&msg->hdrs, key_str, key_len, (void *) &header)) {
22012 + if (join && Z_TYPE_PP(header) == IS_ARRAY) {
22013 + zval *header_str, **val;
22014 + HashPosition pos;
22017 + phpstr_init(&str);
22018 + MAKE_STD_ZVAL(header_str);
22019 + FOREACH_VAL(pos, *header, val) {
22020 + phpstr_appendf(&str, PHPSTR_LEN(&str) ? ", %s":"%s", Z_STRVAL_PP(val));
22022 + phpstr_fix(&str);
22023 + ZVAL_STRINGL(header_str, PHPSTR_VAL(&str), PHPSTR_LEN(&str), 0);
22024 + return header_str;
22026 + ZVAL_ADDREF(*header);
22033 +#define http_message_count(c, m) \
22035 + http_message *__tmp_msg = (m); \
22036 + for (c = 0; __tmp_msg; __tmp_msg = __tmp_msg->parent, ++(c)); \
22039 +#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l))
22040 +#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)
22041 +#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)
22042 +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);
22044 +#define http_message_tostring(m, s, l) _http_message_tostring((m), (s), (l))
22045 +PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length);
22047 +#define http_message_serialize(m, s, l) _http_message_serialize((m), (s), (l))
22048 +PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length);
22050 +#define http_message_reverse(m) _http_message_reverse(m)
22051 +PHP_HTTP_API http_message *_http_message_reverse(http_message *msg);
22053 +#define http_message_interconnect(m1, m2) _http_message_interconnect((m1), (m2))
22054 +PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2);
22056 +#define http_message_tostruct_recursive(m, s) _http_message_tostruct_recursive((m), (s) TSRMLS_CC)
22057 +PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *strct TSRMLS_DC);
22059 +#define http_message_send(m) _http_message_send((m) TSRMLS_CC)
22060 +PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC);
22062 +#define http_message_dup(m) _http_message_dup((m) TSRMLS_CC)
22063 +PHP_HTTP_API http_message *_http_message_dup(http_message *msg TSRMLS_DC);
22065 +#define http_message_dtor(m) _http_message_dtor((m))
22066 +PHP_HTTP_API void _http_message_dtor(http_message *message);
22068 +#define http_message_free(m) _http_message_free((m))
22069 +PHP_HTTP_API void _http_message_free(http_message **message);
22074 + * Local variables:
22076 + * c-basic-offset: 4
22078 + * vim600: noet sw=4 ts=4 fdm=marker
22079 + * vim<600: noet sw=4 ts=4
22083 +++ b/ext/http/php_http_message_object.h
22086 + +--------------------------------------------------------------------+
22088 + +--------------------------------------------------------------------+
22089 + | Redistribution and use in source and binary forms, with or without |
22090 + | modification, are permitted provided that the conditions mentioned |
22091 + | in the accompanying LICENSE file are met. |
22092 + +--------------------------------------------------------------------+
22093 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22094 + +--------------------------------------------------------------------+
22097 +/* $Id: php_http_message_object.h 298590 2010-04-26 11:46:35Z mike $ */
22099 +#ifndef PHP_HTTP_MESSAGE_OBJECT_H
22100 +#define PHP_HTTP_MESSAGE_OBJECT_H
22101 +#ifdef ZEND_ENGINE_2
22103 +typedef struct _http_message_object_t {
22105 + http_message *message;
22106 + zend_object_value parent;
22108 +} http_message_object;
22110 +extern zend_class_entry *http_message_object_ce;
22111 +extern zend_function_entry http_message_object_fe[];
22113 +extern PHP_MINIT_FUNCTION(http_message_object);
22114 +extern PHP_MSHUTDOWN_FUNCTION(http_message_object);
22116 +#define http_message_object_prepend(o, p) http_message_object_prepend_ex((o), (p), 1)
22117 +#define http_message_object_prepend_ex(o, p, t) _http_message_object_prepend_ex((o), (p), (t) TSRMLS_CC)
22118 +extern void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC);
22120 +#define http_message_object_reverse(t, r) _http_message_object_reverse((t), (r) TSRMLS_CC)
22121 +extern void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC);
22123 +#define http_message_object_new(ce) _http_message_object_new((ce) TSRMLS_CC)
22124 +extern zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC);
22125 +#define http_message_object_new_ex(ce, msg, ptr) _http_message_object_new_ex((ce), (msg), (ptr) TSRMLS_CC)
22126 +extern zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC);
22127 +#define http_message_object_clone(zobj) _http_message_object_clone_obj(zobj TSRMLS_CC)
22128 +extern zend_object_value _http_message_object_clone_obj(zval *object TSRMLS_DC);
22129 +#define http_message_object_free(o) _http_message_object_free((o) TSRMLS_CC)
22130 +extern void _http_message_object_free(zend_object *object TSRMLS_DC);
22132 +#define HTTP_MSG_CHECK_OBJ(obj, dofail) \
22133 + if (!(obj)->message) { \
22134 + http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is empty"); \
22137 +#define HTTP_MSG_CHECK_STD() HTTP_MSG_CHECK_OBJ(obj, RETURN_FALSE)
22139 +#define HTTP_MSG_INIT_OBJ(obj) \
22140 + if (!(obj)->message) { \
22141 + (obj)->message = http_message_new(); \
22143 +#define HTTP_MSG_INIT_STD() HTTP_MSG_INIT_OBJ(obj)
22145 +PHP_METHOD(HttpMessage, __construct);
22146 +PHP_METHOD(HttpMessage, getBody);
22147 +PHP_METHOD(HttpMessage, setBody);
22148 +PHP_METHOD(HttpMessage, getHeader);
22149 +PHP_METHOD(HttpMessage, getHeaders);
22150 +PHP_METHOD(HttpMessage, setHeaders);
22151 +PHP_METHOD(HttpMessage, addHeaders);
22152 +PHP_METHOD(HttpMessage, getType);
22153 +PHP_METHOD(HttpMessage, setType);
22154 +PHP_METHOD(HttpMessage, getInfo);
22155 +PHP_METHOD(HttpMessage, setInfo);
22156 +PHP_METHOD(HttpMessage, getResponseCode);
22157 +PHP_METHOD(HttpMessage, setResponseCode);
22158 +PHP_METHOD(HttpMessage, getResponseStatus);
22159 +PHP_METHOD(HttpMessage, setResponseStatus);
22160 +PHP_METHOD(HttpMessage, getRequestMethod);
22161 +PHP_METHOD(HttpMessage, setRequestMethod);
22162 +PHP_METHOD(HttpMessage, getRequestUrl);
22163 +PHP_METHOD(HttpMessage, setRequestUrl);
22164 +PHP_METHOD(HttpMessage, getHttpVersion);
22165 +PHP_METHOD(HttpMessage, setHttpVersion);
22166 +PHP_METHOD(HttpMessage, guessContentType);
22167 +PHP_METHOD(HttpMessage, getParentMessage);
22168 +PHP_METHOD(HttpMessage, send);
22169 +PHP_METHOD(HttpMessage, toString);
22170 +PHP_METHOD(HttpMessage, toMessageTypeObject);
22172 +PHP_METHOD(HttpMessage, count);
22173 +PHP_METHOD(HttpMessage, serialize);
22174 +PHP_METHOD(HttpMessage, unserialize);
22175 +PHP_METHOD(HttpMessage, rewind);
22176 +PHP_METHOD(HttpMessage, valid);
22177 +PHP_METHOD(HttpMessage, current);
22178 +PHP_METHOD(HttpMessage, key);
22179 +PHP_METHOD(HttpMessage, next);
22181 +PHP_METHOD(HttpMessage, factory);
22182 +PHP_METHOD(HttpMessage, fromEnv);
22184 +PHP_METHOD(HttpMessage, detach);
22185 +PHP_METHOD(HttpMessage, prepend);
22186 +PHP_METHOD(HttpMessage, reverse);
22192 + * Local variables:
22194 + * c-basic-offset: 4
22196 + * vim600: noet sw=4 ts=4 fdm=marker
22197 + * vim<600: noet sw=4 ts=4
22201 +++ b/ext/http/php_http_persistent_handle_api.h
22204 + +--------------------------------------------------------------------+
22206 + +--------------------------------------------------------------------+
22207 + | Redistribution and use in source and binary forms, with or without |
22208 + | modification, are permitted provided that the conditions mentioned |
22209 + | in the accompanying LICENSE file are met. |
22210 + +--------------------------------------------------------------------+
22211 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22212 + +--------------------------------------------------------------------+
22215 +/* $Id: php_http_persistent_handle_api.h 292841 2009-12-31 08:48:57Z mike $ */
22217 +#ifndef HTTP_PERSISTENT_HANDLE_H
22218 +#define HTTP_PERSISTENT_HANDLE_H
22220 +typedef void *(*http_persistent_handle_ctor)(void);
22221 +typedef void (*http_persistent_handle_dtor)(void *handle);
22222 +typedef void *(*http_persistent_handle_copy)(void *handle);
22224 +PHP_MINIT_FUNCTION(http_persistent_handle);
22225 +PHP_MSHUTDOWN_FUNCTION(http_persistent_handle);
22227 +#define http_persistent_handle_provide(n, c, d, cc) _http_persistent_handle_provide_ex((n), strlen(n), (c), (d), (cc))
22228 +#define http_persistent_handle_provide_ex(n, l, c, d, cc) _http_persistent_handle_provide_ex((n), (l), (c), (d), (cc))
22229 +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);
22231 +#define http_persistent_handle_cleanup(n, c) _http_persistent_handle_cleanup_ex((n), strlen(n), (c) TSRMLS_CC)
22232 +#define http_persistent_handle_cleanup_ex(n, l,c ) _http_persistent_handle_cleanup_ex((n), (l), (c) TSRMLS_CC)
22233 +PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC);
22235 +#define http_persistent_handle_statall() _http_persistent_handle_statall_ex(NULL TSRMLS_CC)
22236 +#define http_persistent_handle_statall_ex(ht) _http_persistent_handle_statall_ex((ht) TSRMLS_CC)
22237 +PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC);
22239 +#define http_persistent_handle_acquire(n, h) _http_persistent_handle_acquire_ex((n), strlen(n), (h) TSRMLS_CC)
22240 +#define http_persistent_handle_acquire_ex(n, l, h) _http_persistent_handle_acquire_ex((n), (l), (h) TSRMLS_CC)
22241 +PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
22243 +#define http_persistent_handle_release(n, h) _http_persistent_handle_release_ex((n), strlen(n), (h) TSRMLS_CC)
22244 +#define http_persistent_handle_release_ex(n, l, h) _http_persistent_handle_release_ex((n), (l), (h) TSRMLS_CC)
22245 +PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
22247 +#define http_persistent_handle_accrete(n, oh, nh) _http_persistent_handle_accrete_ex((n), strlen(n), (oh), (nh) TSRMLS_CC)
22248 +#define http_persistent_handle_accrete_ex(n, l, oh, nh) _http_persistent_handle_accrete_ex((n), (l), (oh), (nh) TSRMLS_CC)
22249 +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);
22251 +#endif /* HTTP_PERSISTENT_HANDLE_H */
22254 + * Local variables:
22256 + * c-basic-offset: 4
22258 + * vim600: noet sw=4 ts=4 fdm=marker
22259 + * vim<600: noet sw=4 ts=4
22262 +++ b/ext/http/php_http_querystring_api.h
22265 + +--------------------------------------------------------------------+
22267 + +--------------------------------------------------------------------+
22268 + | Redistribution and use in source and binary forms, with or without |
22269 + | modification, are permitted provided that the conditions mentioned |
22270 + | in the accompanying LICENSE file are met. |
22271 + +--------------------------------------------------------------------+
22272 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22273 + +--------------------------------------------------------------------+
22276 +/* $Id: php_http_querystring_api.h 292841 2009-12-31 08:48:57Z mike $ */
22278 +#ifndef PHP_HTTP_QUERYSTRING_API_H
22279 +#define PHP_HTTP_QUERYSTRING_API_H
22281 +#ifdef HTTP_HAVE_ICONV
22282 +#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC)
22283 +PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC);
22286 +#define http_querystring_update(qa, qs) _http_querystring_update((qa), (qs) TSRMLS_CC)
22287 +PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC);
22289 +#define http_querystring_modify(q, p) _http_querystring_modify((q), (p) TSRMLS_CC)
22290 +PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC);
22295 + * Local variables:
22297 + * c-basic-offset: 4
22299 + * vim600: noet sw=4 ts=4 fdm=marker
22300 + * vim<600: noet sw=4 ts=4
22303 +++ b/ext/http/php_http_querystring_object.h
22306 + +--------------------------------------------------------------------+
22308 + +--------------------------------------------------------------------+
22309 + | Redistribution and use in source and binary forms, with or without |
22310 + | modification, are permitted provided that the conditions mentioned |
22311 + | in the accompanying LICENSE file are met. |
22312 + +--------------------------------------------------------------------+
22313 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22314 + +--------------------------------------------------------------------+
22317 +/* $Id: php_http_querystring_object.h 292841 2009-12-31 08:48:57Z mike $ */
22319 +#ifndef PHP_HTTP_QUERYSTRING_OBJECT_H
22320 +#define PHP_HTTP_QUERYSTRING_OBJECT_H
22321 +#ifdef ZEND_ENGINE_2
22323 +typedef struct _http_querystring_object_t {
22325 +} http_querystring_object;
22327 +#define HTTP_QUERYSTRING_TYPE_BOOL IS_BOOL
22328 +#define HTTP_QUERYSTRING_TYPE_INT IS_LONG
22329 +#define HTTP_QUERYSTRING_TYPE_FLOAT IS_DOUBLE
22330 +#define HTTP_QUERYSTRING_TYPE_STRING IS_STRING
22331 +#define HTTP_QUERYSTRING_TYPE_ARRAY IS_ARRAY
22332 +#define HTTP_QUERYSTRING_TYPE_OBJECT IS_OBJECT
22334 +extern zend_class_entry *http_querystring_object_ce;
22335 +extern zend_function_entry http_querystring_object_fe[];
22337 +extern PHP_MINIT_FUNCTION(http_querystring_object);
22339 +#define http_querystring_object_new(ce) _http_querystring_object_new((ce) TSRMLS_CC)
22340 +extern zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC);
22341 +#define http_querystring_object_new_ex(ce, n, ptr) _http_querystring_object_new_ex((ce), (n), (ptr) TSRMLS_CC)
22342 +extern zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC);
22343 +#define http_querystring_object_free(o) _http_querystring_object_free((o) TSRMLS_CC)
22344 +extern void _http_querystring_object_free(zend_object *object TSRMLS_DC);
22346 +PHP_METHOD(HttpQueryString, __construct);
22347 +PHP_METHOD(HttpQueryString, toString);
22348 +PHP_METHOD(HttpQueryString, toArray);
22349 +PHP_METHOD(HttpQueryString, get);
22350 +PHP_METHOD(HttpQueryString, set);
22351 +PHP_METHOD(HttpQueryString, mod);
22352 +PHP_METHOD(HttpQueryString, getBool);
22353 +PHP_METHOD(HttpQueryString, getInt);
22354 +PHP_METHOD(HttpQueryString, getFloat);
22355 +PHP_METHOD(HttpQueryString, getString);
22356 +PHP_METHOD(HttpQueryString, getArray);
22357 +PHP_METHOD(HttpQueryString, getObject);
22358 +#ifdef HTTP_HAVE_ICONV
22359 +PHP_METHOD(HttpQueryString, xlate);
22361 +PHP_METHOD(HttpQueryString, factory);
22363 +PHP_METHOD(HttpQueryString, singleton);
22365 +PHP_METHOD(HttpQueryString, serialize);
22366 +PHP_METHOD(HttpQueryString, unserialize);
22367 +PHP_METHOD(HttpQueryString, offsetGet);
22368 +PHP_METHOD(HttpQueryString, offsetSet);
22369 +PHP_METHOD(HttpQueryString, offsetExists);
22370 +PHP_METHOD(HttpQueryString, offsetUnset);
22375 + * Local variables:
22377 + * c-basic-offset: 4
22379 + * vim600: noet sw=4 ts=4 fdm=marker
22380 + * vim<600: noet sw=4 ts=4
22384 +++ b/ext/http/php_http_request_api.h
22387 + +--------------------------------------------------------------------+
22389 + +--------------------------------------------------------------------+
22390 + | Redistribution and use in source and binary forms, with or without |
22391 + | modification, are permitted provided that the conditions mentioned |
22392 + | in the accompanying LICENSE file are met. |
22393 + +--------------------------------------------------------------------+
22394 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22395 + +--------------------------------------------------------------------+
22398 +/* $Id: php_http_request_api.h 292841 2009-12-31 08:48:57Z mike $ */
22400 +#ifndef PHP_HTTP_REQUEST_API_H
22401 +#define PHP_HTTP_REQUEST_API_H
22403 +#ifdef HTTP_HAVE_CURL
22405 +#include "php_http_request_body_api.h"
22406 +#include "php_http_request_method_api.h"
22408 +extern PHP_MINIT_FUNCTION(http_request);
22409 +extern PHP_MSHUTDOWN_FUNCTION(http_request);
22411 +typedef struct _http_request_t {
22414 + http_request_method meth;
22415 + http_request_body *body;
22418 + curl_infotype last_type;
22425 + HashTable options;
22426 + struct curl_slist *headers;
22434 + char _error[CURL_ERROR_SIZE+1];
22435 + zval *_progress_callback;
22441 + uint _in_progress_cb:1;
22446 +# define pestrndup(s,l,p) _pestrndup((s),(l),(p))
22447 +static inline void *_pestrndup(const void *s, size_t l, int p)
22449 + void *d = pemalloc(l+1, p);
22451 + ((char *) d)[l] = '\0';
22456 +/* CURLOPT_PRIVATE storage living as long as a CURL handle */
22457 +typedef struct _http_request_storage_t {
22459 + char *cookiestore;
22460 + char errorbuffer[CURL_ERROR_SIZE];
22461 +} http_request_storage;
22463 +static inline http_request_storage *http_request_storage_get(CURL *ch)
22465 + http_request_storage *st = NULL;
22466 + curl_easy_getinfo(ch, CURLINFO_PRIVATE, &st);
22470 +#define http_curl_init(r) http_curl_init_ex(NULL, (r))
22471 +#define http_curl_init_ex(c, r) _http_curl_init_ex((c), (r) TSRMLS_CC)
22472 +PHP_HTTP_API CURL *_http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC);
22474 +#define http_curl_free(c) _http_curl_free((c) TSRMLS_CC)
22475 +PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC);
22477 +#define http_curl_copy(c) _http_curl_copy((c) TSRMLS_CC)
22478 +PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC);
22480 +#define http_request_new() _http_request_init_ex(NULL, NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
22481 +#define http_request_init(r) _http_request_init_ex((r), NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
22482 +#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)
22483 +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);
22485 +#define http_request_dtor(r) _http_request_dtor((r))
22486 +PHP_HTTP_API void _http_request_dtor(http_request *request);
22488 +#define http_request_free(r) _http_request_free((r))
22489 +PHP_HTTP_API void _http_request_free(http_request **request);
22491 +#define http_request_reset(r) _http_request_reset(r)
22492 +PHP_HTTP_API void _http_request_reset(http_request *r);
22494 +#define http_request_enable_cookies(r) _http_request_enable_cookies(r)
22495 +PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request);
22497 +#define http_request_reset_cookies(r, s) _http_request_reset_cookies((r), (s))
22498 +PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only);
22500 +#define http_request_flush_cookies(r) _http_request_flush_cookies(r)
22501 +PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request);
22503 +#define http_request_defaults(r) _http_request_defaults(r)
22504 +PHP_HTTP_API void _http_request_defaults(http_request *request);
22506 +#define http_request_prepare(r, o) _http_request_prepare((r), (o))
22507 +PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options);
22509 +#define http_request_exec(r) _http_request_exec((r))
22510 +PHP_HTTP_API void _http_request_exec(http_request *request);
22512 +#define http_request_info(r, i) _http_request_info((r), (i))
22513 +PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info);
22515 +#define http_request_set_progress_callback(r, cb) _http_request_set_progress_callback((r), (cb))
22516 +PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb);
22522 + * Local variables:
22524 + * c-basic-offset: 4
22526 + * vim600: noet sw=4 ts=4 fdm=marker
22527 + * vim<600: noet sw=4 ts=4
22531 +++ b/ext/http/php_http_request_body_api.h
22534 + +--------------------------------------------------------------------+
22536 + +--------------------------------------------------------------------+
22537 + | Redistribution and use in source and binary forms, with or without |
22538 + | modification, are permitted provided that the conditions mentioned |
22539 + | in the accompanying LICENSE file are met. |
22540 + +--------------------------------------------------------------------+
22541 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22542 + +--------------------------------------------------------------------+
22545 +/* $Id: php_http_request_body_api.h 292841 2009-12-31 08:48:57Z mike $ */
22547 +#ifndef PHP_HTTP_REQUEST_BODY_API_H
22548 +#define PHP_HTTP_REQUEST_BODY_API_H
22550 +#ifdef HTTP_HAVE_CURL
22552 +#define HTTP_REQUEST_BODY_EMPTY 0
22553 +#define HTTP_REQUEST_BODY_CSTRING 1
22554 +#define HTTP_REQUEST_BODY_CURLPOST 2
22555 +#define HTTP_REQUEST_BODY_UPLOADFILE 3
22556 +typedef struct _http_request_body_t {
22562 +} http_request_body;
22565 +#define http_request_body_new() http_request_body_init(NULL)
22566 +#define http_request_body_init(b) http_request_body_init_ex((b), 0, NULL, 0, 0)
22567 +#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)
22568 +#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)
22569 +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);
22571 +#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)
22572 +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);
22574 +#define http_request_body_encode(b, s, l) _http_request_body_encode((b), (s), (l) TSRMLS_CC)
22575 +PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC);
22577 +#define http_request_body_dtor(b) _http_request_body_dtor((b) TSRMLS_CC)
22578 +PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC);
22580 +#define http_request_body_free(b) _http_request_body_free((b) TSRMLS_CC)
22581 +PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC);
22587 + * Local variables:
22589 + * c-basic-offset: 4
22591 + * vim600: noet sw=4 ts=4 fdm=marker
22592 + * vim<600: noet sw=4 ts=4
22596 +++ b/ext/http/php_http_request_datashare_api.h
22599 + +--------------------------------------------------------------------+
22601 + +--------------------------------------------------------------------+
22602 + | Redistribution and use in source and binary forms, with or without |
22603 + | modification, are permitted provided that the conditions mentioned |
22604 + | in the accompanying LICENSE file are met. |
22605 + +--------------------------------------------------------------------+
22606 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22607 + +--------------------------------------------------------------------+
22610 +/* $Id: php_http_request_datashare_api.h 292841 2009-12-31 08:48:57Z mike $ */
22612 +#ifndef PHP_HTTP_REQUEST_DATASHARE_API_H
22613 +#define PHP_HTTP_REQUEST_DATASHARE_API_H
22614 +#ifdef HTTP_HAVE_CURL
22615 +#ifdef ZEND_ENGINE_2
22618 +typedef struct _http_request_datashare_lock_t {
22621 +} http_request_datashare_lock;
22623 +typedef union _http_request_datashare_handle_t {
22624 + zend_llist *list;
22625 + http_request_datashare_lock *locks;
22626 +} http_request_datashare_handle;
22628 +typedef struct _http_request_datashare_handle_t {
22629 + zend_llist *list;
22630 +} http_request_datashare_handle;
22633 +typedef struct _http_request_datashare_t {
22635 + zend_bool persistent;
22636 + http_request_datashare_handle handle;
22637 +} http_request_datashare;
22639 +#define HTTP_RSHARE_HANDLES(s) ((s)->persistent ? &HTTP_G->request.datashare.handles : (s)->handle.list)
22641 +#define http_request_datashare_global_get _http_request_datashare_global_get
22642 +extern http_request_datashare *_http_request_datashare_global_get(void);
22644 +extern PHP_MINIT_FUNCTION(http_request_datashare);
22645 +extern PHP_MSHUTDOWN_FUNCTION(http_request_datashare);
22646 +extern PHP_RINIT_FUNCTION(http_request_datashare);
22647 +extern PHP_RSHUTDOWN_FUNCTION(http_request_datashare);
22649 +#define http_request_datashare_new() _http_request_datashare_init_ex(NULL, 0 TSRMLS_CC)
22650 +#define http_request_datashare_init(s) _http_request_datashare_init_ex((s), 0 TSRMLS_CC)
22651 +#define http_request_datashare_init_ex(s, p) _http_request_datashare_init_ex((s), (p) TSRMLS_CC)
22652 +PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC);
22654 +#define http_request_datashare_attach(s, r) _http_request_datashare_attach((s), (r) TSRMLS_CC)
22655 +PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC);
22657 +#define http_request_datashare_detach(s, r) _http_request_datashare_detach((s), (r) TSRMLS_CC)
22658 +PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC);
22660 +#define http_request_datashare_detach_all(s) _http_request_datashare_detach_all((s) TSRMLS_CC)
22661 +PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC);
22663 +#define http_request_datashare_dtor(s) _http_request_datashare_dtor((s) TSRMLS_CC)
22664 +PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC);
22666 +#define http_request_datashare_free(s) _http_request_datashare_free((s) TSRMLS_CC)
22667 +PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC);
22669 +#define http_request_datashare_set(s, o, l, e) _http_request_datashare_set((s), (o), (l), (e) TSRMLS_CC)
22670 +PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC);
22678 + * Local variables:
22680 + * c-basic-offset: 4
22682 + * vim600: noet sw=4 ts=4 fdm=marker
22683 + * vim<600: noet sw=4 ts=4
22687 +++ b/ext/http/php_http_request_int.h
22690 + +--------------------------------------------------------------------+
22692 + +--------------------------------------------------------------------+
22693 + | Redistribution and use in source and binary forms, with or without |
22694 + | modification, are permitted provided that the conditions mentioned |
22695 + | in the accompanying LICENSE file are met. |
22696 + +--------------------------------------------------------------------+
22697 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22698 + +--------------------------------------------------------------------+
22701 +/* $Id: php_http_request_int.h 292841 2009-12-31 08:48:57Z mike $ */
22703 +#if defined(ZTS) && defined(HTTP_HAVE_SSL)
22705 +# define HTTP_NEED_OPENSSL_TSL
22706 +# include <openssl/crypto.h>
22707 +# else /* !PHP_WIN32 */
22708 +# if defined(HTTP_HAVE_OPENSSL)
22709 +# define HTTP_NEED_OPENSSL_TSL
22710 +# include <openssl/crypto.h>
22711 +# elif defined(HTTP_HAVE_GNUTLS)
22712 +# define HTTP_NEED_GNUTLS_TSL
22713 +# include <gcrypt.h>
22716 + "libcurl was compiled with SSL support, but configure could not determine which" \
22717 + "library was used; thus no SSL crypto locking callbacks will be set, which may " \
22718 + "cause random crashes on SSL requests"
22719 +# endif /* HTTP_HAVE_OPENSSL || HTTP_HAVE_GNUTLS */
22720 +# endif /* PHP_WIN32 */
22721 +#endif /* ZTS && HTTP_HAVE_SSL */
22723 +#define HTTP_CURL_OPT(OPTION, p) curl_easy_setopt((request->ch), OPTION, (p))
22725 +#define HTTP_CURL_OPT_STRING(OPTION, ldiff, obdc) \
22727 + char *K = #OPTION; \
22728 + HTTP_CURL_OPT_STRING_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION, obdc); \
22730 +#define HTTP_CURL_OPT_STRING_EX(keyname, optname, obdc) \
22731 + if (!strcasecmp(key.str, keyname)) { \
22732 + zval *copy = http_request_option_cache_ex(request, keyname, strlen(keyname)+1, 0, http_zsep(IS_STRING, *param)); \
22734 + HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(copy), return FAILURE); \
22736 + HTTP_CURL_OPT(optname, Z_STRVAL_P(copy)); \
22737 + zval_ptr_dtor(©); \
22740 +#define HTTP_CURL_OPT_LONG(OPTION, ldiff) \
22742 + char *K = #OPTION; \
22743 + HTTP_CURL_OPT_LONG_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION); \
22745 +#define HTTP_CURL_OPT_LONG_EX(keyname, optname) \
22746 + if (!strcasecmp(key.str, keyname)) { \
22747 + zval *copy = http_zsep(IS_LONG, *param); \
22748 + HTTP_CURL_OPT(optname, Z_LVAL_P(copy)); \
22749 + zval_ptr_dtor(©); \
22754 + * Local variables:
22756 + * c-basic-offset: 4
22758 + * vim600: noet sw=4 ts=4 fdm=marker
22759 + * vim<600: noet sw=4 ts=4
22762 +++ b/ext/http/php_http_request_method_api.h
22765 + +--------------------------------------------------------------------+
22767 + +--------------------------------------------------------------------+
22768 + | Redistribution and use in source and binary forms, with or without |
22769 + | modification, are permitted provided that the conditions mentioned |
22770 + | in the accompanying LICENSE file are met. |
22771 + +--------------------------------------------------------------------+
22772 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22773 + +--------------------------------------------------------------------+
22776 +/* $Id: php_http_request_method_api.h 292841 2009-12-31 08:48:57Z mike $ */
22778 +#ifndef PHP_HTTP_REQUEST_METHOD_API_H
22779 +#define PHP_HTTP_REQUEST_METHOD_API_H
22781 +typedef enum _http_request_method_t {
22782 + /* force the enum to be signed */
22783 + HTTP_NEG_REQUEST_METHOD =-1,
22784 + HTTP_NO_REQUEST_METHOD = 0,
22791 + HTTP_OPTIONS = 6,
22793 + HTTP_CONNECT = 8,
22794 + /* WebDAV - RFC 2518 */
22795 + HTTP_PROPFIND = 9,
22796 + HTTP_PROPPATCH = 10,
22801 + HTTP_UNLOCK = 15,
22802 + /* WebDAV Versioning - RFC 3253 */
22803 + HTTP_VERSION_CONTROL = 16,
22804 + HTTP_REPORT = 17,
22805 + HTTP_CHECKOUT = 18,
22806 + HTTP_CHECKIN = 19,
22807 + HTTP_UNCHECKOUT = 20,
22808 + HTTP_MKWORKSPACE = 21,
22809 + HTTP_UPDATE = 22,
22812 + HTTP_BASELINE_CONTROL = 25,
22813 + HTTP_MKACTIVITY = 26,
22814 + /* WebDAV Access Control - RFC 3744 */
22816 + HTTP_MAX_REQUEST_METHOD = 28
22817 +} http_request_method;
22819 +#define HTTP_MIN_REQUEST_METHOD (HTTP_NO_REQUEST_METHOD + 1)
22820 +#define HTTP_STD_REQUEST_METHOD(m) ((m > HTTP_NO_REQUEST_METHOD) && (m < HTTP_MAX_REQUEST_METHOD))
22822 +extern PHP_MINIT_FUNCTION(http_request_method);
22823 +extern PHP_RINIT_FUNCTION(http_request_method);
22824 +extern PHP_RSHUTDOWN_FUNCTION(http_request_method);
22826 +#define http_request_method_name(m) _http_request_method_name((m) TSRMLS_CC)
22827 +PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC);
22829 +#define http_request_method_exists(u, l, c) _http_request_method_exists((u), (l), (c) TSRMLS_CC)
22830 +PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id, const char *name TSRMLS_DC);
22832 +#define http_request_method_register(m, l) _http_request_method_register((m), (l) TSRMLS_CC)
22833 +PHP_HTTP_API int _http_request_method_register(const char *method, int method_name_len TSRMLS_DC);
22835 +#define http_request_method_unregister(mn) _http_request_method_unregister((mn) TSRMLS_CC)
22836 +PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC);
22841 + * Local variables:
22843 + * c-basic-offset: 4
22845 + * vim600: noet sw=4 ts=4 fdm=marker
22846 + * vim<600: noet sw=4 ts=4
22850 +++ b/ext/http/php_http_request_object.h
22853 + +--------------------------------------------------------------------+
22855 + +--------------------------------------------------------------------+
22856 + | Redistribution and use in source and binary forms, with or without |
22857 + | modification, are permitted provided that the conditions mentioned |
22858 + | in the accompanying LICENSE file are met. |
22859 + +--------------------------------------------------------------------+
22860 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22861 + +--------------------------------------------------------------------+
22864 +/* $Id: php_http_request_object.h 292841 2009-12-31 08:48:57Z mike $ */
22866 +#ifndef PHP_HTTP_REQUEST_OBJECT_H
22867 +#define PHP_HTTP_REQUEST_OBJECT_H
22868 +#ifdef HTTP_HAVE_CURL
22869 +#ifdef ZEND_ENGINE_2
22871 +#include "php_http_request_api.h"
22872 +#include "php_http_request_pool_api.h"
22873 +#include "php_http_request_datashare_api.h"
22875 +typedef struct _http_request_object_t {
22877 + http_request *request;
22878 + http_request_pool *pool;
22879 + http_request_datashare *share;
22880 +} http_request_object;
22882 +extern zend_class_entry *http_request_object_ce;
22883 +extern zend_function_entry http_request_object_fe[];
22885 +extern PHP_MINIT_FUNCTION(http_request_object);
22887 +#define http_request_object_new(ce) _http_request_object_new((ce) TSRMLS_CC)
22888 +extern zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC);
22889 +#define http_request_object_new_ex(ce, ch, ptr) _http_request_object_new_ex((ce), (ch), (ptr) TSRMLS_CC)
22890 +extern zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC);
22891 +#define http_request_object_clone(zv) _http_request_object_clone_obj((zv) TSRMLS_CC)
22892 +extern zend_object_value _http_request_object_clone_obj(zval *zobject TSRMLS_DC);
22893 +#define http_request_object_free(o) _http_request_object_free((o) TSRMLS_CC)
22894 +extern void _http_request_object_free(zend_object *object TSRMLS_DC);
22896 +#define http_request_object_requesthandler(req, this) _http_request_object_requesthandler((req), (this) TSRMLS_CC)
22897 +extern STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC);
22898 +#define http_request_object_responsehandler(req, this) _http_request_object_responsehandler((req), (this) TSRMLS_CC)
22899 +extern STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC);
22901 +PHP_METHOD(HttpRequest, __construct);
22902 +PHP_METHOD(HttpRequest, setOptions);
22903 +PHP_METHOD(HttpRequest, getOptions);
22904 +PHP_METHOD(HttpRequest, addSslOptions);
22905 +PHP_METHOD(HttpRequest, setSslOptions);
22906 +PHP_METHOD(HttpRequest, getSslOptions);
22907 +PHP_METHOD(HttpRequest, addHeaders);
22908 +PHP_METHOD(HttpRequest, getHeaders);
22909 +PHP_METHOD(HttpRequest, setHeaders);
22910 +PHP_METHOD(HttpRequest, addCookies);
22911 +PHP_METHOD(HttpRequest, getCookies);
22912 +PHP_METHOD(HttpRequest, setCookies);
22913 +PHP_METHOD(HttpRequest, enableCookies);
22914 +PHP_METHOD(HttpRequest, resetCookies);
22915 +PHP_METHOD(HttpRequest, flushCookies);
22916 +PHP_METHOD(HttpRequest, setMethod);
22917 +PHP_METHOD(HttpRequest, getMethod);
22918 +PHP_METHOD(HttpRequest, setUrl);
22919 +PHP_METHOD(HttpRequest, getUrl);
22920 +PHP_METHOD(HttpRequest, setContentType);
22921 +PHP_METHOD(HttpRequest, getContentType);
22922 +PHP_METHOD(HttpRequest, setQueryData);
22923 +PHP_METHOD(HttpRequest, getQueryData);
22924 +PHP_METHOD(HttpRequest, addQueryData);
22925 +PHP_METHOD(HttpRequest, setPostFields);
22926 +PHP_METHOD(HttpRequest, getPostFields);
22927 +PHP_METHOD(HttpRequest, addPostFields);
22928 +PHP_METHOD(HttpRequest, getBody);
22929 +PHP_METHOD(HttpRequest, setBody);
22930 +PHP_METHOD(HttpRequest, addBody);
22931 +PHP_METHOD(HttpRequest, addPostFile);
22932 +PHP_METHOD(HttpRequest, setPostFiles);
22933 +PHP_METHOD(HttpRequest, getPostFiles);
22934 +PHP_METHOD(HttpRequest, setPutFile);
22935 +PHP_METHOD(HttpRequest, getPutFile);
22936 +PHP_METHOD(HttpRequest, getPutData);
22937 +PHP_METHOD(HttpRequest, setPutData);
22938 +PHP_METHOD(HttpRequest, addPutData);
22939 +PHP_METHOD(HttpRequest, send);
22940 +PHP_METHOD(HttpRequest, getResponseData);
22941 +PHP_METHOD(HttpRequest, getResponseHeader);
22942 +PHP_METHOD(HttpRequest, getResponseCookies);
22943 +PHP_METHOD(HttpRequest, getResponseCode);
22944 +PHP_METHOD(HttpRequest, getResponseStatus);
22945 +PHP_METHOD(HttpRequest, getResponseBody);
22946 +PHP_METHOD(HttpRequest, getResponseInfo);
22947 +PHP_METHOD(HttpRequest, getResponseMessage);
22948 +PHP_METHOD(HttpRequest, getRawResponseMessage);
22949 +PHP_METHOD(HttpRequest, getRequestMessage);
22950 +PHP_METHOD(HttpRequest, getRawRequestMessage);
22951 +PHP_METHOD(HttpRequest, getHistory);
22952 +PHP_METHOD(HttpRequest, clearHistory);
22953 +PHP_METHOD(HttpRequest, getMessageClass);
22954 +PHP_METHOD(HttpRequest, setMessageClass);
22955 +PHP_METHOD(HttpRequest, factory);
22962 + * Local variables:
22964 + * c-basic-offset: 4
22966 + * vim600: noet sw=4 ts=4 fdm=marker
22967 + * vim<600: noet sw=4 ts=4
22971 +++ b/ext/http/php_http_request_pool_api.h
22974 + +--------------------------------------------------------------------+
22976 + +--------------------------------------------------------------------+
22977 + | Redistribution and use in source and binary forms, with or without |
22978 + | modification, are permitted provided that the conditions mentioned |
22979 + | in the accompanying LICENSE file are met. |
22980 + +--------------------------------------------------------------------+
22981 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22982 + +--------------------------------------------------------------------+
22985 +/* $Id: php_http_request_pool_api.h 292841 2009-12-31 08:48:57Z mike $ */
22987 +#ifndef PHP_HTTP_REQUEST_POOL_API_H
22988 +#define PHP_HTTP_REQUEST_POOL_API_H
22989 +#ifdef HTTP_HAVE_CURL
22990 +#ifdef ZEND_ENGINE_2
22992 +typedef struct _http_request_pool_t {
22994 + zend_llist finished;
22995 + zend_llist handles;
23000 +#ifdef HTTP_HAVE_EVENT
23001 + struct event *timeout;
23002 + unsigned useevents:1;
23003 + unsigned runsocket:1;
23005 +} http_request_pool;
23007 +typedef int (*http_request_pool_apply_func)(http_request_pool *pool, zval *request);
23008 +typedef int (*http_request_pool_apply_with_arg_func)(http_request_pool *pool, zval *request, void *arg);
23010 +PHP_MINIT_FUNCTION(http_request_pool);
23011 +#ifdef HTTP_HAVE_EVENT
23012 +PHP_RINIT_FUNCTION(http_request_pool);
23015 +#define http_request_pool_timeout _http_request_pool_timeout
23016 +extern struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout);
23018 +#define http_request_pool_responsehandler _http_request_pool_responsehandler
23019 +extern void _http_request_pool_responsehandler(http_request_pool *pool);
23021 +#define http_request_pool_apply_responsehandler _http_request_pool_responsehandler
23022 +extern int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch);
23024 +#define http_request_pool_init(p) _http_request_pool_init((p) TSRMLS_CC)
23025 +PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC);
23027 +#define http_request_pool_attach(p, r) _http_request_pool_attach((p), (r))
23028 +PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request);
23030 +#define http_request_pool_detach(p, r) _http_request_pool_detach((p), (r))
23031 +PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request);
23033 +#define http_request_pool_apply(p, f) _http_request_pool_apply((p), (f))
23034 +PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb);
23036 +#define http_request_pool_apply_with_arg(p, f, a) _http_request_pool_apply_with_arg((p), (f), (a))
23037 +PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg);
23039 +#define http_request_pool_detach_all(p) _http_request_pool_detach_all((p))
23040 +PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool);
23042 +#define http_request_pool_send(p) _http_request_pool_send((p))
23043 +PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool);
23045 +#define http_request_pool_select _http_request_pool_select
23046 +PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool);
23048 +#define http_request_pool_select_ex _http_request_pool_select_ex
23049 +PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout);
23051 +#define http_request_pool_perform(p) _http_request_pool_perform((p))
23052 +PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool);
23054 +#define http_request_pool_dtor(p) _http_request_pool_dtor((p))
23055 +PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool);
23062 + * Local variables:
23064 + * c-basic-offset: 4
23066 + * vim600: noet sw=4 ts=4 fdm=marker
23067 + * vim<600: noet sw=4 ts=4
23071 +++ b/ext/http/php_http_requestdatashare_object.h
23074 + +--------------------------------------------------------------------+
23076 + +--------------------------------------------------------------------+
23077 + | Redistribution and use in source and binary forms, with or without |
23078 + | modification, are permitted provided that the conditions mentioned |
23079 + | in the accompanying LICENSE file are met. |
23080 + +--------------------------------------------------------------------+
23081 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23082 + +--------------------------------------------------------------------+
23085 +/* $Id: php_http_requestdatashare_object.h 292841 2009-12-31 08:48:57Z mike $ */
23087 +#ifndef PHP_HTTP_REQUEST_DATASHARE_OBJECT_H
23088 +#define PHP_HTTP_REQUEST_DATASHARE_OBJECT_H
23089 +#ifdef HTTP_HAVE_CURL
23090 +#ifdef ZEND_ENGINE_2
23092 +typedef struct _http_requestdatashare_object_t {
23094 + http_request_datashare *share;
23095 +} http_requestdatashare_object;
23097 +extern zend_class_entry *http_requestdatashare_object_ce;
23098 +extern zend_function_entry http_requestdatashare_object_fe[];
23100 +extern PHP_MINIT_FUNCTION(http_requestdatashare_object);
23102 +#define http_requestdatashare_object_new(ce) _http_requestdatashare_object_new((ce) TSRMLS_CC)
23103 +extern zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC);
23104 +#define http_requestdatashare_object_new_ex(ce, s, ptr) _http_requestdatashare_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
23105 +extern zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC);
23106 +#define http_requestdatashare_object_free(o) _http_requestdatashare_object_free((o) TSRMLS_CC)
23107 +extern void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC);
23109 +PHP_METHOD(HttpRequestDataShare, __destruct);
23110 +PHP_METHOD(HttpRequestDataShare, count);
23111 +PHP_METHOD(HttpRequestDataShare, attach);
23112 +PHP_METHOD(HttpRequestDataShare, detach);
23113 +PHP_METHOD(HttpRequestDataShare, reset);
23114 +PHP_METHOD(HttpRequestDataShare, factory);
23116 +PHP_METHOD(HttpRequestDataShare, singleton);
23124 + * Local variables:
23126 + * c-basic-offset: 4
23128 + * vim600: noet sw=4 ts=4 fdm=marker
23129 + * vim<600: noet sw=4 ts=4
23133 +++ b/ext/http/php_http_requestpool_object.h
23136 + +--------------------------------------------------------------------+
23138 + +--------------------------------------------------------------------+
23139 + | Redistribution and use in source and binary forms, with or without |
23140 + | modification, are permitted provided that the conditions mentioned |
23141 + | in the accompanying LICENSE file are met. |
23142 + +--------------------------------------------------------------------+
23143 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23144 + +--------------------------------------------------------------------+
23147 +/* $Id: php_http_requestpool_object.h 292841 2009-12-31 08:48:57Z mike $ */
23149 +#ifndef PHP_HTTP_REQUESTPOOL_OBJECT_H
23150 +#define PHP_HTTP_REQUESTPOOL_OBJECT_H
23151 +#ifdef HTTP_HAVE_CURL
23152 +#ifdef ZEND_ENGINE_2
23154 +typedef struct _http_requestpool_object_t {
23156 + http_request_pool pool;
23160 +} http_requestpool_object;
23162 +extern zend_class_entry *http_requestpool_object_ce;
23163 +extern zend_function_entry http_requestpool_object_fe[];
23165 +extern PHP_MINIT_FUNCTION(http_requestpool_object);
23167 +#define http_requestpool_object_new(ce) _http_requestpool_object_new(ce TSRMLS_CC)
23168 +extern zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC);
23169 +#define http_requestpool_object_free(o) _http_requestpool_object_free(o TSRMLS_CC)
23170 +extern void _http_requestpool_object_free(zend_object *object TSRMLS_DC);
23172 +PHP_METHOD(HttpRequestPool, __construct);
23173 +PHP_METHOD(HttpRequestPool, __destruct);
23174 +PHP_METHOD(HttpRequestPool, attach);
23175 +PHP_METHOD(HttpRequestPool, detach);
23176 +PHP_METHOD(HttpRequestPool, send);
23177 +PHP_METHOD(HttpRequestPool, reset);
23178 +PHP_METHOD(HttpRequestPool, socketPerform);
23179 +PHP_METHOD(HttpRequestPool, socketSelect);
23180 +PHP_METHOD(HttpRequestPool, valid);
23181 +PHP_METHOD(HttpRequestPool, current);
23182 +PHP_METHOD(HttpRequestPool, key);
23183 +PHP_METHOD(HttpRequestPool, next);
23184 +PHP_METHOD(HttpRequestPool, rewind);
23185 +PHP_METHOD(HttpRequestPool, count);
23186 +PHP_METHOD(HttpRequestPool, getAttachedRequests);
23187 +PHP_METHOD(HttpRequestPool, getFinishedRequests);
23188 +PHP_METHOD(HttpRequestPool, enablePipelining);
23189 +PHP_METHOD(HttpRequestPool, enableEvents);
23196 + * Local variables:
23198 + * c-basic-offset: 4
23200 + * vim600: noet sw=4 ts=4 fdm=marker
23201 + * vim<600: noet sw=4 ts=4
23205 +++ b/ext/http/php_http_response_object.h
23208 + +--------------------------------------------------------------------+
23210 + +--------------------------------------------------------------------+
23211 + | Redistribution and use in source and binary forms, with or without |
23212 + | modification, are permitted provided that the conditions mentioned |
23213 + | in the accompanying LICENSE file are met. |
23214 + +--------------------------------------------------------------------+
23215 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23216 + +--------------------------------------------------------------------+
23219 +/* $Id: php_http_response_object.h 292841 2009-12-31 08:48:57Z mike $ */
23221 +#ifndef PHP_HTTP_RESPONSE_OBJECT_H
23222 +#define PHP_HTTP_RESPONSE_OBJECT_H
23223 +#ifdef ZEND_ENGINE_2
23226 +extern zend_class_entry *http_response_object_ce;
23227 +extern zend_function_entry http_response_object_fe[];
23229 +extern PHP_MINIT_FUNCTION(http_response_object);
23231 +PHP_METHOD(HttpResponse, setHeader);
23232 +PHP_METHOD(HttpResponse, getHeader);
23233 +PHP_METHOD(HttpResponse, setETag);
23234 +PHP_METHOD(HttpResponse, getETag);
23235 +PHP_METHOD(HttpResponse, setLastModified);
23236 +PHP_METHOD(HttpResponse, getLastModified);
23237 +PHP_METHOD(HttpResponse, setContentDisposition);
23238 +PHP_METHOD(HttpResponse, getContentDisposition);
23239 +PHP_METHOD(HttpResponse, setContentType);
23240 +PHP_METHOD(HttpResponse, getContentType);
23241 +PHP_METHOD(HttpResponse, guessContentType);
23242 +PHP_METHOD(HttpResponse, setCache);
23243 +PHP_METHOD(HttpResponse, getCache);
23244 +PHP_METHOD(HttpResponse, setCacheControl);
23245 +PHP_METHOD(HttpResponse, getCacheControl);
23246 +PHP_METHOD(HttpResponse, setGzip);
23247 +PHP_METHOD(HttpResponse, getGzip);
23248 +PHP_METHOD(HttpResponse, setThrottleDelay);
23249 +PHP_METHOD(HttpResponse, getThrottleDelay);
23250 +PHP_METHOD(HttpResponse, setBufferSize);
23251 +PHP_METHOD(HttpResponse, getBufferSize);
23252 +PHP_METHOD(HttpResponse, setData);
23253 +PHP_METHOD(HttpResponse, getData);
23254 +PHP_METHOD(HttpResponse, setFile);
23255 +PHP_METHOD(HttpResponse, getFile);
23256 +PHP_METHOD(HttpResponse, setStream);
23257 +PHP_METHOD(HttpResponse, getStream);
23258 +PHP_METHOD(HttpResponse, send);
23259 +PHP_METHOD(HttpResponse, capture);
23266 + * Local variables:
23268 + * c-basic-offset: 4
23270 + * vim600: noet sw=4 ts=4 fdm=marker
23271 + * vim<600: noet sw=4 ts=4
23275 +++ b/ext/http/php_http_send_api.h
23278 + +--------------------------------------------------------------------+
23280 + +--------------------------------------------------------------------+
23281 + | Redistribution and use in source and binary forms, with or without |
23282 + | modification, are permitted provided that the conditions mentioned |
23283 + | in the accompanying LICENSE file are met. |
23284 + +--------------------------------------------------------------------+
23285 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23286 + +--------------------------------------------------------------------+
23289 +/* $Id: php_http_send_api.h 292841 2009-12-31 08:48:57Z mike $ */
23291 +#ifndef PHP_HTTP_SEND_API_H
23292 +#define PHP_HTTP_SEND_API_H
23294 +typedef enum _http_send_mode_t {
23299 +#define HTTP_REDIRECT 0L
23300 +#define HTTP_REDIRECT_PERM 301L
23301 +#define HTTP_REDIRECT_FOUND 302L
23302 +#define HTTP_REDIRECT_POST 303L
23303 +#define HTTP_REDIRECT_PROXY 305L
23304 +#define HTTP_REDIRECT_TEMP 307L
23306 +extern PHP_MINIT_FUNCTION(http_send);
23308 +#define http_send_status(s) sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) (long) (s) TSRMLS_CC)
23309 +#define http_send_header(n, v, r) _http_send_header_ex((n), strlen(n), (v), strlen(v), (r), NULL TSRMLS_CC)
23310 +#define http_send_header_ex(n, nl, v, vl, r, s) _http_send_header_ex((n), (nl), (v), (vl), (r), (s) TSRMLS_CC)
23311 +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);
23312 +#define http_send_header_string(h) _http_send_status_header_ex(0, (h), strlen(h), 1 TSRMLS_CC)
23313 +#define http_send_header_string_ex(h, l, r) _http_send_status_header_ex(0, (h), (l), (r) TSRMLS_CC)
23314 +#define http_send_status_header(s, h) _http_send_status_header_ex((s), (h), (h)?strlen(h):0, 1 TSRMLS_CC)
23315 +#define http_send_status_header_ex(s, h, l, r) _http_send_status_header_ex((s), (h), (l), (r) TSRMLS_CC)
23316 +PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC);
23318 +#define http_send_header_zval(n, z, r) http_send_header_zval_ex((n), strlen(n), (z), (r))
23319 +#define http_send_header_zval_ex(n, l, z, r) _http_send_header_zval_ex((n), (l), (z), (r) TSRMLS_CC)
23320 +PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC);
23322 +#define http_hide_header(h) http_hide_header_ex((h), strlen(h))
23323 +#define http_hide_header_ex(h, l) _http_hide_header_ex((h), (l) TSRMLS_CC)
23324 +PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC);
23326 +#define http_send_last_modified(t) _http_send_last_modified_ex((t), NULL TSRMLS_CC)
23327 +#define http_send_last_modified_ex(t, s) _http_send_last_modified_ex((t), (s) TSRMLS_CC)
23328 +PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC);
23330 +#define http_send_etag(e, l) _http_send_etag_ex((e), (l), NULL TSRMLS_CC)
23331 +#define http_send_etag_ex(e, l, s) _http_send_etag_ex((e), (l), (s) TSRMLS_CC)
23332 +PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC);
23334 +#define http_send_cache_control(cc, cl) http_send_header_ex("Cache-Control", lenof("Cache-Control"), (cc), (cl), 1, NULL)
23336 +#define http_send_content_type(c, l) _http_send_content_type((c), (l) TSRMLS_CC)
23337 +PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC);
23339 +#define http_send_content_disposition(f, l, i) _http_send_content_disposition((f), (l), (i) TSRMLS_CC)
23340 +PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC);
23342 +#define http_send_data(d, l) http_send((d), (l), SEND_DATA)
23343 +#define http_send_data_ex(d, l, nc) http_send_ex((d), (l), SEND_DATA, (nc))
23344 +#define http_send(d, s, m) _http_send_ex((d), (s), (m), 0 TSRMLS_CC)
23345 +#define http_send_ex(d, s, m, nc) _http_send_ex((d), (s), (m), (nc) TSRMLS_CC)
23346 +PHP_HTTP_API STATUS _http_send_ex(const void *data, size_t data_size, http_send_mode mode, zend_bool no_cache TSRMLS_DC);
23348 +#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)
23349 +#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))
23350 +#define http_send_stream(s) http_send_stream_ex((s), 0, 0)
23351 +#define http_send_stream_ex(s, c, nc) _http_send_stream_ex((s), (c), (nc) TSRMLS_CC)
23352 +PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *s, zend_bool close_stream, zend_bool no_cache TSRMLS_DC);
23354 +#define http_guess_content_type(mf, mm, d, l, m) _http_guess_content_type((mf), (mm), (d), (l), (m) TSRMLS_CC)
23355 +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);
23360 + * Local variables:
23362 + * c-basic-offset: 4
23364 + * vim600: noet sw=4 ts=4 fdm=marker
23365 + * vim<600: noet sw=4 ts=4
23369 +++ b/ext/http/php_http_std_defs.h
23372 + +--------------------------------------------------------------------+
23374 + +--------------------------------------------------------------------+
23375 + | Redistribution and use in source and binary forms, with or without |
23376 + | modification, are permitted provided that the conditions mentioned |
23377 + | in the accompanying LICENSE file are met. |
23378 + +--------------------------------------------------------------------+
23379 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23380 + +--------------------------------------------------------------------+
23383 +/* $Id: php_http_std_defs.h 310777 2011-05-05 06:43:10Z mike $ */
23385 +#ifndef PHP_HTTP_STD_DEFS_H
23386 +#define PHP_HTTP_STD_DEFS_H
23388 +#if defined(PHP_WIN32)
23389 +# if defined(HTTP_EXPORTS)
23390 +# define PHP_HTTP_API __declspec(dllexport)
23391 +# elif defined(COMPILE_DL_HTTP)
23392 +# define PHP_HTTP_API __declspec(dllimport)
23394 +# define PHP_HTTP_API
23397 +# define PHP_HTTP_API
23400 +/* make functions that return SUCCESS|FAILURE more obvious */
23401 +typedef int STATUS;
23404 +#define lenof(S) (sizeof(S) - 1)
23407 +# define MIN(a,b) (a<b?a:b)
23410 +# define MAX(a,b) (a>b?a:b)
23415 +# define STR_SET(STR, SET) \
23422 +#define STR_PTR(s) (s?s:"")
23424 +#define INIT_ZARR(zv, ht) \
23426 + INIT_PZVAL(&(zv)); \
23427 + Z_TYPE(zv) = IS_ARRAY; \
23428 + Z_ARRVAL(zv) = (ht); \
23431 +/* return bool (v == SUCCESS) */
23432 +#define RETVAL_SUCCESS(v) RETVAL_BOOL(SUCCESS == (v))
23433 +#define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v))
23434 +/* return object(values) */
23435 +#define RETVAL_OBJECT(o, addref) \
23436 + RETVAL_OBJVAL((o)->value.obj, addref)
23437 +#define RETURN_OBJECT(o, addref) \
23438 + RETVAL_OBJECT(o, addref); \
23440 +#define RETVAL_OBJVAL(ov, addref) \
23441 + ZVAL_OBJVAL(return_value, ov, addref)
23442 +#define RETURN_OBJVAL(ov, addref) \
23443 + RETVAL_OBJVAL(ov, addref); \
23445 +#define ZVAL_OBJVAL(zv, ov, addref) \
23446 + (zv)->type = IS_OBJECT; \
23447 + (zv)->value.obj = (ov);\
23448 + if (addref && Z_OBJ_HT_P(zv)->add_ref) { \
23449 + Z_OBJ_HT_P(zv)->add_ref((zv) TSRMLS_CC); \
23451 +/* return property */
23452 +#define RETVAL_PROP(n) RETVAL_PROP_EX(getThis(), n)
23453 +#define RETURN_PROP(n) RETURN_PROP_EX(getThis(), n)
23454 +#define RETVAL_PROP_EX(this, n) \
23456 + zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \
23457 + RETVAL_ZVAL(__prop, 1, 0); \
23459 +#define RETURN_PROP_EX(this, n) \
23461 + zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \
23462 + RETURN_ZVAL(__prop, 1, 0); \
23465 +/* function accepts no args */
23466 +#define NO_ARGS zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "");
23469 +#define HTTP_CRLF "\r\n"
23471 +/* default cache control */
23472 +#define HTTP_DEFAULT_CACHECONTROL "private, must-revalidate, max-age=0"
23474 +/* max URL length */
23475 +#define HTTP_URL_MAXLEN 4096
23477 +/* max request method length */
23478 +#define HTTP_REQUEST_METHOD_MAXLEN 31
23480 +/* def URL arg separator */
23481 +#define HTTP_URL_ARGSEP "&"
23483 +/* send buffer size */
23484 +#define HTTP_SENDBUF_SIZE 40960
23486 +/* CURL buffer size */
23487 +#define HTTP_CURLBUF_SIZE 16384
23489 +/* known methods */
23490 +#define HTTP_KNOWN_METHODS \
23492 + "GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, " \
23493 + /* WebDAV - RFC 2518 */ \
23494 + "PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, " \
23495 + /* WebDAV Versioning - RFC 3253 */ \
23496 + "VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, " \
23497 + "MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, " \
23498 + /* WebDAV Access Control - RFC 3744 */ \
23502 +#ifdef ZEND_ENGINE_2
23503 +# include "ext/standard/file.h"
23504 +# define HTTP_DEFAULT_STREAM_CONTEXT FG(default_context)
23506 +# define HTTP_DEFAULT_STREAM_CONTEXT NULL
23509 +#define HTTP_PHP_INI_ENTRY(entry, default, scope, updater, global) \
23510 + STD_PHP_INI_ENTRY(entry, default, scope, updater, global, zend_http_globals, http_globals)
23511 +#define HTTP_PHP_INI_ENTRY_EX(entry, default, scope, updater, displayer, global) \
23512 + STD_PHP_INI_ENTRY_EX(entry, default, scope, updater, global, zend_http_globals, http_globals, displayer)
23515 +#define HTTP_LONG_CONSTANT(name, const) REGISTER_LONG_CONSTANT(name, const, CONST_CS | CONST_PERSISTENT)
23517 +/* {{{ objects & properties */
23518 +#ifdef ZEND_ENGINE_2
23520 +# define HTTP_STATIC_ME_ALIAS(me, al, ai) ZEND_FENTRY(me, ZEND_FN(al), ai, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
23522 +# define HTTP_REGISTER_CLASS_EX(classname, name, parent, flags) \
23524 + zend_class_entry ce; \
23525 + memset(&ce, 0, sizeof(zend_class_entry)); \
23526 + INIT_CLASS_ENTRY(ce, #classname, name## _fe); \
23527 + ce.create_object = _ ##name## _new; \
23528 + name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
23529 + name## _ce->ce_flags |= flags; \
23530 + memcpy(& name## _handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
23533 +# define HTTP_REGISTER_CLASS(classname, name, parent, flags) \
23535 + zend_class_entry ce; \
23536 + memset(&ce, 0, sizeof(zend_class_entry)); \
23537 + INIT_CLASS_ENTRY(ce, #classname, name## _fe); \
23538 + ce.create_object = NULL; \
23539 + name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
23540 + name## _ce->ce_flags |= flags; \
23543 +# define HTTP_REGISTER_EXCEPTION(classname, cename, parent) \
23545 + zend_class_entry ce; \
23546 + memset(&ce, 0, sizeof(zend_class_entry)); \
23547 + INIT_CLASS_ENTRY(ce, #classname, NULL); \
23548 + ce.create_object = NULL; \
23549 + cename = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
23552 +# define getObject(t, o) getObjectEx(t, o, getThis())
23553 +# define getObjectEx(t, o, v) t * o = ((t *) zend_object_store_get_object(v TSRMLS_CC))
23554 +# 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);
23556 +# define freeObject(o) \
23557 + if (OBJ_GUARDS(o)) { \
23558 + zend_hash_destroy(OBJ_GUARDS(o)); \
23559 + FREE_HASHTABLE(OBJ_GUARDS(o)); \
23561 + if (OBJ_PROP(o)) { \
23562 + zend_hash_destroy(OBJ_PROP(o)); \
23563 + FREE_HASHTABLE(OBJ_PROP(o)); \
23567 +# define freeObject(o) \
23568 + if (OBJ_PROP(o)) { \
23569 + zend_hash_destroy(OBJ_PROP(o)); \
23570 + FREE_HASHTABLE(OBJ_PROP(o)); \
23574 +# define OBJ_PROP(o) (o)->zo.properties
23575 +# define OBJ_GUARDS(o) (o)->zo.guards
23577 +# define ACC_PROP_PRIVATE(ce, flags) ((flags & ZEND_ACC_PRIVATE) && (EG(scope) && ce == EG(scope))
23578 +# define ACC_PROP_PROTECTED(ce, flags) ((flags & ZEND_ACC_PROTECTED) && (zend_check_protected(ce, EG(scope))))
23579 +# define ACC_PROP_PUBLIC(flags) (flags & ZEND_ACC_PUBLIC)
23580 +# define ACC_PROP(ce, flags) (ACC_PROP_PUBLIC(flags) || ACC_PROP_PRIVATE(ce, flags) || ACC_PROP_PROTECTED(ce, flags))
23582 +# define SET_EH_THROW_HTTP() SET_EH_THROW_EX(http_exception_get_default())
23583 +# define SET_EH_THROW_EX(ex) php_set_error_handling(EH_THROW, ex TSRMLS_CC)
23584 +# define SET_EH_NORMAL() php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC)
23586 +#endif /* ZEND_ENGINE_2 */
23589 +#ifdef ZEND_ENGINE_2
23590 +# define with_error_handling(eh, ec) \
23592 + error_handling_t __eh = GLOBAL_ERROR_HANDLING; \
23593 + zend_class_entry *__ec= GLOBAL_EXCEPTION_CLASS; \
23594 + php_set_error_handling(eh, ec TSRMLS_CC);
23595 +# define end_error_handling() \
23596 + php_set_error_handling(__eh, __ec TSRMLS_CC); \
23599 +# define with_error_handling(eh, ec)
23600 +# define end_error_handling()
23603 +#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 5
23604 +# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default(TSRMLS_C)
23606 +# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default()
23610 +# define E_THROW 0
23612 +#ifdef ZEND_ENGINE_2
23613 +# define HE_THROW E_THROW TSRMLS_CC
23614 +# define HE_NOTICE (HTTP_G->only_exceptions ? E_THROW : E_NOTICE) TSRMLS_CC
23615 +# define HE_WARNING (HTTP_G->only_exceptions ? E_THROW : E_WARNING) TSRMLS_CC
23616 +# define HE_ERROR (HTTP_G->only_exceptions ? E_THROW : E_ERROR) TSRMLS_CC
23618 +# define HE_THROW E_WARNING TSRMLS_CC
23619 +# define HE_NOTICE E_NOTICE TSRMLS_CC
23620 +# define HE_WARNING E_WARNING TSRMLS_CC
23621 +# define HE_ERROR E_ERROR TSRMLS_CC
23624 +#define HTTP_E_RUNTIME 1L
23625 +#define HTTP_E_INVALID_PARAM 2L
23626 +#define HTTP_E_HEADER 3L
23627 +#define HTTP_E_MALFORMED_HEADERS 4L
23628 +#define HTTP_E_REQUEST_METHOD 5L
23629 +#define HTTP_E_MESSAGE_TYPE 6L
23630 +#define HTTP_E_ENCODING 7L
23631 +#define HTTP_E_REQUEST 8L
23632 +#define HTTP_E_REQUEST_POOL 9L
23633 +#define HTTP_E_SOCKET 10L
23634 +#define HTTP_E_RESPONSE 11L
23635 +#define HTTP_E_URL 12L
23636 +#define HTTP_E_QUERYSTRING 13L
23638 +#ifdef ZEND_ENGINE_2
23639 +# 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)
23640 +# 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)
23641 +# define HTTP_END_ARGS }
23642 +# define HTTP_EMPTY_ARGS_EX(class, method, ret_ref) HTTP_BEGIN_ARGS_EX(class, method, ret_ref, 0) HTTP_END_ARGS
23643 +# define HTTP_ARGS(class, method) args_for_ ##class## _ ##method
23644 +# define HTTP_ARG_VAL(name, pass_ref) ZEND_ARG_INFO(pass_ref, name)
23645 +# define HTTP_ARG_OBJ(class, name, allow_null) ZEND_ARG_OBJ_INFO(0, name, class, allow_null)
23648 +#ifdef ZEND_ENGINE_2
23649 +# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL, 0, 0}
23651 +# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL}
23654 +#ifdef HTTP_HAVE_CURL
23655 +# ifdef ZEND_ENGINE_2
23656 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23657 + HTTP_STATIC_ARG_INFO \
23658 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \
23659 + ZEND_ARG_PASS_INFO(0) \
23660 + ZEND_ARG_PASS_INFO(1) \
23661 + ZEND_END_ARG_INFO(); \
23663 + HTTP_STATIC_ARG_INFO \
23664 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \
23665 + ZEND_ARG_PASS_INFO(0) \
23666 + ZEND_ARG_PASS_INFO(0) \
23667 + ZEND_ARG_PASS_INFO(1) \
23668 + ZEND_END_ARG_INFO(); \
23670 + HTTP_STATIC_ARG_INFO \
23671 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \
23672 + ZEND_ARG_PASS_INFO(0) \
23673 + ZEND_ARG_PASS_INFO(0) \
23674 + ZEND_ARG_PASS_INFO(0) \
23675 + ZEND_ARG_PASS_INFO(1) \
23676 + ZEND_END_ARG_INFO(); \
23678 + HTTP_STATIC_ARG_INFO \
23679 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_5, 0) \
23680 + ZEND_ARG_PASS_INFO(0) \
23681 + ZEND_ARG_PASS_INFO(0) \
23682 + ZEND_ARG_PASS_INFO(0) \
23683 + ZEND_ARG_PASS_INFO(0) \
23684 + ZEND_ARG_PASS_INFO(1) \
23685 + ZEND_END_ARG_INFO();
23688 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23689 + static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \
23690 + static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
23691 + static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
23692 + static unsigned char http_arg_pass_ref_5[] = {5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
23693 +# endif /* ZEND_ENGINE_2 */
23695 +# ifdef ZEND_ENGINE_2
23696 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23697 + HTTP_STATIC_ARG_INFO \
23698 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \
23699 + ZEND_ARG_PASS_INFO(0) \
23700 + ZEND_ARG_PASS_INFO(1) \
23701 + ZEND_END_ARG_INFO(); \
23703 + HTTP_STATIC_ARG_INFO \
23704 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \
23705 + ZEND_ARG_PASS_INFO(0) \
23706 + ZEND_ARG_PASS_INFO(0) \
23707 + ZEND_ARG_PASS_INFO(1) \
23708 + ZEND_END_ARG_INFO(); \
23710 + HTTP_STATIC_ARG_INFO \
23711 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \
23712 + ZEND_ARG_PASS_INFO(0) \
23713 + ZEND_ARG_PASS_INFO(0) \
23714 + ZEND_ARG_PASS_INFO(0) \
23715 + ZEND_ARG_PASS_INFO(1) \
23716 + ZEND_END_ARG_INFO();
23718 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23719 + static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \
23720 + static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
23721 + static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
23722 +# endif /* ZEND_ENGINE_2 */
23723 +#endif /* HTTP_HAVE_CURL */
23726 +#ifndef HAVE_CURL_SHARE_STRERROR
23727 +# define curl_share_strerror(dummy) "unknown error"
23729 +#ifndef HAVE_CURL_EASY_STRERROR
23730 +# define curl_easy_strerror(dummy) "unknown error"
23732 +#ifndef HAVE_CURL_MULTI_STRERROR
23733 +# define curl_multi_strerror(dummy) "unknown error"
23736 +#define PHP_MINIT_CALL(func) PHP_MINIT(func)(INIT_FUNC_ARGS_PASSTHRU)
23737 +#define PHP_RINIT_CALL(func) PHP_RINIT(func)(INIT_FUNC_ARGS_PASSTHRU)
23738 +#define PHP_MSHUTDOWN_CALL(func) PHP_MSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU)
23739 +#define PHP_RSHUTDOWN_CALL(func) PHP_RSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU)
23741 +#define Z_OBJ_DELREF(z) \
23742 + if (Z_OBJ_HT(z)->del_ref) { \
23743 + Z_OBJ_HT(z)->del_ref(&(z) TSRMLS_CC); \
23745 +#define Z_OBJ_ADDREF(z) \
23746 + if (Z_OBJ_HT(z)->add_ref) { \
23747 + Z_OBJ_HT(z)->add_ref(&(z) TSRMLS_CC); \
23749 +#define Z_OBJ_DELREF_P(z) \
23750 + if (Z_OBJ_HT_P(z)->del_ref) { \
23751 + Z_OBJ_HT_P(z)->del_ref((z) TSRMLS_CC); \
23753 +#define Z_OBJ_ADDREF_P(z) \
23754 + if (Z_OBJ_HT_P(z)->add_ref) { \
23755 + Z_OBJ_HT_P(z)->add_ref((z) TSRMLS_CC); \
23757 +#define Z_OBJ_DELREF_PP(z) \
23758 + if (Z_OBJ_HT_PP(z)->del_ref) { \
23759 + Z_OBJ_HT_PP(z)->del_ref(*(z) TSRMLS_CC); \
23761 +#define Z_OBJ_ADDREF_PP(z) \
23762 + if (Z_OBJ_HT_PP(z)->add_ref) { \
23763 + Z_OBJ_HT_PP(z)->add_ref(*(z) TSRMLS_CC); \
23766 +#endif /* PHP_HTTP_STD_DEFS_H */
23769 + * Local variables:
23771 + * c-basic-offset: 4
23773 + * vim600: noet sw=4 ts=4 fdm=marker
23774 + * vim<600: noet sw=4 ts=4
23778 +++ b/ext/http/php_http_url_api.h
23781 + +--------------------------------------------------------------------+
23783 + +--------------------------------------------------------------------+
23784 + | Redistribution and use in source and binary forms, with or without |
23785 + | modification, are permitted provided that the conditions mentioned |
23786 + | in the accompanying LICENSE file are met. |
23787 + +--------------------------------------------------------------------+
23788 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23789 + +--------------------------------------------------------------------+
23792 +/* $Id: php_http_url_api.h 292841 2009-12-31 08:48:57Z mike $ */
23794 +#ifndef PHP_HTTP_URL_API_H
23795 +#define PHP_HTTP_URL_API_H
23797 +#include "ext/standard/url.h"
23799 +extern PHP_MINIT_FUNCTION(http_url);
23801 +#define http_absolute_url(u) _http_absolute_url_ex((u), HTTP_URL_REPLACE TSRMLS_CC)
23802 +#define http_absolute_url_ex(u, f) _http_absolute_url_ex((u), (f) TSRMLS_CC)
23803 +PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC);
23805 +#define HTTP_URL_REPLACE 0x000
23806 +#define HTTP_URL_JOIN_PATH 0x001
23807 +#define HTTP_URL_JOIN_QUERY 0x002
23808 +#define HTTP_URL_STRIP_USER 0x004
23809 +#define HTTP_URL_STRIP_PASS 0x008
23810 +#define HTTP_URL_STRIP_AUTH (HTTP_URL_STRIP_USER|HTTP_URL_STRIP_PASS)
23811 +#define HTTP_URL_STRIP_PORT 0x020
23812 +#define HTTP_URL_STRIP_PATH 0x040
23813 +#define HTTP_URL_STRIP_QUERY 0x080
23814 +#define HTTP_URL_STRIP_FRAGMENT 0x100
23815 +#define HTTP_URL_STRIP_ALL ( \
23816 + HTTP_URL_STRIP_AUTH | \
23817 + HTTP_URL_STRIP_PORT | \
23818 + HTTP_URL_STRIP_PATH | \
23819 + HTTP_URL_STRIP_QUERY | \
23820 + HTTP_URL_STRIP_FRAGMENT \
23822 +#define HTTP_URL_FROM_ENV 0x1000
23824 +#define http_build_url(f, o, n, p, s, l) _http_build_url((f), (o), (n), (p), (s), (l) TSRMLS_CC)
23825 +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);
23827 +#define http_urlencode_hash(h, q) _http_urlencode_hash_ex((h), 1, NULL, 0, (q), NULL TSRMLS_CC)
23828 +#define http_urlencode_hash_ex(h, o, p, pl, q, ql) _http_urlencode_hash_ex((h), (o), (p), (pl), (q), (ql) TSRMLS_CC)
23829 +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);
23831 +#define http_urlencode_hash_recursive(ht, s, as, al, pr, pl) _http_urlencode_hash_recursive((ht), (s), (as), (al), (pr), (pl) TSRMLS_CC)
23832 +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);
23834 +#define http_url_from_struct(u, ht) _http_url_from_struct((u), (ht) TSRMLS_CC)
23835 +static inline php_url *_http_url_from_struct(php_url *url, HashTable *ht TSRMLS_DC)
23840 + url = ecalloc(1, sizeof(php_url));
23843 + if ((SUCCESS == zend_hash_find(ht, "scheme", sizeof("scheme"), (void *) &e))
23844 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23845 + url->scheme = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23847 + if ((SUCCESS == zend_hash_find(ht, "user", sizeof("user"), (void *) &e))
23848 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23849 + url->user = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23851 + if ((SUCCESS == zend_hash_find(ht, "pass", sizeof("pass"), (void *) &e))
23852 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23853 + url->pass = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23855 + if ((SUCCESS == zend_hash_find(ht, "host", sizeof("host"), (void *) &e))
23856 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23857 + url->host = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23859 + if ((SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &e))
23860 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23861 + url->path = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23863 + if ((SUCCESS == zend_hash_find(ht, "query", sizeof("query"), (void *) &e))
23864 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23865 + url->query = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23867 + if ((SUCCESS == zend_hash_find(ht, "fragment", sizeof("fragment"), (void *) &e))
23868 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23869 + url->fragment = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23871 + if (SUCCESS == zend_hash_find(ht, "port", sizeof("port"), (void *) &e)) {
23872 + if (Z_TYPE_PP(e) == IS_LONG) {
23873 + url->port = (unsigned short) Z_LVAL_PP(e);
23875 + zval *o = http_zsep(IS_LONG, *e);
23877 + url->port = (unsigned short) Z_LVAL_P(o);
23878 + zval_ptr_dtor(&o);
23885 +#define http_url_tostruct(u, strct) _http_url_tostruct((u), (strct) TSRMLS_CC)
23886 +static inline HashTable *_http_url_tostruct(php_url *url, zval *strct TSRMLS_DC)
23891 + switch (Z_TYPE_P(strct)) {
23893 + zval_dtor(strct);
23894 + array_init(strct);
23897 + INIT_ZARR(arr, HASH_OF(strct));
23900 + INIT_PZVAL(&arr);
23901 + array_init(&arr);
23905 + if (url->scheme) {
23906 + add_assoc_string(&arr, "scheme", url->scheme, 1);
23909 + add_assoc_string(&arr, "user", url->user, 1);
23912 + add_assoc_string(&arr, "pass", url->pass, 1);
23915 + add_assoc_string(&arr, "host", url->host, 1);
23918 + add_assoc_long(&arr, "port", (long) url->port);
23921 + add_assoc_string(&arr, "path", url->path, 1);
23923 + if (url->query) {
23924 + add_assoc_string(&arr, "query", url->query, 1);
23926 + if (url->fragment) {
23927 + add_assoc_string(&arr, "fragment", url->fragment, 1);
23931 + return Z_ARRVAL(arr);
23937 + * Local variables:
23939 + * c-basic-offset: 4
23941 + * vim600: noet sw=4 ts=4 fdm=marker
23942 + * vim<600: noet sw=4 ts=4
23946 +++ b/ext/http/php_http_util_object.h
23949 + +--------------------------------------------------------------------+
23951 + +--------------------------------------------------------------------+
23952 + | Redistribution and use in source and binary forms, with or without |
23953 + | modification, are permitted provided that the conditions mentioned |
23954 + | in the accompanying LICENSE file are met. |
23955 + +--------------------------------------------------------------------+
23956 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23957 + +--------------------------------------------------------------------+
23960 +/* $Id: php_http_util_object.h 292841 2009-12-31 08:48:57Z mike $ */
23962 +#ifndef PHP_HTTP_UTIL_OBJECT_H
23963 +#define PHP_HTTP_UTIL_OBJECT_H
23964 +#ifdef ZEND_ENGINE_2
23966 +extern zend_class_entry *http_util_object_ce;
23967 +extern zend_function_entry http_util_object_fe[];
23969 +extern PHP_MINIT_FUNCTION(http_util_object);
23975 + * Local variables:
23977 + * c-basic-offset: 4
23979 + * vim600: noet sw=4 ts=4 fdm=marker
23980 + * vim<600: noet sw=4 ts=4
23984 +++ b/ext/http/phpstr/phpstr.c
23987 +/* $Id: phpstr.c 211942 2006-04-24 17:17:09Z mike $ */
23990 +#include "phpstr.h"
23992 +PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags)
23995 + buf = pemalloc(sizeof(phpstr), flags & PHPSTR_INIT_PERSISTENT);
23999 + buf->size = (chunk_size) ? chunk_size : PHPSTR_DEFAULT_SIZE;
24000 + buf->pmem = (flags & PHPSTR_INIT_PERSISTENT) ? 1 : 0;
24001 + buf->data = (flags & PHPSTR_INIT_PREALLOC) ? pemalloc(buf->size, buf->pmem) : NULL;
24002 + buf->free = (flags & PHPSTR_INIT_PREALLOC) ? buf->size : 0;
24009 +PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length)
24011 + if ((buf = phpstr_init(buf))) {
24012 + if (PHPSTR_NOMEM == phpstr_append(buf, string, length)) {
24013 + pefree(buf, buf->pmem);
24020 +PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error)
24022 + char *ptr = NULL;
24024 + fprintf(stderr, "RESIZE: size=%lu, used=%lu, free=%lu\n", buf->size, buf->used, buf->free);
24026 + if (buf->free < len) {
24027 + size_t size = override_size ? override_size : buf->size;
24029 + while ((size + buf->free) < len) {
24033 + if (allow_error) {
24034 + ptr = perealloc_recoverable(buf->data, buf->used + buf->free + size, buf->pmem);
24036 + ptr = perealloc(buf->data, buf->used + buf->free + size, buf->pmem);
24042 + return PHPSTR_NOMEM;
24045 + buf->free += size;
24051 +PHPSTR_API size_t phpstr_shrink(phpstr *buf)
24053 + /* avoid another realloc on fixation */
24054 + if (buf->free > 1) {
24055 + char *ptr = perealloc(buf->data, buf->used + 1, buf->pmem);
24060 + return PHPSTR_NOMEM;
24064 + return buf->used;
24067 +PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len)
24069 + if (PHPSTR_NOMEM == phpstr_resize(buf, append_len)) {
24070 + return PHPSTR_NOMEM;
24072 + memcpy(buf->data + buf->used, append, append_len);
24073 + buf->used += append_len;
24074 + buf->free -= append_len;
24075 + return append_len;
24078 +PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...)
24082 + size_t append_len, alloc;
24084 + va_start(argv, format);
24085 + append_len = vspprintf(&append, 0, format, argv);
24088 + alloc = phpstr_append(buf, append, append_len);
24091 + if (PHPSTR_NOMEM == alloc) {
24092 + return PHPSTR_NOMEM;
24094 + return append_len;
24097 +PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset)
24099 + if (PHPSTR_NOMEM == phpstr_resize(buf, insert_len)) {
24100 + return PHPSTR_NOMEM;
24102 + memmove(buf->data + offset + insert_len, buf->data + offset, insert_len);
24103 + memcpy(buf->data + offset, insert, insert_len);
24104 + buf->used += insert_len;
24105 + buf->free -= insert_len;
24106 + return insert_len;
24109 +PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...)
24113 + size_t insert_len, alloc;
24115 + va_start(argv, format);
24116 + insert_len = vspprintf(&insert, 0, format, argv);
24119 + alloc = phpstr_insert(buf, insert, insert_len, offset);
24122 + if (PHPSTR_NOMEM == alloc) {
24123 + return PHPSTR_NOMEM;
24125 + return insert_len;
24128 +PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len)
24130 + if (PHPSTR_NOMEM == phpstr_resize(buf, prepend_len)) {
24131 + return PHPSTR_NOMEM;
24133 + memmove(buf->data + prepend_len, buf->data, buf->used);
24134 + memcpy(buf->data, prepend, prepend_len);
24135 + buf->used += prepend_len;
24136 + buf->free -= prepend_len;
24137 + return prepend_len;
24140 +PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...)
24144 + size_t prepend_len, alloc;
24146 + va_start(argv, format);
24147 + prepend_len = vspprintf(&prepend, 0, format, argv);
24150 + alloc = phpstr_prepend(buf, prepend, prepend_len);
24153 + if (PHPSTR_NOMEM == alloc) {
24154 + return PHPSTR_NOMEM;
24156 + return prepend_len;
24159 +PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len)
24161 + char *copy = ecalloc(1, buf->used + 1);
24162 + memcpy(copy, buf->data, buf->used);
24167 + *len = buf->used;
24172 +PHPSTR_API phpstr *phpstr_dup(const phpstr *buf)
24174 + phpstr *dup = phpstr_clone(buf);
24175 + if (PHPSTR_NOMEM == phpstr_append(dup, buf->data, buf->used)) {
24176 + phpstr_free(&dup);
24181 +PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length)
24183 + if (offset >= buf->used) {
24186 + if (offset + length > buf->used) {
24187 + length = buf->used - offset;
24189 + memmove(buf->data + offset, buf->data + offset + length, buf->used - length);
24190 + buf->used -= length;
24191 + buf->free += length;
24195 +PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t length)
24197 + if (offset >= buf->used) {
24200 + size_t need = 1 + ((length + offset) > buf->used ? (buf->used - offset) : (length - offset));
24201 + phpstr *sub = phpstr_init_ex(NULL, need, PHPSTR_INIT_PREALLOC | (buf->pmem ? PHPSTR_INIT_PERSISTENT:0));
24203 + if (PHPSTR_NOMEM == phpstr_append(sub, buf->data + offset, need)) {
24204 + phpstr_free(&sub);
24206 + sub->size = buf->size;
24213 +PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length)
24215 + if (length < buf->used) {
24216 + return phpstr_sub(buf, buf->used - length, length);
24218 + return phpstr_sub(buf, 0, buf->used);
24223 +PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv)
24226 + buf = phpstr_init(buf);
24229 + while (argc > i++) {
24230 + phpstr_free_t f = va_arg(argv, phpstr_free_t);
24231 + phpstr *current = va_arg(argv, phpstr *);
24232 + phpstr_append(buf, current->data, current->used);
24233 + FREE_PHPSTR(f, current);
24240 +PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...)
24245 + va_start(argv, argc);
24246 + ret = phpstr_merge_va(buf, argc, argv);
24251 +PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...)
24256 + va_start(argv, argc);
24257 + ret = phpstr_merge_va(NULL, argc, argv);
24262 +PHPSTR_API phpstr *phpstr_fix(phpstr *buf)
24264 + if (PHPSTR_NOMEM == phpstr_resize_ex(buf, 1, 1, 0)) {
24267 + buf->data[buf->used] = '\0';
24271 +PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right)
24273 + if (left->used > right->used) {
24275 + } else if (right->used > left->used) {
24278 + return memcmp(left->data, right->data, left->used);
24282 +PHPSTR_API void phpstr_reset(phpstr *buf)
24284 + buf->free += buf->used;
24288 +PHPSTR_API void phpstr_dtor(phpstr *buf)
24291 + pefree(buf->data, buf->pmem);
24292 + buf->data = NULL;
24298 +PHPSTR_API void phpstr_free(phpstr **buf)
24301 + phpstr_dtor(*buf);
24302 + pefree(*buf, (*buf)->pmem);
24307 +PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size)
24314 + *s = phpstr_init_ex(NULL, chunk_size << 1, chunk_size ? PHPSTR_INIT_PREALLOC : 0);
24319 + phpstr_append(storage, data, data_len);
24322 + if (!chunk_size) {
24323 + phpstr_data(storage, chunk, &chunk_size);
24325 + return chunk_size;
24328 + if (storage->used >= (chunk_size = storage->size >> 1)) {
24329 + *chunk = estrndup(storage->data, chunk_size);
24330 + phpstr_cut(storage, 0, chunk_size);
24331 + return chunk_size;
24337 +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)
24339 + char *chunk = NULL;
24342 + while ((got = phpstr_chunk_buffer(s, data, data_len, &chunk, chunk_len))) {
24343 + passthru(opaque, chunk, got TSRMLS_CC);
24344 + if (!chunk_len) {
24345 + /* we already got the last chunk,
24346 + and freed all resources */
24351 + STR_SET(chunk, NULL);
24357 + * Local variables:
24359 + * c-basic-offset: 4
24361 + * vim600: sw=4 ts=4 fdm=marker
24362 + * vim<600: sw=4 ts=4
24366 +++ b/ext/http/phpstr/phpstr.h
24369 +/* $Id: phpstr.h 229282 2007-02-07 15:31:50Z mike $ */
24371 +#ifndef _PHPSTR_H_
24372 +#define _PHPSTR_H_
24374 +#ifndef PHPSTR_DEFAULT_SIZE
24375 +# define PHPSTR_DEFAULT_SIZE 256
24378 +#define PHPSTR_NOMEM ((size_t) -1)
24381 +# define STR_FREE(STR) \
24389 +# define STR_SET(STR, SET) \
24397 +# define TSRMLS_DC
24398 +# define TSRMLS_CC
24401 +#ifdef PHP_ATTRIBUTE_FORMAT
24402 +# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b) PHP_ATTRIBUTE_FORMAT(f, a, b)
24404 +# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b)
24407 +# define pemalloc(s,p) malloc(s)
24408 +# define pefree(x,p) free(x)
24409 +# define perealloc(x,s,p) realloc(x,s)
24410 +# define perealloc_recoverable perealloc
24411 +# define ecalloc calloc
24412 +static inline void *estrndup(void *p, size_t s)
24414 + char *r = (char *) malloc(s+1);
24415 + if (r) memcpy((void *) r, p, s), r[s] = '\0';
24416 + return (void *) r;
24420 +#if defined(PHP_WIN32)
24421 +# if defined(PHPSTR_EXPORTS)
24422 +# define PHPSTR_API __declspec(dllexport)
24423 +# elif defined(COMPILE_DL_PHPSTR)
24424 +# define PHPSTR_API __declspec(dllimport)
24426 +# define PHPSTR_API
24429 +# define PHPSTR_API
24432 +#define PHPSTR(p) ((phpstr *) (p))
24433 +#define PHPSTR_VAL(p) (PHPSTR(p))->data
24434 +#define PHPSTR_LEN(p) (PHPSTR(p))->used
24436 +#define FREE_PHPSTR_PTR(STR) pefree(STR, STR->pmem)
24437 +#define FREE_PHPSTR_VAL(STR) phpstr_dtor(STR)
24438 +#define FREE_PHPSTR_ALL(STR) phpstr_free(&(STR))
24439 +#define FREE_PHPSTR(free, STR) \
24442 + case PHPSTR_FREE_NOT: break; \
24443 + case PHPSTR_FREE_PTR: pefree(STR, STR->pmem); break; \
24444 + case PHPSTR_FREE_VAL: phpstr_dtor(STR); break; \
24445 + case PHPSTR_FREE_ALL: \
24447 + phpstr *PTR = (STR); \
24448 + phpstr_free(&PTR); \
24451 + default: break; \
24454 +#define RETURN_PHPSTR_PTR(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_PTR, 0)
24455 +#define RETURN_PHPSTR_VAL(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 0)
24456 +#define RETURN_PHPSTR_DUP(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
24457 +#define RETVAL_PHPSTR_PTR(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_PTR, 0)
24458 +#define RETVAL_PHPSTR_VAL(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 0)
24459 +#define RETVAL_PHPSTR_DUP(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
24460 +/* RETURN_PHPSTR(buf, PHPSTR_FREE_PTR, 0) */
24461 +#define RETURN_PHPSTR(STR, free, dup) \
24462 + RETVAL_PHPSTR((STR), (free), (dup)); \
24465 +#define RETVAL_PHPSTR(STR, free, dup) \
24466 + phpstr_fix(STR); \
24467 + RETVAL_STRINGL((STR)->data, (STR)->used, (dup)); \
24468 + FREE_PHPSTR((free), (STR));
24470 +typedef struct _phpstr_t {
24476 + unsigned reserved:31;
24479 +typedef enum _phpstr_free_t {
24480 + PHPSTR_FREE_NOT = 0,
24481 + PHPSTR_FREE_PTR, /* pefree() */
24482 + PHPSTR_FREE_VAL, /* phpstr_dtor() */
24483 + PHPSTR_FREE_ALL /* phpstr_free() */
24486 +#define PHPSTR_ALL_FREE(STR) PHPSTR_FREE_ALL,(STR)
24487 +#define PHPSTR_PTR_FREE(STR) PHPSTR_FREE_PTR,(STR)
24488 +#define PHPSTR_VAL_FREE(STR) PHPSTR_FREE_VAL,(STR)
24489 +#define PHPSTR_NOT_FREE(STR) PHPSTR_FREE_NOT,(STR)
24491 +#define PHPSTR_INIT_PREALLOC 0x01
24492 +#define PHPSTR_INIT_PERSISTENT 0x02
24494 +/* create a new phpstr */
24495 +#define phpstr_new() phpstr_init(NULL)
24496 +#define phpstr_init(b) phpstr_init_ex(b, PHPSTR_DEFAULT_SIZE, 0)
24497 +#define phpstr_clone(phpstr_pointer) phpstr_init_ex(NULL, (phpstr_pointer)->size, (phpstr_pointer)->pmem ? PHPSTR_INIT_PERSISTENT:0)
24498 +PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags);
24500 +/* create a phpstr from a zval or c-string */
24501 +#define phpstr_from_zval(z) phpstr_from_string(Z_STRVAL(z), Z_STRLEN(z))
24502 +#define phpstr_from_zval_ex(b, z) phpstr_from_string_ex(b, Z_STRVAL(z), Z_STRLEN(z))
24503 +#define phpstr_from_string(s, l) phpstr_from_string_ex(NULL, (s), (l))
24504 +PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length);
24506 +/* usually only called from within the internal functions */
24507 +#define phpstr_resize(b, s) phpstr_resize_ex((b), (s), 0, 0)
24508 +PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error);
24510 +/* shrink memory chunk to actually used size (+1) */
24511 +PHPSTR_API size_t phpstr_shrink(phpstr *buf);
24513 +/* append data to the phpstr */
24514 +#define phpstr_appends(b, a) phpstr_append((b), (a), sizeof(a)-1)
24515 +#define phpstr_appendl(b, a) phpstr_append((b), (a), strlen(a))
24516 +PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len);
24517 +PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3);
24519 +/* insert data at a specific position of the phpstr */
24520 +#define phpstr_inserts(b, i, o) phpstr_insert((b), (i), sizeof(i)-1, (o))
24521 +#define phpstr_insertl(b, i, o) phpstr_insert((b), (i), strlen(i), (o))
24522 +PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset);
24523 +PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 3, 4);
24525 +/* prepend data */
24526 +#define phpstr_prepends(b, p) phpstr_prepend((b), (p), sizeof(p)-1)
24527 +#define phpstr_prependl(b, p) phpstr_prepend((b), (p), strlen(p))
24528 +PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len);
24529 +PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3);
24531 +/* get a zero-terminated string */
24532 +PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len);
24534 +/* get a part of the phpstr */
24535 +#define phpstr_mid(b, o, l) phpstr_sub((b), (o), (l))
24536 +#define phpstr_left(b, l) phpstr_sub((b), 0, (l))
24537 +PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length);
24538 +PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t len);
24540 +/* remove a substring */
24541 +PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length);
24543 +/* get a complete phpstr duplicate */
24544 +PHPSTR_API phpstr *phpstr_dup(const phpstr *buf);
24546 +/* merge several phpstr objects
24549 + phpstr *final = phpstr_merge(3,
24550 + PHPSTR_NOT_FREE(&keep),
24551 + PHPSTR_ALL_FREE(middle_ptr),
24552 + PHPSTR_VAL_FREE(&local);
24554 +PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...);
24555 +PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...);
24556 +PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv);
24558 +/* sets a trailing NUL byte */
24559 +PHPSTR_API phpstr *phpstr_fix(phpstr *buf);
24561 +/* memcmp for phpstr objects */
24562 +PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right);
24564 +/* reset phpstr object */
24565 +PHPSTR_API void phpstr_reset(phpstr *buf);
24567 +/* free a phpstr objects contents */
24568 +PHPSTR_API void phpstr_dtor(phpstr *buf);
24570 +/* free a phpstr object completely */
24571 +PHPSTR_API void phpstr_free(phpstr **buf);
24573 +/* stores data in a phpstr until it reaches chunk_size */
24574 +PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size);
24576 +typedef void (*phpstr_passthru_func)(void *opaque, const char *, size_t TSRMLS_DC);
24578 +/* wrapper around phpstr_chunk_buffer, which passes available chunks to passthru() */
24579 +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);
24585 + * Local variables:
24587 + * c-basic-offset: 4
24589 + * vim600: sw=4 ts=4 fdm=marker
24590 + * vim<600: sw=4 ts=4
24593 +++ b/ext/http/tests/HttpMessage_001.phpt
24599 +include 'skip.inc';
24600 +checkmin("5.2.5");
24605 +$m = new HttpMessage(
24606 + "HTTP/1.1 301\r\n".
24607 + "Location: /anywhere\r\n".
24608 + "HTTP/1.1 302\r\n".
24609 + "Location: /somewhere\r\n".
24610 + "HTTP/1.1 206 Partial content\r\n".
24611 + "Content-Range: bytes=2-3\r\n".
24612 + "Transfer-Encoding: chunked\r\n".
24619 +var_dump($m->getResponseStatus());
24621 +$x = $m->getParentMessage();
24622 +$x = $m->getParentMessage();
24623 +$x = $m->getParentMessage();
24625 +var_dump($m->getBody());
24626 +var_dump(HttpMessage::fromString($m->toString(true))->toString(true));
24629 + var_dump($m->toString());
24630 + } while ($m = $m->getParentMessage());
24631 +} catch (HttpException $ex) {
24638 +string(15) "Partial content"
24640 +string(190) "HTTP/1.1 301
24641 +Location: /anywhere
24643 +Location: /somewhere
24644 +HTTP/1.1 206 Partial content
24645 +Content-Range: bytes=2-3
24646 +X-Original-Transfer-Encoding: chunked
24651 +string(119) "HTTP/1.1 206 Partial content
24652 +Content-Range: bytes=2-3
24653 +X-Original-Transfer-Encoding: chunked
24658 +string(36) "HTTP/1.1 302
24659 +Location: /somewhere
24661 +string(35) "HTTP/1.1 301
24662 +Location: /anywhere
24666 +++ b/ext/http/tests/HttpMessage_002.phpt
24669 +HttpMessage properties
24672 +include 'skip.inc';
24673 +checkmin("5.2.5");
24674 +checkcls('HttpMessage');
24678 +class Message extends HttpMessage
24680 + var $var_property = 'var';
24681 + public $public_property = 'public';
24682 + protected $protected_property = 'protected';
24683 + private $private_property = 'private';
24685 + public function test()
24687 + var_dump($this->var_property);
24688 + var_dump($this->public_property);
24689 + var_dump($this->protected_property);
24690 + var_dump($this->private_property);
24691 + var_dump($this->non_ex_property);
24692 + $this->var_property.='_property';
24693 + $this->public_property.='_property';
24694 + $this->protected_property.='_property';
24695 + $this->private_property.='_property';
24696 + $this->non_ex_property = 'non_ex';
24697 + var_dump($this->var_property);
24698 + var_dump($this->public_property);
24699 + var_dump($this->protected_property);
24700 + var_dump($this->private_property);
24701 + var_dump($this->non_ex_property);
24703 + print_r($this->headers);
24704 + $this->headers['Foo'] = 'Bar';
24708 +error_reporting(E_ALL|E_STRICT);
24718 +string(6) "public"
24719 +string(9) "protected"
24720 +string(7) "private"
24722 +Notice: Undefined property: Message::$non_ex_property in %s
24724 +string(12) "var_property"
24725 +string(15) "public_property"
24726 +string(18) "protected_property"
24727 +string(16) "private_property"
24728 +string(6) "non_ex"
24732 +%aFatal error%sCannot access HttpMessage properties by reference or array key/index in%s
24734 +++ b/ext/http/tests/HttpMessage_003.phpt
24737 +HttpMessage implements Serializable, Countable
24740 +include 'skip.inc';
24741 +checkmin("5.2.5");
24747 +$m = new HttpMessage(
24748 + "HTTP/1.1 301\r\n".
24749 + "Location: /anywhere\r\n".
24750 + "HTTP/1.1 302\r\n".
24751 + "Location: /somewhere\r\n".
24752 + "HTTP/1.1 200\r\n".
24753 + "Transfer-Encoding: chunked\r\n".
24760 +var_dump($m->count());
24761 +var_dump($m->serialize());
24762 +$m->unserialize("HTTP/1.1 200 Ok\r\nServer: Funky/1.0");
24764 +var_dump($m->count());
24771 +string(148) "HTTP/1.1 301
24772 +Location: /anywhere
24774 +Location: /somewhere
24776 +X-Original-Transfer-Encoding: chunked
24781 +object(HttpMessage)#%d (%d) {
24786 + ["requestMethod%s]=>
24788 + ["requestUrl%s]=>
24790 + ["responseStatus%s]=>
24792 + ["responseCode%s]=>
24794 + ["httpVersion%s]=>
24799 + string(9) "Funky/1.0"
24801 + ["parentMessage%s]=>
24807 +++ b/ext/http/tests/HttpMessage_004.phpt
24810 +HttpMessage::detach()
24813 +include 'skip.inc';
24820 +$m = new HttpMessage("
24827 +Content-Type: text/plain
24833 +$d = $m->detach();
24834 +$d->addHeaders(array('Server'=>'Funky/2.0'));
24835 +var_dump($d->getHeaders() == $m->getHeaders());
24836 +var_dump($d->getBody());
24845 \ No newline at end of file
24847 +++ b/ext/http/tests/HttpMessage_005.phpt
24850 +HttpMessage::prepend()
24853 +include 'skip.inc';
24860 +$m1 = new HttpMessage("
24867 +Content-Type: text/plain
24873 +$m2 = new HttpMessage("
24874 +GET http://example.com/ HTTP/1.0
24877 +Content-Type: text/html
24883 +$m1->prepend($m2);
24885 +echo $m1->toString(true);
24887 +$m1->prepend($m1->detach(), false);
24888 +echo $m1->toString(true);
24894 +GET http://example.com/ HTTP/1.0
24897 +Content-Type: text/html
24907 +Content-Type: text/plain
24911 +GET http://example.com/ HTTP/1.0
24914 +Content-Type: text/html
24924 +Content-Type: text/plain
24930 +Content-Type: text/plain
24935 \ No newline at end of file
24937 +++ b/ext/http/tests/HttpMessage_006.phpt
24940 +HttpMessage iterator
24943 +include 'skip.inc';
24950 +$m = new HttpMessage("
24954 +HTTP/1.1 304 Not Modified
24957 +foreach ($m as $msg) {
24958 + echo "==\n", $msg;
24966 +HTTP/1.1 304 Not Modified
24974 \ No newline at end of file
24976 +++ b/ext/http/tests/HttpMessage_007.phpt
24979 +HttpMessage::reverse()
24982 +include 'skip.inc';
24988 +$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";
24989 +echo HttpMessage::fromString($s)->toString(true);
24991 +echo HttpMessage::fromString($s)->reverse()->toString(true);
24993 +$m = new HttpMessage($s);
24994 +$r = $m->reverse();
24996 +var_dump($r->count());
24997 +echo $r->toString(true);
25003 +GET /first HTTP/1.1
25004 +HTTP/1.1 200 Ok-first
25005 +GET /second HTTP/1.1
25006 +HTTP/1.1 200 Ok-second
25007 +GET /third HTTP/1.1
25008 +HTTP/1.1 200 Ok-third
25010 +HTTP/1.1 200 Ok-third
25011 +GET /third HTTP/1.1
25012 +HTTP/1.1 200 Ok-second
25013 +GET /second HTTP/1.1
25014 +HTTP/1.1 200 Ok-first
25015 +GET /first HTTP/1.1
25017 +HTTP/1.1 200 Ok-third
25018 +GET /third HTTP/1.1
25019 +HTTP/1.1 200 Ok-second
25020 +GET /second HTTP/1.1
25021 +HTTP/1.1 200 Ok-first
25022 +GET /first HTTP/1.1
25025 +++ b/ext/http/tests/HttpMessage_008.phpt
25028 +HttpMessage::toMessageTypeObject()
25031 +include 'skip.inc';
25033 +checkcls('HttpRequest');
25039 +$b = HttpRequest::encodeBody(array("a"=>"b",1=>2),null);
25041 +$m = new HttpMessage;
25042 +$m->setType(HttpMessage::TYPE_REQUEST);
25043 +$m->setRequestMethod('POST');
25044 +$m->setRequestUrl("http://www.example.com");
25045 +$m->setHttpVersion('1.1');
25048 + "Content-Type" => "application/x-www-form-urlencoded",
25049 + "Host" => "www.example.com",
25050 + "Content-Length"=> strlen($b),
25054 +$r = $m->toMessageTypeObject();
25060 +POST http://www.example.com HTTP/1.1
25061 +Content-Type: application/x-www-form-urlencoded
25062 +Host: www.example.com
25069 +++ b/ext/http/tests/HttpMessage_009_bug16700.phpt
25072 +Bug #16700 - child classes of HttpMessage cannot not have array properties
25075 +include 'skip.inc';
25082 +class ChildMessage extends HttpMessage {
25083 + public $properties = array();
25086 +$child = new ChildMessage;
25087 +$child->properties['foo'] = 'bar';
25088 +echo $child->properties['foo'], "\n";
25096 +++ b/ext/http/tests/HttpQueryString_001.phpt
25099 +HttpQueryString global
25102 +include 'skip.inc';
25103 +checkmin("5.2.5");
25109 +$_GET = array('a'=>'b','c'=>'3.4','r'=>array(1,2,3));
25110 +$_SERVER['QUERY_STRING'] = 'a=b&c=3.4&r[0]=1&r[1]=2&r[2]=3';
25112 +var_dump(HttpQueryString::singleton()->get());
25113 +var_dump(HttpQueryString::singleton()->get('n'));
25114 +var_dump(HttpQueryString::singleton()->get('a'));
25115 +var_dump(HttpQueryString::singleton()->get('a', "i", 0, true));
25116 +var_dump(HttpQueryString::singleton()->get('a', "string", 'hi!'));
25117 +var_dump(HttpQueryString::singleton()->get('c'));
25118 +var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_INT));
25119 +var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_FLOAT));
25120 +var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_BOOL));
25121 +var_dump(HttpQueryString::singleton()->get('r'));
25122 +var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_ARRAY));
25123 +var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_OBJECT));
25125 +HttpQueryString::singleton()->set(new HttpQueryString(false, 'z[0]=2'));
25127 +HttpQueryString::singleton()->set(array('a'=>'b', 'c'=> "3.4"));
25128 +HttpQueryString::singleton()->set(array('a' => NULL));
25130 +var_dump(HttpQueryString::singleton());
25132 +var_dump($_SERVER['QUERY_STRING']);
25138 +string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3"
25163 +object(stdClass)#%d (%d) {
25171 +object(HttpQueryString)#1 (2) {
25172 + ["queryArray%s]=>
25191 + ["queryString%s]=>
25192 + &string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
25212 +string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
25214 \ No newline at end of file
25216 +++ b/ext/http/tests/HttpQueryString_002.phpt
25219 +HttpQueryString local
25222 +include 'skip.inc';
25223 +checkmin("5.2.5");
25229 +$q = new HttpQueryString(false, $array = array('a'=>'b','c'=>'3.4','r'=>array(1,2,3)));
25230 +var_dump($q->get());
25231 +var_dump($q->get('n'));
25232 +var_dump($q->get('a'));
25233 +var_dump($q->get('a', "i", 0, true));
25234 +var_dump($q->get('a', "string", 'hi!'));
25235 +var_dump($q->get('c'));
25236 +var_dump($q->get('c', HttpQueryString::TYPE_INT));
25237 +var_dump($q->get('c', HttpQueryString::TYPE_FLOAT));
25238 +var_dump($q->get('c', HttpQueryString::TYPE_BOOL));
25239 +var_dump($q->get('r'));
25240 +var_dump($q->get('r', HttpQueryString::TYPE_ARRAY));
25241 +var_dump($q->get('r', HttpQueryString::TYPE_OBJECT));
25243 +$q->set('z[0]=2');
25244 +$q->set(array('a'=>'b', 'c'=> "3.4"));
25245 +$q->set(array('a' => NULL));
25254 +string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3"
25279 +object(stdClass)#%d (%d) {
25287 +object(HttpQueryString)#1 (2) {
25288 + ["queryArray%s]=>
25307 + ["queryString%s]=>
25308 + string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
25326 \ No newline at end of file
25328 +++ b/ext/http/tests/HttpQueryString_003.phpt
25331 +HttpQueryString xlate
25334 +include 'skip.inc';
25335 +checkmin("5.2.5");
25336 +checkext('iconv');
25341 +$qs = new HttpQueryString(false, "ä[0]=ü&ö[a]=ß");
25342 +var_dump($qs->get());
25343 +$qs->xlate("latin1", "utf8");
25344 +var_dump($qs->get());
25345 +$qs->xlate("utf8", "latin1");
25346 +var_dump($qs->get());
25350 +string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF"
25351 +string(41) "%C3%A4%5B0%5D=%C3%BC&%C3%B6%5Ba%5D=%C3%9F"
25352 +string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF"
25355 +++ b/ext/http/tests/HttpQueryString_004.phpt
25358 +HttpQueryString w/ objects
25361 +include 'skip.inc';
25362 +checkmin("5.2.5");
25367 +class test_props {
25370 + protected $dont_show;
25371 + private $dont_show2;
25372 + function __construct() {
25373 + $this->bar = (object) array("baz"=>1);
25374 + $this->dont_show = 'xxx';
25375 + $this->dont_show2 = 'zzz';
25378 +$foo = new test_props;
25379 +var_dump($q = new HttpQueryString(false, $foo));
25380 +$foo->bar->baz = 0;
25381 +var_dump($q->mod($foo));
25386 +object(HttpQueryString)#3 (2) {
25387 + ["queryArray%s]=>
25395 + ["queryString%s]=>
25396 + string(14) "bar%5Bbaz%5D=1"
25398 +object(HttpQueryString)#4 (2) {
25399 + ["queryArray%s]=>
25407 + ["queryString%s]=>
25408 + string(14) "bar%5Bbaz%5D=0"
25412 +++ b/ext/http/tests/HttpRequestDataShare_001.phpt
25415 +HttpRequestDataShare
25418 +include "skip.inc";
25419 +checkurl("www.google.com");
25420 +checkcls("HttpRequestDataShare");
25426 +$s = new HttpRequestDataShare;
25428 +$s->cookie = true;
25430 +$r1 = new HttpRequest("http://www.google.com/");
25431 +$r2 = new HttpRequest("http://www.google.com/");
25433 +$r1->enableCookies();
25434 +$r2->enableCookies();
25444 +var_dump(current($r1->getResponseCookies())->cookies["PREF"] === HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]);
25453 +++ b/ext/http/tests/HttpRequestDataShare_002.phpt
25456 +HttpRequestDataShare global
25459 +include "skip.inc";
25460 +checkurl("www.google.com");
25461 +checkcls("HttpRequestDataShare");
25467 +$s = HttpRequestDataShare::singleton(true);
25468 +$s->cookie = true;
25471 +$r1 = new HttpRequest("http://www.google.com/");
25472 +$r2 = new HttpRequest("http://www.google.com/");
25474 +$r1->enableCookies();
25475 +$r2->enableCookies();
25485 +if (current($r1->getResponseCookies())->cookies["PREF"] !== HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]) {
25487 + current($r1->getResponseCookies())->cookies["PREF"],
25488 + HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]
25496 +object(HttpRequestDataShare)#1 (4) {
25508 +++ b/ext/http/tests/HttpRequestPool_001.phpt
25514 +include 'skip.inc';
25515 +checkmin("5.2.5");
25516 +checkcls('HttpRequestPool');
25517 +checkurl('www.php.net');
25518 +checkurl('dev.iworks.at');
25523 +$post = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
25524 +$post->addPostFields(array('a'=>1,'b'=>2)) ;
25526 +$pool = new HttpRequestPool(
25527 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
25533 +foreach ($pool as $req) {
25534 + echo $req->getUrl(), '=',
25535 + $req->getResponseCode(), ':',
25536 + $req->getResponseMessage()->getResponseCode(), "\n";
25539 +foreach ($pool as $req) {
25541 + $pool->attach(new HttpRequest('http://foo.bar'));
25542 + } catch (HttpRequestPoolException $x) {
25547 +foreach ($pool as $req) {
25548 + $pool->detach($req);
25556 +http://www.php.net/=200:200
25557 +http://dev.iworks.at/ext-http/.print_request.php=200:200
25562 +++ b/ext/http/tests/HttpRequestPool_002.phpt
25565 +extending HttpRequestPool
25568 +include 'skip.inc';
25569 +checkcls('HttpRequestPool');
25570 +checkurl('www.php.net');
25576 +class MyPool extends HttpRequestPool
25578 + public function send()
25580 + while ($this->socketPerform()) {
25581 + if (!$this->socketSelect()) {
25582 + throw new HttpSocketException;
25587 + protected final function socketPerform()
25589 + $result = parent::socketPerform();
25592 + foreach ($this->getFinishedRequests() as $r) {
25593 + echo "=", $r->getResponseCode(), "=";
25594 + $this->detach($r);
25601 +$pool = new MyPool(
25602 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
25603 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
25604 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD)
25613 +\.*=200=\.*=200=\.*=200=
25616 +++ b/ext/http/tests/HttpRequestPool_003.phpt
25619 +HttpRequestPool chain
25622 +include 'skip.inc';
25623 +checkcls('HttpRequest');
25624 +checkcls('HttpRequestPool');
25631 +set_time_limit(0);
25632 +ini_set('error_reporting', E_ALL);
25633 +ini_set('html_errors', 0);
25635 +class Pool extends HttpRequestPool
25641 + public final function __construct($urls_file = 'urls.txt', $cache_dir = 'HttpRequestPool_cache')
25643 + $this->dir = (is_dir($cache_dir) or @mkdir($cache_dir)) ? $cache_dir : null;
25645 + foreach (array_map('trim', file($urls_file)) as $url) {
25646 + $this->all[$url] = $this->dir ? $this->dir .'/'. md5($url) : null;
25652 + public final function send()
25655 + $now = array_slice($this->all, 0, RMAX);
25656 + $this->rem = array_slice($this->all, RMAX);
25659 + $this->rem = array();
25662 + foreach ($now as $url => $file) {
25666 + HttpRequest::METH_GET,
25669 + 'compress' => GZIP,
25670 + 'timeout' => TOUT,
25671 + 'connecttimeout' => TOUT,
25672 + 'lastmodified' => is_file($file)?filemtime($file):0
25678 + while ($this->socketPerform()) {
25679 + if (!$this->socketSelect()) {
25680 + throw new HttpSocketException;
25685 + protected final function socketPerform()
25688 + $rc = parent::socketPerform();
25689 + } catch (HttpRequestException $x) {
25690 + // a request may have thrown an exception,
25691 + // but it is still save to continue
25692 + echo $x->getMessage(), "\n";
25695 + foreach ($this->getFinishedRequests() as $r) {
25696 + $this->detach($r);
25698 + $u = $r->getUrl();
25699 + $c = $r->getResponseCode();
25700 + $b = $r->getResponseBody();
25702 + printf("%d %s %d\n", $c, $u, strlen($b));
25704 + if ($c == 200 && $this->dir) {
25705 + file_put_contents($this->all[$u], $b);
25708 + if ($a = each($this->rem)) {
25709 + list($url, $file) = $a;
25713 + HttpRequest::METH_GET,
25716 + 'compress' => GZIP,
25717 + 'timeout' => TOUT,
25718 + 'connecttimeout' => TOUT,
25719 + 'lastmodified' => is_file($file)?filemtime($file):0
25729 +define('GZIP', true);
25730 +define('TOUT', 50);
25731 +define('RMAX', 10);
25732 +chdir(dirname(__FILE__));
25734 +$time = microtime(true);
25735 +$pool = new Pool();
25736 +printf("Elapsed: %0.3fs\n", microtime(true)-$time);
25794 +++ b/ext/http/tests/HttpRequestPool_004.phpt
25797 +HttpRequestPool::__destruct() invalid curl handle
25800 +include 'skip.inc';
25801 +checkmin("5.2.5");
25802 +checkcls('HttpRequest');
25803 +checkcls('HttpRequestPool');
25808 +$p = new HttpRequestPool(new HttpRequest('http://example.com'));
25816 +++ b/ext/http/tests/HttpRequestPool_005.phpt
25819 +HttpRequestPool exception
25822 +include 'skip.inc';
25823 +checkmin("5.2.5");
25824 +checkcls('HttpRequestPool');
25830 +$p = new HttpRequestPool(new HttpRequest('http://_____'));
25833 +} catch (HttpRequestPoolException $x) {
25834 + for ($i=0; $x; ++$i, $x = @$x->innerException) {
25835 + printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage());
25839 +$p = new HttpRequestPool(new HttpRequest('http://_____'), new HttpRequest('http://_____'));
25842 +} catch (HttpRequestPoolException $x) {
25843 + for ($i=0; $x; ++$i, $x = @$x->innerException) {
25844 + printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage());
25852 +HttpRequestPoolException: Exception caused by 2 inner exception(s)
25853 + HttpInvalidParamException: Empty or too short HTTP message: ''
25854 + HttpRequestException: %souldn't resolve host name; %s (http://_____/)
25856 +HttpRequestPoolException: Exception caused by 4 inner exception(s)
25857 + HttpInvalidParamException: Empty or too short HTTP message: ''
25858 + HttpRequestException: %souldn't resolve host name; %s (http://_____/)
25859 + HttpInvalidParamException: Empty or too short HTTP message: ''
25860 + HttpRequestException: %souldn't resolve host name; %s (http://_____/)
25865 +++ b/ext/http/tests/HttpRequestPool_006.phpt
25868 +HttpRequestPool detaching in callbacks
25871 +include 'skip.inc';
25872 +checkcls("HttpRequestPool");
25873 +checkurl("at.php.net");
25874 +checkurl("de.php.net");
25879 +class r extends HttpRequest {
25880 + function onProgress() {
25881 + static $i = array();
25882 + if (empty($i[$this->getUrl()])) {
25883 + $i[$this->getUrl()] = true;
25885 + $GLOBALS['p']->detach($this);
25886 + } catch (Exception $ex) {
25891 + function onFinish() {
25892 + $GLOBALS['p']->detach($this);
25895 +$p = new HttpRequestPool(new r("http://at.php.net"), new r("http://de.php.net"));
25897 +var_dump($p->getAttachedRequests());
25902 +exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d
25904 +#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r))
25905 +#1 [internal function]: r->onProgress(Array)
25906 +#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send()
25908 +exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d
25910 +#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r))
25911 +#1 [internal function]: r->onProgress(Array)
25912 +#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send()
25918 +++ b/ext/http/tests/HttpRequest_001.phpt
25921 +HttpRequest options
25924 +include 'skip.inc';
25925 +checkmin("5.2.5");
25926 +checkcls('HttpRequest');
25931 +$r1 = new HttpRequest(null, 0, array('redirect'=>11, 'headers'=>array('X-Foo'=>'Bar')));
25932 +$r2 = new HttpRequest;
25933 +$r2->setOptions(array('redirect'=>99, 'headers'=>array('X-Bar'=>'Foo')));
25934 +$o1 = $r1->getOptions();
25935 +$o2 = $r2->getOptions();
25936 +$r1->setOptions($o2);
25937 +$r2->setOptions($o1);
25938 +print_r(array($o1, $o2));
25939 +var_dump(serialize($r1->getOptions()) === serialize($r2->getOptions()));
25949 + [headers] => Array
25960 + [headers] => Array
25972 +++ b/ext/http/tests/HttpRequest_002.phpt
25975 +HttpRequest GET/POST
25978 +include 'skip.inc';
25979 +checkmin("5.2.5");
25980 +checkcls('HttpRequest');
25981 +checkurl('www.google.com');
25982 +checkurl('dev.iworks.at');
25988 +$r = new HttpRequest('http://www.google.com', HttpRequest::METH_GET);
25990 +print_r($r->getResponseInfo());
25992 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
25993 +$r->addCookies(array('MyCookie' => 'foobar'));
25994 +$r->addQueryData(array('gq'=>'foobar','gi'=>10));
25995 +$r->addPostFields(array('pq'=>'foobar','pi'=>10));
25996 +$r->addPostFile('upload', dirname(__FILE__).'/data.txt', 'text/plain');
25998 +echo $r->getResponseBody();
25999 +var_dump($r->getResponseMessage()->getResponseCode());
26007 + [effective_url] => http://www.google.com/
26008 + [response_code] => 302
26009 + [total_time] => %f
26010 + [namelookup_time] => %f
26011 + [connect_time] => %f
26012 + [pretransfer_time] => %f
26013 + [size_upload] => %d
26014 + [size_download] => %d
26015 + [speed_download] => %d
26016 + [speed_upload] => %d
26017 + [header_size] => %d
26018 + [request_size] => %d
26019 + [ssl_verifyresult] => %d
26021 + [content_length_download] => %d
26022 + [content_length_upload] => %d
26023 + [starttransfer_time] => %f
26024 + [content_type] => %s
26025 + [redirect_time] => %d
26026 + [redirect_count] => %d
26027 + [connect_code] => %d
26028 + [httpauth_avail] => %d
26029 + [proxyauth_avail] => %d
26031 + [num_connects] => %d
26032 + [ssl_engines] => Array
26034 + [cookies] => Array
26044 + [MyCookie] => foobar
26048 + [upload] => Array
26050 + [name] => data.txt
26051 + [type] => text/plain
26061 +++ b/ext/http/tests/HttpRequest_003.phpt
26067 +include 'skip.inc';
26068 +checkmin("5.2.5");
26069 +checkurl('arweb.info');
26070 +skipif(!http_support(HTTP_SUPPORT_SSLREQUESTS), 'need ssl-request support')
26075 +$o = array('redirect' => '3', 'ssl' => array('version' => '3', 'verifyhost' => '1'));
26076 +$r = new HttpRequest('https://ssl.irmler.at/iworks/data.txt');
26077 +$r->setOptions($o);
26079 +var_dump($r->getResponseBody());
26080 +var_dump(is_object($r->getResponseMessage()));
26081 +var_dump(is_object($r->getResponseMessage()));
26082 +var_dump(is_object($r->getResponseMessage()));
26084 +$r->setOptions($o);
26090 +string(10) "1234567890"
26118 +++ b/ext/http/tests/HttpRequest_004.phpt
26121 +HttpRequest multiple posts
26124 +include 'skip.inc';
26125 +checkcls('HttpRequest');
26132 + array('int' => 1, 'dbl' => M_PI),
26133 + array('str' => 'something', 'nil' => null)
26136 +echo "\nFirst Request\n";
26137 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HttpRequest::METH_POST);
26138 +$r->setPostFields($fields[0]);
26139 +$r->addPostFields($fields[1]);
26140 +var_dump($r->send()->getBody());
26141 +var_dump($fields);
26143 +echo "\nSecond Request\n";
26144 +$r->setPostFields($fields);
26145 +var_dump($r->send()->getBody());
26146 +var_dump($fields);
26148 +echo "\nThird Request\n";
26149 +$r->addPostFields(array('x' => 'X'));
26150 +var_dump($r->send()->getBody());
26151 +var_dump($fields);
26153 +echo "\nFourth Request\n";
26154 +$r->setPostFields(array());
26155 +var_dump($r->send()->getBody());
26156 +var_dump($fields);
26167 + [dbl] => 3.1415926535898
26168 + [str] => something
26171 +string(44) "int=1&dbl=3.1415926535898&str=something&nil="
26179 + float(3.1415926535898)
26184 + string(9) "something"
26196 + [dbl] => 3.1415926535898
26201 + [str] => something
26206 +string(72) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D="
26214 + float(3.1415926535898)
26219 + string(9) "something"
26231 + [dbl] => 3.1415926535898
26236 + [str] => something
26242 +string(76) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D=&x=X"
26250 + float(3.1415926535898)
26255 + string(9) "something"
26262 +string(13) "string(0) ""
26270 + float(3.1415926535898)
26275 + string(9) "something"
26283 +++ b/ext/http/tests/HttpRequest_005.phpt
26286 +HttpRequest accessors
26289 +include 'skip.inc';
26290 +checkcls('HttpRequest');
26295 +error_reporting(0);
26296 +$r = new HttpRequest;
26297 +foreach (get_class_methods('HttpRequest') as $method) {
26299 + if (strlen($method) > 3 && substr($method, 0, 3) == 'get')
26300 + $x = $r->$method();
26301 + } catch (HttpException $e) {
26310 +++ b/ext/http/tests/HttpRequest_006.phpt
26313 +HttpRequest XMLRPC
26316 +include 'skip.inc';
26317 +checkext('xmlrpc');
26318 +checkcls('HttpRequest');
26324 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
26325 +$r->setContentType('text/xml');
26326 +$r->setBody(xmlrpc_encode_request('testMethod', array('foo' => 'bar')));
26327 +var_dump($r->send());
26328 +var_dump($r->send());
26329 +var_dump($r->send());
26335 +object(HttpMessage)#%d (%d) {
26336 + ["type:protected"]=>
26338 + ["body:protected"]=>
26339 + string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
26341 +<methodName>testMethod</methodName>
26349 + <string>bar</string>
26359 + ["requestMethod:protected"]=>
26361 + ["requestUrl:protected"]=>
26363 + ["responseStatus:protected"]=>
26365 + ["responseCode:protected"]=>
26367 + ["httpVersion:protected"]=>
26369 + ["headers:protected"]=>
26373 + ["parentMessage:protected"]=>
26376 +object(HttpMessage)#%d (%d) {
26377 + ["type:protected"]=>
26379 + ["body:protected"]=>
26380 + string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
26382 +<methodName>testMethod</methodName>
26390 + <string>bar</string>
26400 + ["requestMethod:protected"]=>
26402 + ["requestUrl:protected"]=>
26404 + ["responseStatus:protected"]=>
26406 + ["responseCode:protected"]=>
26408 + ["httpVersion:protected"]=>
26410 + ["headers:protected"]=>
26414 + ["parentMessage:protected"]=>
26417 +object(HttpMessage)#%d (%d) {
26418 + ["type:protected"]=>
26420 + ["body:protected"]=>
26421 + string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
26423 +<methodName>testMethod</methodName>
26431 + <string>bar</string>
26441 + ["requestMethod:protected"]=>
26443 + ["requestUrl:protected"]=>
26445 + ["responseStatus:protected"]=>
26447 + ["responseCode:protected"]=>
26449 + ["httpVersion:protected"]=>
26451 + ["headers:protected"]=>
26455 + ["parentMessage:protected"]=>
26460 +++ b/ext/http/tests/HttpRequest_007.phpt
26466 +include 'skip.inc';
26467 +checkcls('HttpRequest');
26473 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
26474 +$r->recordHistory = true;
26475 +$r->addHeaders(array('content-type' => 'text/plain'));
26476 +$r->setPutFile(__FILE__);
26478 +var_dump($r->getHistory()->toString(true));
26483 +string(%d) "PUT /ext-http/.print_put.php5 HTTP/1.1
26484 +User-Agent: PECL::HTTP/%a
26485 +Host: dev.iworks.at
26487 +Content-Type: text/plain
26488 +Content-Length: %d
26489 +Expect: 100-continue
26494 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
26495 +$r->recordHistory = true;
26496 +$r->addHeaders(array('content-type' => 'text/plain'));
26497 +$r->setPutFile(__FILE__);
26499 +var_dump($r->getHistory()->toString(true));
26503 +HTTP/1.1 100 Continue
26508 +Vary: Accept-Encoding
26509 +Content-Length: %d
26510 +Content-Type: text/html
26515 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
26516 +$r->recordHistory = true;
26517 +$r->addHeaders(array('content-type' => 'text/plain'));
26518 +$r->setPutFile(__FILE__);
26520 +var_dump($r->getHistory()->toString(true));
26527 +++ b/ext/http/tests/HttpRequest_008.phpt
26530 +HttpRequest custom request method
26533 +include 'skip.inc';
26534 +checkcls('HttpRequest');
26540 +HttpRequest::methodRegister('foobar');
26541 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HttpRequest::METH_FOOBAR);
26542 +$r->setContentType('text/plain');
26543 +$r->setBody('Yep, this is FOOBAR!');
26544 +var_dump($r->send()->getResponseCode());
26545 +var_dump($r->getRawRequestMessage());
26552 +string(%d) "FOOBAR /ext-http/.print_request.php HTTP/1.1
26554 +Host: dev.iworks.at
26556 +Content-Type: text/plain
26557 +Content-Length: 20
26559 +Yep, this is FOOBAR!"
26562 +++ b/ext/http/tests/HttpRequest_009.phpt
26565 +HttpRequest callbacks
26568 +include 'skip.inc';
26569 +checkcls('HttpRequest');
26575 +class _R extends HttpRequest
26577 + function onProgress($progress)
26579 + print_r($progress);
26582 + function onFinish()
26584 + var_dump($this->getResponseCode());
26588 +$r = new _R('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
26589 +$r->addPostFile('upload', __FILE__, 'text/plain');
26613 +++ b/ext/http/tests/HttpRequest_010.phpt
26616 +HttpRequest cookie API
26619 +include 'skip.inc';
26620 +checkmin("5.2.5");
26621 +checkcls("HttpRequest");
26627 +$r = new HttpRequest("http://dev.iworks.at/ext-http/.cookie.php");
26630 +$c[0] = $r->getResponseInfo("cookies");
26631 +if (!empty($c[0])) {
26632 + var_dump('$c[0]', $c[0]);
26635 +var_dump($r->enableCookies());
26638 +$c[1] = $r->getResponseInfo("cookies");
26639 +if (empty($c[1])) {
26640 + var_dump('$c[1]', $c[1]);
26643 +var_dump($r->resetCookies());
26646 +$c[2] = $r->getResponseInfo("cookies");
26647 +if ($c[1] === $c[2]) {
26648 + var_dump('$c[1]', $c[1], '$c[2]', $c[2]);
26652 +$c[3] = $r->getResponseInfo("cookies");
26653 +if ($c[2] !== $c[3]) {
26654 + var_dump('$c[2]', $c[2], '$c[3]', $c[3]);
26664 +++ b/ext/http/tests/HttpResponse_001.phpt
26667 +HttpResponse - send data with caching headers
26670 +include 'skip.inc';
26671 +checkmin("5.2.5");
26676 +HttpResponse::setCache(true);
26677 +HttpResponse::setCacheControl('public', 3600);
26678 +HttpResponse::setData('foobar');
26679 +HttpResponse::send();
26682 +X-Powered-By: PHP/%a
26683 +Cache-Control: public, must-revalidate, max-age=3600
26684 +Last-Modified: %a, %d %a 20%d %d:%d:%d GMT
26686 +Accept-Ranges: bytes
26687 +ETag: "3858f62230ac3c915f300c664312c63f"
26692 +++ b/ext/http/tests/HttpResponse_002.phpt
26695 +HttpResponse - send gzipped file
26698 +include 'skip.inc';
26699 +checkmin("5.2.5");
26701 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
26704 +HTTP_ACCEPT_ENCODING=gzip
26707 +HttpResponse::setGzip(true);
26708 +HttpResponse::setFile(__FILE__);
26709 +HttpResponse::send();
26712 +X-Powered-By: PHP/%a
26714 +Accept-Ranges: bytes
26715 +Content-Encoding: gzip
26716 +Vary: Accept-Encoding
26720 +++ b/ext/http/tests/HttpResponse_003.phpt
26723 +HttpResponse - send gzipped file with caching headers
26726 +include 'skip.inc';
26727 +checkmin("5.2.5");
26729 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
26732 +HTTP_ACCEPT_ENCODING=gzip
26735 +HttpResponse::setGzip(true);
26736 +HttpResponse::setCache(true);
26737 +HttpResponse::setCacheControl('public', 3600);
26738 +HttpResponse::setFile(__FILE__);
26739 +HttpResponse::send();
26742 +X-Powered-By: PHP/%a
26743 +Cache-Control: public, must-revalidate, max-age=3600
26744 +Last-Modified: %a, %d %a 20%d %d:%d:%d GMT
26746 +Accept-Ranges: bytes
26748 +Content-Encoding: gzip
26749 +Vary: Accept-Encoding
26753 +++ b/ext/http/tests/HttpResponse_004.phpt
26756 +HttpResponse - send cached gzipped data
26759 +include 'skip.inc';
26761 +checkmin("5.2.7");
26762 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
26765 +HTTP_IF_NONE_MATCH="900150983cd24fb0d6963f7d28e17f72"
26766 +HTTP_ACCEPT_ENCODING=gzip
26769 +HttpResponse::setGzip(true);
26770 +HttpResponse::setCache(true);
26771 +HttpResponse::setCacheControl('public', 3600);
26772 +HttpResponse::setData("abc");
26773 +HttpResponse::send();
26777 +X-Powered-By: PHP/%s
26778 +Cache-Control: public, must-revalidate, max-age=3600
26780 +Accept-Ranges: bytes
26781 +ETag: "900150983cd24fb0d6963f7d28e17f72"
26783 +++ b/ext/http/tests/HttpResponse_005.phpt
26786 +HttpResponse file not found
26789 +include 'skip.inc';
26791 +checkmin("5.2.5");
26795 +ini_set("error_reporting", 0);
26796 +ini_set("default_mimetype", "text/plain");
26798 +HttpResponse::setContentType("application/pdf");
26799 +HttpResponse::setContentDisposition("doc.pdf");
26800 +HttpResponse::setFile("__nonexistant__.pdf");
26801 +HttpResponse::send();
26805 +X-Powered-By: PHP/%s
26806 +Content-Type: text/plain
26810 +++ b/ext/http/tests/allowed_methods_002.phpt
26816 +include 'skip.inc';
26818 +checkmin("5.2.5");
26822 +include 'log.inc';
26823 +log_prepare(_AMETH_LOG);
26824 +ini_set('http.request.methods.allowed', 'POST');
26829 +X-Powered-By: PHP/%a
26834 +++ b/ext/http/tests/allowed_methods_002_logging.phpt
26837 +logging allowed methods
26840 +include 'skip.inc';
26842 +checkmin("5.2.5");
26845 +HTTP_HOST=example.com
26849 +include 'log.inc';
26850 +log_content(_AMETH_LOG);
26855 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [405-ALLOWED] Allow: POST <%a>
26858 +++ b/ext/http/tests/bug_15800.phpt
26861 +Bug #15800 Double free when zval is separated in convert_to_*
26864 +include 'skip.inc';
26865 +checkmin("5.2.5");
26866 +checkcls('HttpRequest');
26867 +skipif(!function_exists('debug_zval_dump'), "need DEBUG version of PHP");
26872 +$o = array('ssl' => array('verifypeer'=>'1'));
26873 +debug_zval_dump($o);
26875 +$r = new HttpRequest('http://www.google.com');
26876 +$r->setOptions($o);
26878 +debug_zval_dump($o);
26881 +debug_zval_dump($o);
26887 +array(1) refcount(2){
26889 + array(1) refcount(1){
26891 + string(1) "1" refcount(1)
26894 +array(1) refcount(2){
26896 + array(1) refcount(1){
26898 + string(1) "1" refcount(2)
26901 +array(1) refcount(2){
26903 + array(1) refcount(1){
26905 + string(1) "1" refcount(1)
26910 +++ b/ext/http/tests/build_str_001.phpt
26916 +include 'skip.inc';
26922 +parse_str("a=b", $q);
26923 +echo http_build_str($q, null, "&"), "\n";
26925 +parse_str("a=b&c[0]=1", $q);
26926 +echo http_build_str($q, null, "&"), "\n";
26928 +parse_str("a=b&c[0]=1&d[e]=f", $q);
26929 +echo http_build_str($q, null, "&"), "\n";
26931 +echo http_build_str(array(1,2,array(3)), "foo", "&"), "\n";
26939 +a=b&c%5B0%5D=1&d%5Be%5D=f
26940 +foo%5B0%5D=1&foo%5B1%5D=2&foo%5B2%5D%5B0%5D=3
26943 +++ b/ext/http/tests/build_url_001.phpt
26946 +http_build_url() with relative paths
26949 +include 'skip.inc';
26954 +echo http_build_url('page'), "\n";
26955 +echo http_build_url('with/some/path/'), "\n";
26961 +http://%a/with/some/path/
26964 +++ b/ext/http/tests/build_url_002.phpt
26967 +http_build_url() with parse_url()
26970 +include 'skip.inc';
26975 +echo http_build_url(parse_url("http://example.org/orig?q=1#f"),
26976 + parse_url("https://www.example.com:9999/replaced#n")), "\n";
26977 +echo http_build_url(("http://example.org/orig?q=1#f"),
26978 + ("https://www.example.com:9999/replaced#n"), 0, $u), "\n";
26984 +https://www.example.com:9999/replaced?q=1#n
26985 +https://www.example.com:9999/replaced?q=1#n
26988 + [scheme] => https
26989 + [host] => www.example.com
26991 + [path] => /replaced
26997 +++ b/ext/http/tests/build_url_003.phpt
27003 +include 'skip.inc';
27004 +checkmin("5.2.5");
27007 +HTTP_HOST=www.example.com
27010 +$url = '/path/?query#anchor';
27012 +printf("-%s-\n", http_build_url($url));
27013 +printf("-%s-\n", http_build_url($url, array('scheme' => 'https')));
27014 +printf("-%s-\n", http_build_url($url, array('scheme' => 'https', 'host' => 'ssl.example.com')));
27015 +printf("-%s-\n", http_build_url($url, array('scheme' => 'ftp', 'host' => 'ftp.example.com', 'port' => 21)));
27020 +-http://www.example.com/path/?query#anchor-
27021 +-https://www.example.com/path/?query#anchor-
27022 +-https://ssl.example.com/path/?query#anchor-
27023 +-ftp://ftp.example.com/path/?query#anchor-
27026 +++ b/ext/http/tests/build_url_004.phpt
27029 +http_build_url flags
27032 +include 'skip.inc';
27037 +echo http_build_url("http://mike@www.example.com/foo/bar", "./baz", HTTP_URL_STRIP_AUTH|HTTP_URL_JOIN_PATH), "\n";
27038 +echo http_build_url("http://mike@www.example.com/foo/bar/", "../baz", HTTP_URL_STRIP_USER|HTTP_URL_JOIN_PATH), "\n";
27039 +echo http_build_url("http://mike:1234@www.example.com/foo/bar/", "./../baz", HTTP_URL_STRIP_PASS|HTTP_URL_JOIN_PATH), "\n";
27040 +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";
27045 +http://www.example.com/foo/baz
27046 +http://www.example.com/foo/baz
27047 +http://mike@www.example.com/foo/baz
27048 +http://www.example.com/?a%5B0%5D=1&a%5B1%5D=b&b=c
27051 +++ b/ext/http/tests/chunked_decode_001.phpt
27054 +http_chunked_decode() "\r\n"
27057 +include 'skip.inc';
27071 +var_dump(http_chunked_decode($data));
27079 +++ b/ext/http/tests/chunked_decode_002.phpt
27082 +http_chunked_decode() "\n"
27085 +include 'skip.inc';
27099 +var_dump(http_chunked_decode($data));
27107 +++ b/ext/http/tests/chunked_decode_003.phpt
27110 +http_chunked_decode() truncated message
27113 +include 'skip.inc';
27127 +var_dump(http_chunked_decode($data));
27131 +%aWarning%ahttp_chunked_decode()%aTruncated message: chunk size 255 exceeds remaining data size 12 at pos 34 of 46 in%a
27137 +++ b/ext/http/tests/chunked_decode_004.phpt
27140 +http_chunked_decode() truncated message ending with NUL after a chunk
27143 +include 'skip.inc';
27157 +var_dump(http_chunked_decode($data));
27166 +++ b/ext/http/tests/cloning_001.phpt
27172 +include 'skip.inc';
27173 +checkmin("5.2.5");
27174 +checkcls('HttpRequest');
27180 +$r1 = new HttpRequest;
27182 +$r1->setOptions(array('redirect' => 3));
27183 +var_dump($r1->getOptions() == $r2->getOptions());
27184 +$r1->setUrl('http://www.google.com/');
27185 +var_dump($r1->getUrl() == $r2->getUrl());
27187 +var_dump($r1->getResponseInfo() == $r2->getResponseInfo());
27198 +++ b/ext/http/tests/data.txt
27200 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27201 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27202 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27203 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27204 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27205 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27206 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27207 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27208 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27209 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27211 +++ b/ext/http/tests/date_001.phpt
27214 +http_date() with timestamp
27217 +include 'skip.inc';
27222 +echo http_date(1), "\n";
27223 +echo http_date(1234567890), "\n";
27227 +Thu, 01 Jan 1970 00:00:01 GMT
27228 +Fri, 13 Feb 2009 23:31:30 GMT
27231 +++ b/ext/http/tests/date_002.phpt
27234 +http_date() without timestamp
27237 +include 'skip.inc';
27242 +ini_set('date.timezone', 'GMT');
27244 +$t = strtotime($d);
27246 +echo "$t\n$d\nDone\n";
27252 +%a, %d %a %d %d:%d:%d GMT
27255 +++ b/ext/http/tests/encoding_objects_001.phpt
27258 +encoding stream objects
27261 +include 'skip.inc';
27263 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
27268 +$d = new HttpDeflateStream;
27269 +$i = new HttpInflateStream;
27270 +echo $i->flush($d->flush("Hi "));
27271 +echo $i->finish($d->finish("there!\n"));
27272 +echo $i->finish($d->finish("Yo...\n"));
27274 +$id = $i->update($d->update($pd = file_get_contents(__FILE__)));
27275 +foreach (glob('*.phpt') as $f) {
27276 + $id .= $i->update($d->update($tmp = file_get_contents($f)));
27279 +$id .= $i->finish($d->finish());
27281 +var_dump($id == $pd);
27293 +++ b/ext/http/tests/encodings.phpt
27299 +include 'skip.inc';
27300 +skipif(!function_exists('http_deflate'), 'need zlib');
27306 +set_time_limit(0);
27307 +error_reporting(E_ALL);
27311 +for ($i = 0; $i < 5000; ++$i) {
27312 + $s .= chr(rand(0,255));
27315 +var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_ZLIB)));
27316 +var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_GZIP)));
27317 +var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_RAW)));
27319 +if (extension_loaded('zlib')) {
27321 + $s = "A simple test string, which won't blow up ext/zlib.\n";
27323 + ($s == http_inflate(gzencode($s))) or print "GZIP Failed\n";
27324 + ($s == http_inflate(gzdeflate($s))) or print "DEFLATE Failed\n";
27325 + ($s == http_inflate(gzcompress($s))) or print "COMPRESS Failed\n";
27327 + ($s == gzinflate(http_deflate($s, HTTP_DEFLATE_TYPE_RAW))) or print "INFLATE Failed\n";
27328 + ($s == gzuncompress(http_deflate($s, HTTP_DEFLATE_TYPE_ZLIB))) or print "UNCOMPRESS Failed\n";
27340 +++ b/ext/http/tests/etag_mode_031.phpt
27343 +crc32 etag (may fail because PHPs crc32 is actually crc32b)
27346 +include 'skip.inc';
27348 +checkmin("5.2.5");
27352 +ini_set('http.etag.mode', extension_loaded('hash')?'crc32b':'crc32');
27353 +http_cache_etag();
27354 +http_send_data("abc\n");
27357 +X-Powered-By: PHP/%a
27358 +Cache-Control: private, must-revalidate, max-age=0
27359 +Accept-Ranges: bytes
27366 +++ b/ext/http/tests/etag_mode_032.phpt
27372 +include 'skip.inc';
27374 +checkmin("5.2.5");
27378 +ini_set('http.etag.mode', 'SHA1');
27379 +http_cache_etag();
27380 +http_send_data("abc\n");
27383 +X-Powered-By: PHP/%a
27384 +Cache-Control: private, must-revalidate, max-age=0
27385 +Accept-Ranges: bytes
27386 +ETag: "03cfd743661f07975fa2f1220c5194cbaff48451"
27392 +++ b/ext/http/tests/etag_mode_033.phpt
27398 +include 'skip.inc';
27400 +checkmin("5.2.5");
27404 +ini_set('http.etag.mode', 'MD5');
27405 +http_cache_etag();
27406 +http_send_data("abc\n");
27409 +X-Powered-By: PHP/%a
27410 +Cache-Control: private, must-revalidate, max-age=0
27411 +Accept-Ranges: bytes
27412 +ETag: "0bee89b07a248e27c83fc3d5951213c1"
27418 +++ b/ext/http/tests/etag_mode_034.phpt
27424 +include 'skip.inc';
27426 +checkmin("5.2.5");
27427 +skipif(!extension_loaded('hash'), 'need ext/hash support');
27431 +ini_set('http.etag.mode', 'sha256');
27432 +http_cache_etag();
27433 +http_send_data("abc\n");
27436 +X-Powered-By: PHP/%a
27437 +Cache-Control: private, must-revalidate, max-age=0
27438 +Accept-Ranges: bytes
27439 +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb"
27445 +++ b/ext/http/tests/etag_mode_041.phpt
27448 +ob crc32 etag (may fail because PHPs crc32 is actually crc32b)
27451 +include 'skip.inc';
27453 +checkmin("5.2.5");
27457 +ini_set('http.etag.mode', extension_loaded('hash')?'crc32b':'crc32');
27458 +http_cache_etag();
27462 +X-Powered-By: PHP/%a
27463 +Cache-Control: private, must-revalidate, max-age=0
27469 +++ b/ext/http/tests/etag_mode_042.phpt
27475 +include 'skip.inc';
27477 +checkmin("5.2.5");
27481 +ini_set('http.etag.mode', 'SHA1');
27482 +http_cache_etag();
27486 +X-Powered-By: PHP/%a
27487 +Cache-Control: private, must-revalidate, max-age=0
27488 +ETag: "03cfd743661f07975fa2f1220c5194cbaff48451"
27493 +++ b/ext/http/tests/etag_mode_043.phpt
27499 +include 'skip.inc';
27501 +checkmin("5.2.5");
27505 +ini_set('http.etag.mode', 'bogus');
27506 +http_cache_etag();
27510 +X-Powered-By: PHP/%a
27511 +Cache-Control: private, must-revalidate, max-age=0
27512 +ETag: "0bee89b07a248e27c83fc3d5951213c1"
27517 +++ b/ext/http/tests/etag_mode_044.phpt
27523 +include 'skip.inc';
27525 +checkmin("5.2.5");
27526 +skipif(!extension_loaded('hash'), 'need ext/hash support');
27530 +ini_set('http.etag.mode', 'sha256');
27531 +http_cache_etag();
27535 +X-Powered-By: PHP/%a
27536 +Cache-Control: private, must-revalidate, max-age=0
27537 +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb"
27542 +++ b/ext/http/tests/exceptions.phpt
27548 +include 'skip.inc';
27549 +checkmin("5.2.5");
27555 +ini_set('http.only_exceptions', true);
27558 + HTTP_E_RUNTIME => 'Runtime',
27559 + HTTP_E_INVALID_PARAM => 'InvalidParam',
27560 + HTTP_E_HEADER => 'Header',
27561 + HTTP_E_MALFORMED_HEADERS => 'MalformedHeaders',
27562 + HTTP_E_REQUEST_METHOD => 'RequestMethod',
27563 + HTTP_E_MESSAGE_TYPE => 'MessageType',
27564 + HTTP_E_ENCODING => 'Encoding',
27565 + HTTP_E_REQUEST => 'Request',
27566 + HTTP_E_REQUEST_POOL => 'RequestPool',
27567 + HTTP_E_SOCKET => 'Socket',
27568 + HTTP_E_RESPONSE => 'Response',
27569 + HTTP_E_URL => 'Url',
27572 +foreach ($e as $i => $c) {
27574 + $n = "Http{$c}Exception";
27576 + } catch (HttpException $x) {
27577 + printf("%2d: %s\n", $i, get_class($x));
27584 + 1: HttpRuntimeException
27585 + 2: HttpInvalidParamException
27586 + 3: HttpHeaderException
27587 + 4: HttpMalformedHeadersException
27588 + 5: HttpRequestMethodException
27589 + 6: HttpMessageTypeException
27590 + 7: HttpEncodingException
27591 + 8: HttpRequestException
27592 + 9: HttpRequestPoolException
27593 +10: HttpSocketException
27594 +11: HttpResponseException
27595 +12: HttpUrlException
27598 +++ b/ext/http/tests/get_request_data_001.phpt
27604 +include 'skip.inc';
27612 +$_SERVER['HTTP_ACCEPT_CHARSET'] = 'iso-8859-1, *';
27613 +$_SERVER['HTTP_ACCEPT_ENCODING'] = 'none';
27614 +$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0';
27615 +$_SERVER['HTTP_HOST'] = 'localhost';
27617 +$h = http_get_request_headers();
27620 +var_dump(http_get_request_body());
27621 +var_dump(http_get_request_body());
27622 +var_dump(http_get_request_body());
27623 +var_dump(fread(http_get_request_body_stream(), 4096));
27630 + [Accept-Charset] => iso-8859-1, *
27631 + [Accept-Encoding] => none
27632 + [Host] => localhost
27633 + [User-Agent] => Mozilla/5.0
27635 +string(7) "a=b&c=d"
27636 +string(7) "a=b&c=d"
27637 +string(7) "a=b&c=d"
27638 +string(7) "a=b&c=d"
27641 +++ b/ext/http/tests/log.inc
27644 +define('_REDIR_LOG', '__r_log');
27645 +define('_CACHE_LOG', '__c_log');
27646 +define('_AMETH_LOG', '__m_log');
27647 +define('_CMPST_LOG', '__a_log');
27649 +function log_prepare($log)
27651 + is_file($log) and @unlink($log);
27654 + case _REDIR_LOG: ini_set('http.log.redirect', _REDIR_LOG); break;
27655 + case _CACHE_LOG: ini_set('http.log.cache', _CACHE_LOG); break;
27656 + case _AMETH_LOG: ini_set('http.log.allowed_methods', _AMETH_LOG); break;
27657 + case _CMPTS_LOG: ini_set('http.log.composite', _CMPST_LOG); break;
27660 +function log_content($log)
27662 + echo file_get_contents($log);
27667 +++ b/ext/http/tests/match_request_header_001.phpt
27670 +http_match_request_header()
27673 +include 'skip.inc';
27674 +checkmin("5.2.5");
27681 +var_dump(http_match_request_header("Foo", "bar", 1));
27682 +var_dump(http_match_request_header("fOO", "BAR", 0));
27683 +var_dump(http_match_request_header("foo", "BAR", 1));
27693 +++ b/ext/http/tests/negotiation_001.phpt
27699 +include 'skip.inc';
27700 +checkmin("5.2.5");
27703 +HTTP_ACCEPT=application/xml, application/xhtml+xml, text/html ; q = .8
27704 +HTTP_ACCEPT_LANGUAGE=de-AT,de-DE;q=0.8,en-GB;q=0.3,en-US;q=0.2
27705 +HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
27710 + array('de', 'en', 'es'),
27713 + array('utf-8', 'iso-8859-1'),
27716 + array('foo/bar', 'application/xhtml+xml', 'text/html')
27718 +var_dump(http_negotiate_language($langs[0]));
27719 +var_dump(http_negotiate_language($langs[0], $lresult));
27720 +var_dump(http_negotiate_charset($csets[0]));
27721 +var_dump(http_negotiate_charset($csets[0], $cresult));
27722 +var_dump(http_negotiate_content_type($ctype[0]));
27723 +var_dump(http_negotiate_content_type($ctype[0], $tresult));
27724 +var_dump(http_negotiate_language(array("unknown")));
27725 +var_dump(http_negotiate_charset(array("unknown")));
27726 +var_dump(http_negotiate_content_type(array("unknown")));
27727 +print_r($lresult);
27728 +print_r($cresult);
27729 +print_r($tresult);
27736 +string(10) "iso-8859-1"
27737 +string(10) "iso-8859-1"
27738 +string(21) "application/xhtml+xml"
27739 +string(21) "application/xhtml+xml"
27740 +string(7) "unknown"
27741 +string(7) "unknown"
27742 +string(7) "unknown"
27750 + [iso-8859-1] => 1000
27755 + [application/xhtml+xml] => 999
27756 + [text/html] => 0.8
27760 +++ b/ext/http/tests/ob_deflatehandler_001.phpt
27766 +include 'skip.inc';
27768 +checkmin("5.2.5");
27769 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
27772 +HTTP_ACCEPT_ENCODING=gzip
27775 +ob_start('ob_deflatehandler');
27781 +Content-Encoding: gzip
27782 +Vary: Accept-Encoding
27786 +++ b/ext/http/tests/ob_inflatehandler_001.phpt
27792 +include 'skip.inc';
27794 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
27798 +ob_start('ob_inflatehandler');
27799 +echo http_deflate("TEST\n");
27805 +++ b/ext/http/tests/parse_cookie_001.phpt
27811 +include 'skip.inc';
27817 +var_dump(http_parse_cookie('name="value"; foo="bar\"baz"; hey=got"it ; path=/ ; comment=; expires='.http_date(1).' secure ; httpOnly', 0, array("comment")));
27823 +object(stdClass)%a {
27827 + string(5) "value"
27829 + string(7) "bar"baz"
27831 + string(6) "got"it"
27849 +++ b/ext/http/tests/parse_cookie_002.phpt
27855 +include 'skip.inc';
27856 +checkmin("5.2.5");
27862 +var_dump(http_parse_cookie('foo')->cookies['foo']);
27863 +var_dump(http_parse_cookie('foo;')->cookies['foo']);
27864 +var_dump(http_parse_cookie('foo ')->cookies['foo']);
27865 +var_dump(http_parse_cookie('foo ;')->cookies['foo']);
27866 +var_dump(http_parse_cookie('foo ; ')->cookies['foo']);
27867 +var_dump(http_parse_cookie('foo=')->cookies['foo']);
27868 +var_dump(http_parse_cookie('foo=;')->cookies['foo']);
27869 +var_dump(http_parse_cookie('foo =')->cookies['foo']);
27870 +var_dump(http_parse_cookie('foo =;')->cookies['foo']);
27871 +var_dump(http_parse_cookie('foo= ')->cookies['foo']);
27872 +var_dump(http_parse_cookie('foo= ;')->cookies['foo']);
27874 +var_dump(http_parse_cookie('foo=1')->cookies['foo']);
27875 +var_dump(http_parse_cookie('foo=1;')->cookies['foo']);
27876 +var_dump(http_parse_cookie('foo=1 ;')->cookies['foo']);
27877 +var_dump(http_parse_cookie('foo= 1;')->cookies['foo']);
27878 +var_dump(http_parse_cookie('foo = 1;')->cookies['foo']);
27879 +var_dump(http_parse_cookie('foo = 1 ;')->cookies['foo']);
27880 +var_dump(http_parse_cookie('foo=1')->cookies['foo']);
27881 +var_dump(http_parse_cookie('foo= 1')->cookies['foo']);
27883 +var_dump(http_parse_cookie('foo="1"')->cookies['foo']);
27884 +var_dump(http_parse_cookie('foo="1" ')->cookies['foo']);
27885 +var_dump(http_parse_cookie('foo="1";')->cookies['foo']);
27886 +var_dump(http_parse_cookie('foo = "1" ;')->cookies['foo']);
27887 +var_dump(http_parse_cookie('foo= "1" ')->cookies['foo']);
27889 +var_dump(http_parse_cookie('foo=""')->cookies['foo']);
27890 +var_dump(http_parse_cookie('foo="\""')->cookies['foo']);
27891 +var_dump(http_parse_cookie('foo=" "')->cookies['foo']);
27892 +var_dump(http_parse_cookie('foo= "')->cookies['foo']);
27893 +var_dump(http_parse_cookie('foo=" ')->cookies['foo']);
27894 +var_dump(http_parse_cookie('foo= " ')->cookies['foo']);
27932 +++ b/ext/http/tests/parse_headers_001.phpt
27935 +http_parse_headers()
27938 +include 'skip.inc';
27943 +print_r(http_parse_headers(
27944 +"Host: localhost\r\n".
27945 +"Host: ambigious\r\n".
27946 +"Nospace:here\r\n".
27947 +"Muchspace: there \r\n".
27950 +"Folded: one\r\n".
27966 + [Nospace] => here
27967 + [Muchspace] => there
27976 +++ b/ext/http/tests/parse_message_001.phpt
27979 +http_parse_message()
27982 +include 'skip.inc';
27983 +checkurl('www.google.com');
27984 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), 'need curl support');
27989 +$m = http_parse_message(http_get('http://www.google.com'));
27994 +<HTML>%aThe document has moved%a</HTML>
27997 +++ b/ext/http/tests/parse_message_002.phpt
28000 +identity encoding trap
28003 +include 'skip.inc';
28010 +"HTTP/1.1 200 Ok\n".
28011 +"Transfer-Encoding: identity\n".
28012 +"Content-Length: 3\n".
28013 +"Content-Type: text/plain\n\n".
28016 +print_r(http_parse_message($message));
28024 + [httpVersion] => 1.1
28025 + [responseCode] => 200
28026 + [responseStatus] => Ok
28027 + [headers] => Array
28029 + [Transfer-Encoding] => identity
28030 + [Content-Length] => 3
28031 + [Content-Type] => text/plain
28035 + [parentMessage] =>
28039 +++ b/ext/http/tests/parse_message_003.phpt
28042 +content range message
28045 +include 'skip.inc';
28052 +"HTTP/1.1 200 Ok\n".
28053 +"Content-Range: bytes: 0-1/5\n\n".
28056 +$msg = http_parse_message($message);
28057 +var_dump($msg->body);
28060 +"HTTP/1.1 200 Ok\n".
28061 +"Content-Range: bytes 0-1/1\n\n".
28064 +$msg = http_parse_message($message);
28070 +%a Invalid Content-Range header: bytes 0-1/1 in%a
28073 +++ b/ext/http/tests/parse_message_004.phpt
28076 +http_parse_message() recursive
28079 +include 'skip.inc';
28087 +Host: www.example.com
28091 +Content-Length: 10
28093 +Host: www.example.com
28097 +Content-Length: 10
28102 +var_dump(http_parse_message($message));
28108 +object(stdClass)%a {
28111 + ["httpVersion"]=>
28113 + ["responseCode"]=>
28115 + ["responseStatus"]=>
28120 + string(9) "Funky/1.0"
28121 + ["Content-Length"]=>
28125 + string(10) "1234567890"
28126 + ["parentMessage"]=>
28127 + object(stdClass)%a {
28130 + ["httpVersion"]=>
28132 + ["requestMethod"]=>
28139 + string(15) "www.example.com"
28145 + ["parentMessage"]=>
28146 + object(stdClass)%a {
28149 + ["httpVersion"]=>
28151 + ["responseCode"]=>
28153 + ["responseStatus"]=>
28158 + string(9) "Funky/1.0"
28159 + ["Content-Length"]=>
28164 + ["parentMessage"]=>
28165 + object(stdClass)%a {
28168 + ["httpVersion"]=>
28170 + ["requestMethod"]=>
28177 + string(15) "www.example.com"
28183 + ["parentMessage"]=>
28191 +++ b/ext/http/tests/parse_message_005.phpt
28194 +http_parse_message() content range header w/(o) =
28197 +include 'skip.inc';
28202 +print_r(http_parse_message(
28206 +Content-Range: bytes: 0-0/100
28212 +Content-Range: bytes 0-0/100
28225 + [httpVersion] => 1.1
28226 + [responseCode] => 206
28227 + [responseStatus] =>
28228 + [headers] => Array
28230 + [Server] => Funky/1.0
28231 + [Content-Range] => bytes 0-0/100
28235 + [parentMessage] => stdClass Object
28238 + [httpVersion] => 1.1
28239 + [responseCode] => 206
28240 + [responseStatus] =>
28241 + [headers] => Array
28243 + [Server] => Funky/1.0
28244 + [Content-Range] => bytes: 0-0/100
28248 + [parentMessage] =>
28254 +++ b/ext/http/tests/parse_message_006.phpt
28260 +include 'skip.inc';
28267 +"HTTP/1.1 200 Ok\n".
28268 +"Header: Value\r\n".
28269 +"Connection: close\r\n".
28273 +print_r(http_parse_message($message));
28281 + [httpVersion] => 1.1
28282 + [responseCode] => 200
28283 + [responseStatus] => Ok
28284 + [headers] => Array
28286 + [Header] => Value
28287 + [Connection] => close
28291 + [parentMessage] =>
28295 +++ b/ext/http/tests/parse_params_001.phpt
28301 +include 'skip.inc';
28306 +var_dump(http_parse_params('text/html; charset=iso-8859-1'));
28307 +var_dump(http_parse_params('text/html; charset="iso-8859-1"'));
28308 +var_dump(http_parse_params('attachment; filename="gol;got,a.ext"'));
28309 +var_dump(http_parse_params('public, must-revalidate, max-age=0'));
28310 +$p = http_parse_params('a'); var_dump($p->params[0]);
28311 +$p = http_parse_params('a=b'); var_dump($p->params[0]);
28316 +object(stdClass)%a {
28320 + string(9) "text/html"
28324 + string(10) "iso-8859-1"
28328 +object(stdClass)%a {
28332 + string(9) "text/html"
28336 + string(10) "iso-8859-1"
28340 +object(stdClass)%a {
28344 + string(10) "attachment"
28348 + string(13) "gol;got,a.ext"
28352 +object(stdClass)%a {
28356 + string(6) "public"
28358 + string(15) "must-revalidate"
28373 +++ b/ext/http/tests/persistent_handles_001.phpt
28376 +persistent handles
28379 +include 'skip.inc';
28380 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28381 +skipif(!function_exists('zend_thread_id'), "need ZTS build");
28384 +http.persistent.handles.limit=-1
28385 +http.persistent.handles.ident=GLOBAL
28390 +echo "No free handles!\n";
28391 +foreach (http_persistent_handles_count() as $provider => $idents) {
28392 + foreach ((array)$idents as $ident => $counts) {
28393 + if (!empty($counts["free"])) {
28394 + printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
28399 +http_get("http://www.google.com/", null, $info[]);
28401 +echo "One free request handle within GLOBAL: ";
28402 +var_dump(http_persistent_handles_count()->http_request["GLOBAL"]["free"]);
28404 +echo "Reusing request handle: ";
28405 +http_get("http://www.google.com/", null, $info[]);
28406 +var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
28408 +echo "Handles' been cleaned up:\n";
28409 +http_persistent_handles_clean();
28410 +print_r(http_persistent_handles_count());
28417 +One free request handle within GLOBAL: int(1)
28418 +Reusing request handle: bool(true)
28421 +Handles' been cleaned up:
28424 + [http_request] => Array
28426 + [GLOBAL] => Array
28434 + [http_request_datashare] => Array
28436 + [GLOBAL] => Array
28444 + [http_request_datashare_lock] => Array
28446 + [GLOBAL] => Array
28454 + [http_request_pool] => Array
28456 + [GLOBAL] => Array
28467 +++ b/ext/http/tests/persistent_handles_002.phpt
28470 +persistent handles
28473 +include 'skip.inc';
28474 +checkmin("5.2.5");
28475 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28476 +skipif(function_exists('zend_thread_id'), "need non-ZTS build");
28479 +http.persistent.handles.limit=-1
28480 +http.persistent.handles.ident=GLOBAL
28485 +echo "No free handles!\n";
28486 +foreach (http_persistent_handles_count() as $provider => $idents) {
28487 + foreach ((array)$idents as $ident => $counts) {
28488 + if (!empty($counts["free"])) {
28489 + printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
28494 +http_get("http://www.google.com/", null, $info[]);
28496 +echo "One free request handle within GLOBAL: ";
28497 +$h = http_persistent_handles_count();
28498 +var_dump($h->http_request["GLOBAL"]["free"]);
28500 +echo "Reusing request handle: ";
28501 +http_get("http://www.google.com/", null, $info[]);
28502 +var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
28504 +echo "Handles' been cleaned up:\n";
28505 +http_persistent_handles_clean();
28506 +print_r(http_persistent_handles_count());
28513 +One free request handle within GLOBAL: int(1)
28514 +Reusing request handle: bool(true)
28517 +Handles' been cleaned up:
28520 + [http_request] => Array
28522 + [GLOBAL] => Array
28530 + [http_request_datashare] => Array
28532 + [GLOBAL] => Array
28540 + [http_request_pool] => Array
28542 + [GLOBAL] => Array
28553 +++ b/ext/http/tests/persistent_handles_003.phpt
28556 +persistent handles
28559 +include 'skip.inc';
28561 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28564 +http.persistent.handles.limit=-1
28565 +http.persistent.handles.ident=GLOBAL
28570 +echo "No free handles!\n";
28571 +foreach (http_persistent_handles_count() as $provider => $idents) {
28572 + foreach ((array)$idents as $ident => $counts) {
28573 + if (!empty($counts["free"])) {
28574 + printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
28579 +http_get("http://www.google.com/", null, $info[]);
28581 +echo "One free request handle within GLOBAL: ";
28582 +$h = http_persistent_handles_count();
28583 +var_dump($h->http_request["GLOBAL"]["free"]);
28585 +echo "Reusing request handle: ";
28586 +http_get("http://www.google.com/", null, $info[]);
28587 +var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
28589 +echo "Handles' been cleaned up:\n";
28590 +http_persistent_handles_clean();
28591 +print_r(http_persistent_handles_count());
28598 +One free request handle within GLOBAL: int(1)
28599 +Reusing request handle: bool(true)
28602 +Handles' been cleaned up:
28605 + [http_request] => Array
28607 + [GLOBAL] => Array
28618 +++ b/ext/http/tests/redirect_011.phpt
28621 +http_redirect() with params
28624 +include 'skip.inc';
28626 +checkmin("5.2.5");
28629 +HTTP_HOST=localhost
28632 +include 'log.inc';
28633 +log_prepare(_REDIR_LOG);
28634 +http_redirect('redirect', array('a' => 1, 'b' => 2));
28638 +X-Powered-By: PHP/%a
28639 +Location: http://localhost/redirect?a=1&b=2
28642 +Redirecting to <a href="http://localhost/redirect?a=1&b=2">http://localhost/redirect?a=1&b=2</a>.
28645 +++ b/ext/http/tests/redirect_011_logging.phpt
28651 +include 'skip.inc';
28653 +checkmin("5.2.5");
28656 +HTTP_HOST=example.com
28660 +include 'log.inc';
28661 +log_content(_REDIR_LOG);
28666 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a>
28669 +++ b/ext/http/tests/redirect_012.phpt
28672 +http_redirect() with session
28675 +include 'skip.inc';
28677 +checkmin("5.2.5");
28678 +checkext('session');
28681 +HTTP_HOST=localhost
28684 +include 'log.inc';
28685 +log_prepare(_REDIR_LOG);
28687 +http_redirect('redirect', array('a' => 1), true);
28691 +X-Powered-By: PHP/%a
28692 +Set-Cookie: PHPSESSID=%a; path=/
28696 +Location: http://localhost/redirect?a=1&PHPSESSID=%a
28699 +++ b/ext/http/tests/redirect_012_logging.phpt
28705 +include 'skip.inc';
28707 +checkmin("5.2.5");
28708 +checkext("session");
28711 +HTTP_HOST=example.com
28715 +include 'log.inc';
28716 +log_content(_REDIR_LOG);
28721 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a>
28724 +++ b/ext/http/tests/redirect_013.phpt
28727 +http_redirect() permanent
28730 +include 'skip.inc';
28732 +checkmin("5.2.5");
28735 +HTTP_HOST=localhost
28738 +include 'log.inc';
28739 +log_prepare(_REDIR_LOG);
28740 +http_redirect('redirect', null, false, HTTP_REDIRECT_PERM);
28744 +X-Powered-By: PHP/%a
28745 +Location: http://localhost/redirect
28748 +Redirecting to <a href="http://localhost/redirect">http://localhost/redirect</a>.
28751 +++ b/ext/http/tests/redirect_013_logging.phpt
28757 +include 'skip.inc';
28759 +checkmin("5.2.5");
28762 +HTTP_HOST=example.com
28766 +include 'log.inc';
28767 +log_content(_REDIR_LOG);
28772 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [301-REDIRECT] Location: http%a <%a>
28775 +++ b/ext/http/tests/request_cookies.phpt
28778 +urlencoded cookies
28781 +include 'skip.inc';
28783 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28789 +$cookies = array("name" => "val=ue");
28791 +$r = new HttpRequest("http://dev.iworks.at/ext-http/.print_request.php", HTTP_METH_GET, array("cookies" => $cookies));
28792 +$r->recordHistory = true;
28794 +$r->setOptions(array('encodecookies' => false));
28796 +echo $r->getHistory()->toString(true);
28802 +GET /ext-http/.print_request.php HTTP/1.1
28804 +Host: dev.iworks.at
28806 +Cookie: name=val%3Due
28815 +GET /ext-http/.print_request.php HTTP/1.1
28817 +Host: dev.iworks.at
28819 +Cookie: name=val=ue;
28830 +++ b/ext/http/tests/request_etag.phpt
28836 +include 'skip.inc';
28837 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28842 +var_dump(http_get("http://dev.iworks.at/ext-http/etag", array("etag" => '"26ad3a-5-95eb19c0"')));
28847 +string(%d) "HTTP/1.1 304 Not Modified
28850 +ETag: "26ad3a-5-95eb19c0"
28853 \ No newline at end of file
28855 +++ b/ext/http/tests/request_gzip.phpt
28861 +include 'skip.inc';
28862 +checkurl('dev.iworks.at');
28863 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), 'need curl support');
28869 +var_dump(http_parse_message(http_get('http://dev.iworks.at/ext-http/.print_request.php?gzip=1', array('compress' => true))));
28874 +object(stdClass)%a {
28877 + ["httpVersion"]=>
28879 + ["responseCode"]=>
28881 + ["responseStatus"]=>
28887 + string(15) "Accept-Encoding"
28888 + ["Content-Length"]=>
28890 + ["Content-Type"]=>
28891 + string(9) "text/html"
28892 + ["X-Original-Content-Encoding"]=>
28894 + ["X-Original-Content-Length"]=>
28898 + string(26) "Array
28903 + ["parentMessage"]=>
28909 +++ b/ext/http/tests/request_methods.phpt
28915 +include 'skip.inc';
28921 +for ($i = 0; $i <= HTTP_METH_ACL+1; ++$i) {
28922 + var_dump(http_request_method_exists($i));
28923 + echo $name = http_request_method_name($i), "\n";
28924 + var_dump(http_request_method_exists($name));
28927 +for ($i = 0; $i < 5; ++$i) {
28928 + $n = http_request_method_register("M$i");
28929 + var_dump(http_request_method_exists($n));
28930 + var_dump(http_request_method_exists("M$i"));
28932 +for ($i = 0; $i < 5; ++$i) {
28933 + var_dump(http_request_method_unregister("M$i"));
28934 + var_dump(http_request_method_exists("M$i"));
28935 + var_dump(http_request_method_exists($i+HTTP_METH_ACL+1));
29056 +++ b/ext/http/tests/request_put_data.phpt
29062 +include 'skip.inc';
29063 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
29069 +$data = str_repeat("abc", 6000/* > CURLBUF_SIZE */);
29070 +$resp = http_put_data("http://dev.iworks.at/ext-http/.print_put.php5", $data);
29071 +$mess = http_parse_message($resp);
29072 +var_dump($data === $mess->body);
29081 +++ b/ext/http/tests/send_data_001.phpt
29084 +http_send_data() NIL-NUM range
29087 +include 'skip.inc';
29089 +checkmin("5.2.5");
29092 +HTTP_RANGE=bytes=-5
29095 +http_send_content_type('text/plain');
29096 +http_send_data(str_repeat('123abc', 1000));
29100 +X-Powered-By: PHP/%s
29101 +Content-Type: text/plain
29102 +Accept-Ranges: bytes
29103 +Content-Range: bytes 5995-5999/6000
29108 +++ b/ext/http/tests/send_data_002.phpt
29111 +http_send_data() NUM-NUM range
29114 +include 'skip.inc';
29116 +checkmin("5.2.5");
29119 +HTTP_RANGE=bytes=5-6
29122 +http_send_content_type('text/plain');
29123 +http_send_data(str_repeat('123abc', 1000));
29127 +X-Powered-By: PHP/%s
29128 +Content-Type: text/plain
29129 +Accept-Ranges: bytes
29130 +Content-Range: bytes 5-6/6000
29135 +++ b/ext/http/tests/send_data_003.phpt
29138 +http_send_data() NUM-NIL range
29141 +include 'skip.inc';
29143 +checkmin("5.2.5");
29146 +HTTP_RANGE=bytes=5981-
29149 +http_send_content_type('text/plain');
29150 +http_send_data(str_repeat('123abc', 1000));
29154 +X-Powered-By: PHP/%s
29155 +Content-Type: text/plain
29156 +Accept-Ranges: bytes
29157 +Content-Range: bytes 5981-5999/6000
29158 +Content-Length: 19
29160 +c123abc123abc123abc
29162 +++ b/ext/http/tests/send_data_004.phpt
29165 +http_send_data() syntactically invalid range
29168 +include 'skip.inc';
29173 +HTTP_RANGE=bytes=123,-wtf ?
29176 +http_send_content_type('text/plain');
29177 +http_send_data(str_repeat('123abc', 1000));
29180 +X-Powered-By: PHP/%s
29181 +Content-Type: text/plain
29182 +Accept-Ranges: bytes
29183 +Content-Length: 6000
29185 +123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc
29186 \ No newline at end of file
29188 +++ b/ext/http/tests/send_data_005.phpt
29191 +http_send_data() oversized range
29194 +include 'skip.inc';
29196 +checkmin("5.2.5");
29199 +HTTP_RANGE=bytes=5990-6000
29202 +http_send_content_type('text/plain');
29203 +http_send_data(str_repeat('123abc', 1000));
29207 \ No newline at end of file
29209 +++ b/ext/http/tests/send_data_006.phpt
29212 +http_send_data() multiple ranges
29215 +include 'skip.inc';
29217 +checkmin("5.2.5");
29220 +HTTP_RANGE=bytes=0-3, 4-5,9-11
29223 +http_send_content_type('text/plain');
29224 +http_send_data(str_repeat('123abc', 1000));
29228 +X-Powered-By: PHP/%s
29229 +Accept-Ranges: bytes
29230 +Content-Type: multipart/byteranges; boundary=%d.%d
29234 +Content-Type: text/plain
29235 +Content-Range: bytes 0-3/6000
29239 +Content-Type: text/plain
29240 +Content-Range: bytes 4-5/6000
29244 +Content-Type: text/plain
29245 +Content-Range: bytes 9-11/6000
29250 +++ b/ext/http/tests/send_data_010.phpt
29253 +http_send_data() HTTP_SENDBUF_SIZE long string
29256 +include 'skip.inc';
29262 +http_throttle(0.01, 1);
29263 +http_send_data('00000000000000000000');
29266 +X-Powered-By: PHP/%s
29267 +Accept-Ranges: bytes
29268 +Content-Length: 20
29271 +00000000000000000000
29273 +++ b/ext/http/tests/send_data_011.phpt
29276 +http_send_data() last modified caching
29279 +include 'skip.inc';
29285 +http_cache_last_modified(-5);
29286 +http_send_data("abc\n");
29289 +X-Powered-By: PHP/%s
29290 +Cache-Control: private, must-revalidate, max-age=0
29291 +Last-Modified: %s, %d %s %d %d:%d:%d GMT
29292 +Accept-Ranges: bytes
29298 +++ b/ext/http/tests/send_failed_precond_001.phpt
29301 +http_send() failed precondition
29304 +include 'skip.inc';
29309 +HTTP_RANGE=bytes=0-1
29310 +HTTP_IF_UNMODIFIED_SINCE=Thu, 01 Jan 1970 00:16:40 GMT
29313 +http_cache_last_modified();
29314 +http_send_file(__FILE__);
29319 +Cache-Control: private, must-revalidate, max-age=0
29321 +Accept-Ranges: bytes
29322 +Content-type: text/html
29324 +++ b/ext/http/tests/send_file_005.phpt
29327 +http_send_file() multiple ranges
29330 +include 'skip.inc';
29332 +checkmin("5.2.5");
29335 +HTTP_RANGE=bytes=0-3, 4-5,9-11
29338 +http_send_content_type('text/plain');
29339 +http_send_file('data.txt');
29343 +X-Powered-By: PHP/%s
29344 +Accept-Ranges: bytes
29345 +Content-Type: multipart/byteranges; boundary=%d.%d
29349 +Content-Type: text/plain
29350 +Content-Range: bytes 0-3/1010
29354 +Content-Type: text/plain
29355 +Content-Range: bytes 4-5/1010
29359 +Content-Type: text/plain
29360 +Content-Range: bytes 9-11/1010
29365 +++ b/ext/http/tests/send_file_008.phpt
29371 +include 'skip.inc';
29377 +http_send_file('data.txt');
29380 +X-Powered-By: PHP/%s
29381 +Accept-Ranges: bytes
29382 +Content-Length: 1010
29385 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29386 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29387 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29388 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29389 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29390 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29391 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29392 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29393 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29394 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29396 +++ b/ext/http/tests/send_file_009.phpt
29399 +http_send_file() NUM-NUM range
29402 +include 'skip.inc';
29404 +checkmin("5.2.5");
29407 +HTTP_RANGE=bytes=5-9
29410 +http_send_file('data.txt');
29414 +X-Powered-By: PHP/%s
29415 +Accept-Ranges: bytes
29416 +Content-Range: bytes 5-9/1010
29422 +++ b/ext/http/tests/send_file_010.phpt
29425 +http_send_file() NIL-NUM range
29428 +include 'skip.inc';
29430 +checkmin("5.2.5");
29433 +HTTP_RANGE=bytes=-9
29436 +http_send_file('data.txt');
29440 +X-Powered-By: PHP/%s
29441 +Accept-Ranges: bytes
29442 +Content-Range: bytes 1001-1009/1010
29448 +++ b/ext/http/tests/send_file_011.phpt
29451 +http_send_file() NUM-NIL range
29454 +include 'skip.inc';
29456 +checkmin("5.2.5");
29459 +HTTP_RANGE=bytes=1000-
29462 +http_send_file('data.txt');
29466 +X-Powered-By: PHP/%s
29467 +Accept-Ranges: bytes
29468 +Content-Range: bytes 1000-1009/1010
29469 +Content-Length: 10
29474 +++ b/ext/http/tests/send_file_012.phpt
29477 +http_send_file() syntactically invalid range
29480 +include 'skip.inc';
29485 +HTTP_RANGE=bytes=xxx
29488 +http_send_file('data.txt');
29491 +X-Powered-By: PHP/%s
29492 +Accept-Ranges: bytes
29493 +Content-Length: 1010
29496 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29497 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29498 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29499 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29500 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29501 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29502 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29503 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29504 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29505 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29507 +++ b/ext/http/tests/send_file_013.phpt
29510 +http_send_file() oversized range
29513 +include 'skip.inc';
29515 +checkmin("5.2.5");
29518 +HTTP_RANGE=bytes=-1111
29521 +http_send_file('data.txt');
29525 +X-Powered-By: PHP/%s
29526 +Accept-Ranges: bytes
29529 +++ b/ext/http/tests/send_ifrange_001.phpt
29532 +http_send() If-Range
29535 +include 'skip.inc';
29537 +checkmin("5.2.5");
29540 +HTTP_RANGE=bytes=0-1
29541 +HTTP_IF_RANGE="abc"
29544 +http_cache_etag('abc');
29545 +http_send_file(__FILE__);
29550 +Cache-Control: private, must-revalidate, max-age=0
29552 +Accept-Ranges: bytes
29553 +Content-Range: bytes 0-1/%d
29555 +Content-type: text/html
29559 +++ b/ext/http/tests/send_ifrange_003.phpt
29562 +http_send() If-Range
29565 +include 'skip.inc';
29567 +checkmin("5.2.5");
29570 +HTTP_RANGE=bytes=0-1
29571 +HTTP_IF_RANGE="abcd"
29574 +http_cache_etag('abc');
29575 +http_send_file(__FILE__);
29579 +Cache-Control: private, must-revalidate, max-age=0
29581 +Accept-Ranges: bytes
29582 +Content-Length: %d
29583 +Content-type: text/html
29587 +++ b/ext/http/tests/skip.inc
29590 +defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
29591 +if (!function_exists('fprintf')) {
29592 + function fprintf(){ $a=func_get_args(); $s=array_shift($a); return fwrite($s, call_user_func_array('sprintf',$a)); }
29594 +function skipif($if, $skip) { if ($if) { fprintf(STDOUT, "skip $skip"); exit(); }}
29595 +function checkcgi() { skipif(!strncasecmp('CLI', PHP_SAPI, 3), 'need CGI SAPI'); }
29596 +function checkext($ext) { skipif(!extension_loaded($ext), "need ext/$ext"); }
29597 +function checkmin($ver) { skipif(version_compare(PHP_VERSION, $ver) < 0, sprintf("need PHP >= v%s",$ver)); }
29598 +function checkmax($ver) { skipif(version_compare(PHP_VERSION, $ver) > 0, sprintf("need PHP <= v%s",$ver)); }
29599 +function checkurl($url) { skipif(!@fsockopen($url, 80), "$url not responsive"); }
29600 +function checkcls($cls) { skipif(!class_exists($cls), "need class $cls"); }
29601 +function checkver($ver) { checkmin($ver); }
29605 +++ b/ext/http/tests/stream_filters_001.phpt
29611 +include 'skip.inc';
29612 +checkmin("5.2.5");
29618 +define('F', 'http.test_stream_filters');
29620 +$f = fopen(F, 'w');
29621 +stream_filter_append($f, 'http.chunked_encode');
29623 +fwrite($f, "Here ");
29625 +fwrite($f, " go!\n");
29628 +var_dump(file_get_contents(F));
29630 +$f = fopen(F, 'r');
29631 +stream_filter_append($f, 'http.chunked_decode');
29632 +var_dump(fread($f, 256));
29649 +string(12) "Here we go!
29653 +++ b/ext/http/tests/stream_filters_002.phpt
29656 +gzip stream filters
29659 +include 'skip.inc';
29661 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
29668 +$d = file_get_contents(__FILE__);
29669 +$n = tempnam(dirname(__FILE__), 'hsf');
29671 +$f = fopen($n, 'wb');
29672 +stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_GZIP);
29677 +var_dump($d.$d == http_inflate(file_get_contents($n)));
29679 +$f = fopen($n, 'wb');
29680 +stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE);
29685 +var_dump($d.$d == http_inflate(file_get_contents($n)));
29687 +$f = fopen($n, 'wb');
29688 +stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_RAW);
29693 +var_dump($d.$d == http_inflate(file_get_contents($n)));
29706 +++ b/ext/http/tests/stream_filters_003.phpt
29712 +include 'skip.inc';
29713 +checkmin("5.2.5");
29714 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
29720 +define('OUT', fopen('php://output', 'w'));
29722 +stream_filter_append(OUT, 'http.chunked_encode');
29723 +stream_filter_append(OUT, 'http.deflate');
29724 +stream_filter_append(OUT, 'http.chunked_encode');
29725 +stream_filter_append(OUT, 'http.deflate');
29726 +stream_filter_append(OUT, 'http.inflate');
29727 +stream_filter_append(OUT, 'http.chunked_decode');
29728 +stream_filter_append(OUT, 'http.inflate');
29729 +stream_filter_append(OUT, 'http.chunked_decode');
29731 +$text = <<<SOME_TEXT
29732 +This is some stream filter fun; we'll see if it bails out or not.
29733 +The text should come out at the other end of the stream exactly like written to it.
29738 +foreach (str_split($text, 5) as $part) {
29739 + fwrite(OUT, $part);
29740 + if (rand(0, 1)) {
29747 +This is some stream filter fun; we'll see if it bails out or not.
29748 +The text should come out at the other end of the stream exactly like written to it.
29751 +++ b/ext/http/tests/urls.txt
29753 +http://www.microsoft.com
29754 +http://www.opensource.org
29755 +http://www.google.com
29756 +http://www.yahoo.com
29757 +http://www.ibm.com
29758 +http://www.mysql.com
29759 +http://www.oracle.com
29760 +http://www.ripe.net
29761 +http://www.iana.org
29762 +http://www.amazon.com
29763 +http://www.netcraft.com
29764 +http://www.heise.de
29765 +http://www.chip.de
29767 +http://www.cnet.com
29768 +http://www.news.com
29769 +http://www.cnn.com
29770 +http://www.wikipedia.org
29771 +http://www.dell.com
29773 +http://www.cert.org
29774 +http://www.mit.edu
29775 +http://www.nist.gov
29776 +http://www.ebay.com
29777 +http://www.playstation.com
29778 +http://www.uefa.com
29779 +http://www.ieee.org
29780 +http://www.apple.com
29781 +http://www.sony.com
29782 +http://www.symantec.com
29783 +http://www.zdnet.com
29784 +http://www.fujitsu.com
29785 +http://www.supermicro.com
29786 +http://www.hotmail.com
29787 +http://www.ecma.com
29788 +http://www.bbc.co.uk
29789 +http://news.google.com
29790 +http://www.foxnews.com
29791 +http://www.msn.com
29792 +http://www.wired.com
29793 +http://www.sky.com
29794 +http://www.usatoday.com
29795 +http://www.cbs.com
29796 +http://www.nbc.com
29797 +http://slashdot.org
29798 +http://www.bloglines.com
29799 +http://www.techweb.com
29800 +http://www.newslink.org
29802 \ No newline at end of file