[packages] php5: update pecl module http to 1.7.4
[openwrt/svn-archive/archive.git] / lang / php5 / patches / 030-PECL-add-http.patch
1 --- /dev/null
2 +++ b/ext/http/CREDITS
3 @@ -0,0 +1,2 @@
4 +HTTP extension for PHP
5 +Michael Wallner
6 --- /dev/null
7 +++ b/ext/http/KnownIssues.txt
8 @@ -0,0 +1,33 @@
9 +Known Issues
10 +============
11 +$Id: KnownIssues.txt 292753 2009-12-29 12:30:43Z mike $
12 +
13 +PHP < 5.1.3:
14 + HttpResponse::getHeader() does not work with Apache2 SAPIs.
15 + Using an encoding stream filter on a stream you read from doesn't work.
16 +
17 +Windows:
18 + If you keep getting "SSL connect error" when trying to issue
19 + requests, try another (newer) libeay32.dll/ssleay32.dll pair.
20 +
21 +Internals:
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
37 + procedural API
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.
42 --- /dev/null
43 +++ b/ext/http/LICENSE
44 @@ -0,0 +1,47 @@
45 +Copyright (c) 2004-2010, Michael Wallner <mike@iworks.at>.
46 +All rights reserved.
47 +
48 +Redistribution and use in source and binary forms, with or without
49 +modification, are permitted provided that the following conditions are met:
50 +
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.
56 +
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.
67 +
68 +===============================================================================
69 +
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:
72 +
73 +Copyright (c) 1996 - 2006, Daniel Stenberg, <daniel@haxx.se>.
74 +All rights reserved.
75 +
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.
79 +
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.
87 +
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.
91 +
92 --- /dev/null
93 +++ b/ext/http/Makefile.frag
94 @@ -0,0 +1,23 @@
95 +# vim: noet ts=1 sw=1
96 +
97 +phpincludedir=$(prefix)/include/php
98 +
99 +install-http: install install-http-headers
100 +
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; \
113 + else \
114 + echo "WTF? $$f"; \
115 + fi \
116 + done;
117 +
118 --- /dev/null
119 +++ b/ext/http/ThanksTo.txt
120 @@ -0,0 +1,20 @@
121 +Thanks To
122 +=========
123 +$Id: ThanksTo.txt 275653 2009-02-12 13:11:05Z mike $
124 +
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:
128 +
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)
139 +
140 +Thanks a lot!
141 --- /dev/null
142 +++ b/ext/http/config.m4
143 @@ -0,0 +1,5 @@
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
147 +
148 +sinclude(config9.m4)
149 --- /dev/null
150 +++ b/ext/http/config.w32
151 @@ -0,0 +1,129 @@
152 +// config.w32 for pecl/http
153 +// $Id: config.w32 287971 2009-09-02 14:36:08Z pajoye $
154 +
155 +ARG_ENABLE("http", "whether to enable extended HTTP support", "no");
156 +
157 +function check_for_main_ext(ext, header)
158 +{
159 + if (!header) {
160 + header = "php_"+ ext +".h";
161 + }
162 +
163 + /* When in configure, we're always in the root of PHP source */
164 + var ext_path = "ext\\" + ext;
165 +
166 + STDOUT.Write("Checking for ext/"+ ext +" ... ");
167 +
168 + if (FSO.FileExists(ext_path + "\\" + header)) {
169 + STDOUT.WriteLine(ext_path);
170 + return ext_path;
171 + }
172 +
173 + STDOUT.WriteLine("<not found>");
174 + return false;
175 +}
176 +
177 +function check_for_pecl_ext(ext, header)
178 +{
179 + if (!header) {
180 + header = "php_"+ ext +".h";
181 + }
182 +
183 + var g;
184 + var s = ext +"\\"+ header;
185 +
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);
191 + return f;
192 + }
193 + STDOUT.WriteLine("<not found>");
194 + return false;
195 +}
196 +
197 +if (PHP_HTTP != "no") {
198 +
199 + EXTENSION("http",
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",
211 + null,
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");
216 +
217 + AC_DEFINE("HAVE_GETHOSTNAME", 1);
218 + AC_DEFINE("HAVE_GETSERVBYPORT", 1);
219 + AC_DEFINE("HAVE_GETSERVBYNAME", 1);
220 +
221 + if (PHP_DEBUG != "no") {
222 + ADD_FLAG("CFLAGS_HTTP", "/W3");
223 + }
224 +
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");
228 + } else {
229 + WARNING("zlib encoding functions not enabled; libraries and headers not found");
230 + }
231 +
232 + if (typeof(PHP_HASH) != "undefined" && PHP_HASH != "no") {
233 + var f;
234 +
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);
238 + }
239 + }
240 +
241 + if (PHP_SESSION != "no") {
242 + ADD_EXTENSION_DEP("http", "session", true);
243 + }
244 +
245 + if (PHP_ICONV != "no") {
246 + ADD_EXTENSION_DEP("http", "iconv", true);
247 + }
248 +
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, "");
267 + } else {
268 + WARNING("curl convenience functions not enabled; libraries and headers not found");
269 + }
270 +/*
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", "", "");
276 +// } else {
277 +// WARNING("content type guessing not enabled; libraries and headers not found");
278 +// }
279 +*/
280 +}
281 --- /dev/null
282 +++ b/ext/http/config9.m4
283 @@ -0,0 +1,468 @@
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
287 +
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")
306 +
307 +if test "$PHP_HTTP" != "no"; then
308 +
309 + ifdef([AC_PROG_EGREP], [
310 + AC_PROG_EGREP
311 + ], [
312 + AC_CHECK_PROG(EGREP, egrep, egrep)
313 + ])
314 + ifdef([AC_PROG_SED], [
315 + AC_PROG_SED
316 + ], [
317 + ifdef([LT_AC_PROG_SED], [
318 + LT_AC_PROG_SED
319 + ], [
320 + AC_CHECK_PROG(SED, sed, sed)
321 + ])
322 + ])
323 +
324 + AC_PROG_CPP
325 +
326 + if test "$PHP_HTTP_SHARED_DEPS" != "no"; then
327 + AC_DEFINE([HTTP_SHARED_DEPS], [1], [ ])
328 + else
329 + AC_DEFINE([HTTP_SHARED_DEPS], [0], [ ])
330 + fi
331 +
332 + dnl
333 + dnl HTTP_SHARED_DEP(name[, code-if-yes[, code-if-not]])
334 + dnl
335 + AC_DEFUN([HTTP_SHARED_DEP], [
336 + extname=$1
337 + haveext=$[HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)
338 +
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])
342 + $3
343 + elif test "$haveext"; then
344 + AC_MSG_RESULT([yes])
345 + ifdef([PHP_ADD_EXTENSION_DEP], [
346 + PHP_ADD_EXTENSION_DEP([http], $1, true)
347 + ])
348 + $2
349 + else
350 + AC_MSG_RESULT([no])
351 + $3
352 + fi
353 + ])
354 +
355 + dnl
356 + dnl HTTP_HAVE_PHP_EXT(name[, code-if-yes[, code-if-not]])
357 + dnl
358 + AC_DEFUN([HTTP_HAVE_PHP_EXT], [
359 + extname=$1
360 + haveext=$[PHP_]translit($1,a-z_-,A-Z__)
361 +
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])
368 + $2
369 + else
370 + [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=
371 + AC_MSG_RESULT([no])
372 + $3
373 + fi
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])
377 + $2
378 + else
379 + [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=
380 + AC_MSG_RESULT([no])
381 + $3
382 + fi
383 + ])
384 +
385 + dnl
386 + dnl odd PHP4 fix
387 + dnl
388 + if test "x$PHP_LIBDIR" = "x"; then
389 + PHP_LIBDIR=lib
390 + fi
391 +
392 +dnl ----
393 +dnl STDC
394 +dnl ----
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)
400 +
401 +dnl ----
402 +dnl ZLIB
403 +dnl ----
404 + if test "$PHP_HTTP_ZLIB_COMPRESSION" != "no"; then
405 + AC_MSG_CHECKING([for zlib.h])
406 + ZLIB_DIR=
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
409 + ZLIB_DIR=$i
410 + break;
411 + fi
412 + done
413 + if test "x$ZLIB_DIR" = "x"; then
414 + AC_MSG_RESULT([not found])
415 + AC_MSG_ERROR([could not find zlib.h])
416 + else
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])
423 + else
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])
427 + fi
428 + fi
429 + fi
430 +
431 +dnl ----
432 +dnl CURL
433 +dnl ----
434 + if test "$PHP_HTTP_CURL_REQUESTS" != "no"; then
435 + AC_MSG_CHECKING([for curl/curl.h])
436 + CURL_DIR=
437 + for i in "$PHP_HTTP_CURL_REQUESTS" /usr/local /usr /opt; do
438 + if test -f "$i/include/curl/curl.h"; then
439 + CURL_DIR=$i
440 + break
441 + fi
442 + done
443 + if test "x$CURL_DIR" = "x"; then
444 + AC_MSG_RESULT([not found])
445 + AC_MSG_ERROR([could not find curl/curl.h])
446 + else
447 + AC_MSG_RESULT([found in $CURL_DIR])
448 + fi
449 +
450 + AC_MSG_CHECKING([for curl-config])
451 + 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
454 + CURL_CONFIG=$i
455 + break
456 + fi
457 + done
458 + if test "x$CURL_CONFIG" = "x"; then
459 + AC_MSG_RESULT([not found])
460 + AC_MSG_ERROR([could not find curl-config])
461 + else
462 + AC_MSG_RESULT([found: $CURL_CONFIG])
463 + fi
464 +
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])
471 + fi
472 +
473 + dnl
474 + dnl compile tests
475 + dnl
476 +
477 + save_INCLUDES="$INCLUDES"
478 + INCLUDES=
479 + save_LIBS="$LIBS"
480 + LIBS=
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"
486 +
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], [ ])
492 +
493 + AC_MSG_CHECKING([for openssl support in libcurl])
494 + AC_TRY_RUN([
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);
502 + }
503 + return 1;
504 + }
505 + ], [
506 + AC_MSG_RESULT([yes])
507 + AC_CHECK_HEADER([openssl/crypto.h], [
508 + AC_DEFINE([HTTP_HAVE_OPENSSL], [1], [ ])
509 + ])
510 + ], [
511 + AC_MSG_RESULT([no])
512 + ], [
513 + AC_MSG_RESULT([no])
514 + ])
515 +
516 + AC_MSG_CHECKING([for gnutls support in libcurl])
517 + AC_TRY_RUN([
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);
525 + }
526 + return 1;
527 + }
528 + ], [
529 + AC_MSG_RESULT([yes])
530 + AC_CHECK_HEADER([gcrypt.h], [
531 + AC_DEFINE([HTTP_HAVE_GNUTLS], [1], [ ])
532 + ])
533 + ], [
534 + AC_MSG_RESULT([no])
535 + ], [
536 + AC_MSG_RESULT([no])
537 + ])
538 + else
539 + AC_MSG_RESULT([no])
540 + fi
541 +
542 + INCLUDES="$save_INCLUDES"
543 + LIBS="$save_LIBS"
544 + CFLAGS="$save_CFLAGS"
545 + LDFLAGS="$save_LDFLAGS"
546 +
547 + dnl end compile tests
548 +
549 + AC_MSG_CHECKING([for bundled SSL CA info])
550 + CURL_CAINFO=
551 + for i in `$CURL_CONFIG --ca` "/etc/ssl/certs/ca-certificates.crt"; do
552 + if test -f "$i"; then
553 + CURL_CAINFO="$i"
554 + break
555 + fi
556 + done
557 + if test "x$CURL_CAINFO" = "x"; then
558 + AC_MSG_RESULT([not found])
559 + else
560 + AC_MSG_RESULT([$CURL_CAINFO])
561 + AC_DEFINE_UNQUOTED([HTTP_CURL_CAINFO], ["$CURL_CAINFO"], [path to bundled SSL CA info])
562 + fi
563 +
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])
568 +
569 + PHP_CHECK_LIBRARY(curl, curl_share_strerror,
570 + [AC_DEFINE([HAVE_CURL_SHARE_STRERROR], [1], [ ])], [ ],
571 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
572 + )
573 + PHP_CHECK_LIBRARY(curl, curl_multi_strerror,
574 + [AC_DEFINE([HAVE_CURL_MULTI_STRERROR], [1], [ ])], [ ],
575 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
576 + )
577 + PHP_CHECK_LIBRARY(curl, curl_easy_strerror,
578 + [AC_DEFINE([HAVE_CURL_EASY_STRERROR], [1], [ ])], [ ],
579 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
580 + )
581 + PHP_CHECK_LIBRARY(curl, curl_easy_reset,
582 + [AC_DEFINE([HAVE_CURL_EASY_RESET], [1], [ ])], [ ],
583 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
584 + )
585 + PHP_CHECK_LIBRARY(curl, curl_formget,
586 + [AC_DEFINE([HAVE_CURL_FORMGET], [1], [ ])], [ ],
587 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
588 + )
589 + PHP_CHECK_LIBRARY(curl, curl_multi_setopt,
590 + [AC_DEFINE([HAVE_CURL_MULTI_SETOPT], [1], [ ])], [ ],
591 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
592 + )
593 + PHP_CHECK_LIBRARY(curl, curl_multi_timeout,
594 + [AC_DEFINE([HAVE_CURL_MULTI_TIMEOUT], [1], [ ])], [ ],
595 + [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR]
596 + )
597 +
598 + dnl ----
599 + dnl EVENT
600 + dnl ----
601 +
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])
605 + ], [
606 + AC_MSG_CHECKING([for event.h])
607 + EVENT_DIR=
608 + for i in "$PHP_HTTP_CURL_LIBEVENT" /usr/local /usr /opt; do
609 + if test -f "$i/include/event.h"; then
610 + EVENT_DIR=$i
611 + break
612 + fi
613 + done
614 + if test "x$EVENT_DIR" = "x"; then
615 + AC_MSG_RESULT([not found])
616 + AC_MSG_WARN([continuing without libevent support])
617 + else
618 + AC_MSG_RESULT([found in $EVENT_DIR])
619 +
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"
625 + else
626 + EVENT_VER="1.2 or greater"
627 + fi
628 + fi
629 + AC_DEFINE_UNQUOTED([HTTP_EVENT_VERSION], ["$EVENT_VER"], [ ])
630 + AC_MSG_RESULT([$EVENT_VER])
631 +
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])
636 + else
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]
643 + )
644 + fi
645 + fi
646 + ])
647 + fi
648 + fi
649 +
650 +dnl ----
651 +dnl MAGIC
652 +dnl ----
653 + if test "$PHP_HTTP_MAGIC_MIME" != "no"; then
654 + AC_MSG_CHECKING([for magic.h])
655 + MAGIC_DIR=
656 + for i in "$PHP_HTTP_MAGIC_MIME" /usr/local /usr /opt; do
657 + if test -f "$i/include/magic.h"; then
658 + MAGIC_DIR=$i
659 + break
660 + fi
661 + done
662 + if test "x$MAGIC_DIR" = "x"; then
663 + AC_MSG_RESULT([not found])
664 + AC_MSG_ERROR([could not find magic.h])
665 + else
666 + AC_MSG_RESULT([found in $MAGIC_DIR])
667 + fi
668 +
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])
672 + fi
673 +
674 +dnl ----
675 +dnl HASH
676 +dnl ----
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
684 + break
685 + elif test -f $i/ext/hash/php_hash.h; then
686 + HTTP_EXT_HASH_INCDIR=$i/ext/hash
687 + break
688 + fi
689 + fi
690 + done
691 + if test "x$HTTP_EXT_HASH_INCDIR" = "x"; then
692 + AC_MSG_RESULT([not found])
693 + else
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])
697 + fi
698 + ])
699 +
700 +dnl ----
701 +dnl ICONV
702 +dnl ----
703 + HTTP_HAVE_PHP_EXT([iconv])
704 +
705 +dnl ----
706 +dnl SESSION
707 +dnl ----
708 + HTTP_HAVE_PHP_EXT([session])
709 +
710 +dnl ----
711 +dnl DONE
712 +dnl ----
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"
723 +
724 + PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared)
725 +
726 + dnl shared extension deps
727 + HTTP_SHARED_DEP([hash])
728 + HTTP_SHARED_DEP([iconv])
729 + HTTP_SHARED_DEP([session])
730 +
731 + PHP_ADD_BUILD_DIR($ext_builddir/phpstr, 1)
732 + PHP_SUBST([HTTP_SHARED_LIBADD])
733 +
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)
745 + ], [
746 + PHP_SUBST([PHP_HTTP_HEADERS])
747 + PHP_ADD_MAKEFILE_FRAGMENT
748 + ])
749 +
750 + AC_DEFINE([HAVE_HTTP], [1], [Have extended HTTP support])
751 +fi
752 --- /dev/null
753 +++ b/ext/http/docs/examples/tutorial.txt
754 @@ -0,0 +1,175 @@
755 +
756 +A Beginners Tutorial
757 +--------------------
758 +$Revision: 208773 $
759 +
760 +
761 +- GET Queries
762 +
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.
767 +
768 +<?php
769 +$r = new HttpRequest('http://www.google.com/search');
770 +
771 +// store Googles cookies in a dedicated file
772 +touch('google.txt');
773 +$r->setOptions(
774 + array( 'cookiestore' => 'google.txt',
775 + )
776 +);
777 +
778 +$r->setQueryData(
779 + array( 'q' => '+"pecl_http" -msg -cvs -list',
780 + 'hl' => 'de'
781 + )
782 +);
783 +
784 +// HttpRequest::send() returns an HttpMessage object
785 +// of type HttpMessage::TYPE_RESPONSE or throws an exception
786 +try {
787 + print $r->send()->getBody();
788 +} catch (HttpException $e) {
789 + print $e;
790 +}
791 +?>
792 +
793 +- Multipart Posts
794 +
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
799 + redirect option.
800 +
801 +<?php
802 +$r = new HttpRequest('http://dev.iworks.at/.print_request.php', HTTP_METH_POST);
803 +
804 +// if redirects is set to true, a single redirect is allowed;
805 +// one can set any reasonable count of allowed redirects
806 +$r->setOptions(
807 + array( 'cookies' => array('MyCookie' => 'has a value'),
808 + 'redirect' => true,
809 + )
810 +);
811 +
812 +// common form data
813 +$r->setPostFields(
814 + array( 'name' => 'Mike',
815 + 'mail' => 'mike@php.net',
816 + )
817 +);
818 +// add the file to post (form name, file name, file type)
819 +touch('profile.jpg');
820 +$r->addPostFile('image', 'profile.jpg', 'image/jpeg');
821 +
822 +try {
823 + print $r->send()->getBody();
824 +} catch (HttpException $e) {
825 + print $e;
826 +}
827 +?>
828 +
829 +- Parallel Requests
830 +
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
834 + at the same time.
835 +
836 +<?php
837 +try {
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) {
844 + print $e;
845 + exit;
846 +}
847 +
848 +try {
849 + $p->send();
850 + // HttpRequestPool implements an iterator over attached HttpRequest objects
851 + foreach ($p as $r) {
852 + echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
853 + }
854 +} catch (HttpException $e) {
855 + print $e;
856 +}
857 +?>
858 +
859 +- Parallel Requests?
860 +
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.
864 +
865 +<?php
866 +class Pool extends HttpRequestPool
867 +{
868 + public function __construct()
869 + {
870 + parent::__construct(
871 + new HttpRequest('http://pear.php.net', HTTP_METH_HEAD),
872 + new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD)
873 + );
874 +
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!");
883 + }
884 + }
885 + print "\nDone!\n";
886 + }
887 +}
888 +
889 +try {
890 + foreach (new Pool as $r) {
891 + echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n";
892 + }
893 +} catch (HttpException $ex) {
894 + print $e;
895 +}
896 +?>
897 +
898 +- Cached Responses
899 +
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.
905 +
906 +<?php
907 +HttpResponse::setCacheControl('public');
908 +HttpResponse::setCache(true);
909 +HttpResponse::capture();
910 +
911 +print "This will be cached until content changes!\n";
912 +print "Note that this approach will only save the clients download time.\n";
913 +?>
914 +
915 +- Bandwidth Throttling
916 +
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.
920 +
921 +<?php
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();
929 +?>
930 --- /dev/null
931 +++ b/ext/http/docs/http.ini
932 @@ -0,0 +1,61 @@
933 +; example INI file for pecl/http
934 +; $Id: http.ini 229420 2007-02-09 14:19:40Z mike $
935 +
936 +[http]
937 +; enable if you want to transform all errors to exceptions (PHP >= 5 only)
938 +;http.only_exceptions = 1
939 +
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
943 +
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
947 +
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"
952 +
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"
958 +
959 +; custom request methods
960 +;http.request.methods.custom = "KICK, BANN"
961 +
962 +; log file for positive cache hits
963 +;http.log.cache =
964 +
965 +; log file for redirects
966 +;http.log.redirect =
967 +
968 +; log file for responses with http_send_file() etc. where the file's not been found
969 +;http.log.not_found =
970 +
971 +; log file for requests with an unallowed request method
972 +;http.log.allowed_methods =
973 +
974 +; composite log file (i.e. log all messages to this file)
975 +;http.log.composite =
976 +
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
980 +
981 +; automatically inflate sent content
982 +;http.send.inflate.start_auto = 0
983 +;http.send.inflate.start_flags =
984 +
985 +; global HttpRequestDataShare settings
986 +;http.request.datashare.cookie = 0
987 +;http.request.datashare.dns = 1
988 +
989 +; limit of idle persistent handles per provider
990 +;http.persistent.handles.limit = -1
991 +
992 +; default ident of persistent handles
993 +;http.persistent.handles.ident = "GLOBAL"
994 --- /dev/null
995 +++ b/ext/http/http.c
996 @@ -0,0 +1,546 @@
997 +/*
998 + +--------------------------------------------------------------------+
999 + | PECL :: http |
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 + +--------------------------------------------------------------------+
1007 +*/
1008 +
1009 +/* $Id: http.c 300300 2010-06-09 07:29:35Z mike $ */
1010 +
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"
1017 +
1018 +#include "php_ini.h"
1019 +#include "ext/standard/info.h"
1020 +#include "zend_extensions.h"
1021 +
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"
1035 +
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"
1046 +
1047 +ZEND_DECLARE_MODULE_GLOBALS(http);
1048 +HTTP_DECLARE_ARG_PASS_INFO();
1049 +
1050 +#ifdef COMPILE_DL_HTTP
1051 +ZEND_GET_MODULE(http)
1052 +#endif
1053 +
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)
1061 +#endif
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)
1102 +#endif
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)
1113 +#endif
1114 + PHP_FE(http_support, NULL)
1115 +
1116 + EMPTY_FUNCTION_ENTRY
1117 +};
1118 +/* }}} */
1119 +
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);
1125 +
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")
1131 +# endif
1132 +# ifdef HTTP_HAVE_HASH
1133 + ZEND_MOD_REQUIRED("hash")
1134 +# endif
1135 +# ifdef HTTP_HAVE_SESSION
1136 + ZEND_MOD_REQUIRED("session")
1137 +# endif
1138 +# ifdef HTTP_HAVE_ICONV
1139 + ZEND_MOD_REQUIRED("iconv")
1140 +# endif
1141 +# ifdef HTTP_HAVE_EVENT
1142 + ZEND_MOD_CONFLICTS("event")
1143 +#endif
1144 + {NULL, NULL, NULL, 0}
1145 +};
1146 +#endif
1147 +/* }}} */
1148 +
1149 +/* {{{ http_module_entry */
1150 +zend_module_entry http_module_entry = {
1151 +#if ZEND_EXTENSION_API_NO >= 220050617
1152 + STANDARD_MODULE_HEADER_EX, NULL,
1153 + http_module_deps,
1154 +#else
1155 + STANDARD_MODULE_HEADER,
1156 +#endif
1157 + "http",
1158 + http_functions,
1159 + PHP_MINIT(http),
1160 + PHP_MSHUTDOWN(http),
1161 + PHP_RINIT(http),
1162 + PHP_RSHUTDOWN(http),
1163 + PHP_MINFO(http),
1164 + PHP_HTTP_VERSION,
1165 + STANDARD_MODULE_PROPERTIES
1166 +};
1167 +/* }}} */
1168 +
1169 +int http_module_number;
1170 +
1171 +/* {{{ http_globals */
1172 +static void http_globals_init_once(zend_http_globals *G)
1173 +{
1174 + memset(G, 0, sizeof(zend_http_globals));
1175 +}
1176 +
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)
1179 +{
1180 +#ifdef HTTP_HAVE_SAPI_RTIME
1181 + G->request.time = sapi_get_request_time(TSRMLS_C);
1182 +#else
1183 + G->request.time = time(NULL);
1184 +#endif
1185 + G->send.buffer_size = 0;
1186 + G->read_post_data = 0;
1187 +}
1188 +
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)
1191 +{
1192 + if (G->request.headers) {
1193 + zend_hash_destroy(G->request.headers);
1194 + FREE_HASHTABLE(G->request.headers);
1195 + G->request.headers = NULL;
1196 + }
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;
1202 + }
1203 +}
1204 +
1205 +#if defined(ZTS) && defined(PHP_DEBUG)
1206 +#if ZTS && PHP_DEBUG
1207 +zend_http_globals *http_globals(void)
1208 +{
1209 + TSRMLS_FETCH();
1210 + return HTTP_G;
1211 +}
1212 +#endif
1213 +#endif
1214 +/* }}} */
1215 +
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)
1219 +{
1220 + if (*methods && SG(request_info).request_method) {
1221 + if (SUCCESS != http_check_method_ex(SG(request_info).request_method, methods)) {
1222 + char *header;
1223 + spprintf(&header, 0, "Allow: %s", methods);
1224 + http_exit(405, header);
1225 + }
1226 + }
1227 +}
1228 +/* }}} */
1229 +
1230 +/* {{{ PHP_INI */
1231 +PHP_INI_MH(http_update_allowed_methods)
1232 +{
1233 + if (*new_value) {
1234 + http_check_allowed_methods(new_value);
1235 + }
1236 + return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
1237 +}
1238 +PHP_INI_MH(http_update_persistent_handle_ident)
1239 +{
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);
1242 +}
1243 +
1244 +#ifndef ZEND_ENGINE_2
1245 +# define OnUpdateLong OnUpdateInt
1246 +#endif
1247 +
1248 +PHP_INI_BEGIN()
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)
1262 +#endif
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)
1268 +#endif
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)
1274 +#endif
1275 + HTTP_PHP_INI_ENTRY("http.force_exit", "1", PHP_INI_ALL, OnUpdateBool, force_exit)
1276 +PHP_INI_END()
1277 +/* }}} */
1278 +
1279 +/* {{{ PHP_MINIT_FUNCTION */
1280 +PHP_MINIT_FUNCTION(http)
1281 +{
1282 + http_module_number = module_number;
1283 + ZEND_INIT_MODULE_GLOBALS(http, http_globals_init_once, NULL);
1284 + REGISTER_INI_ENTRIES();
1285 +
1286 + if (0
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)
1291 +#endif
1292 +#ifdef HTTP_HAVE_CURL
1293 + || SUCCESS != PHP_MINIT_CALL(http_request)
1294 +# ifdef ZEND_ENGINE_2
1295 +# endif
1296 +#endif
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)
1301 +
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)
1308 +# endif
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)
1317 +# endif
1318 +# ifndef WONKY
1319 + || SUCCESS != PHP_MINIT_CALL(http_response_object)
1320 +# endif
1321 + || SUCCESS != PHP_MINIT_CALL(http_util_object)
1322 +#endif
1323 + ) {
1324 + return FAILURE;
1325 + }
1326 +
1327 + return SUCCESS;
1328 +}
1329 +/* }}} */
1330 +
1331 +/* {{{ PHP_MSHUTDOWN_FUNCTION */
1332 +PHP_MSHUTDOWN_FUNCTION(http)
1333 +{
1334 + UNREGISTER_INI_ENTRIES();
1335 +
1336 + if (0
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)
1341 +# endif
1342 +#endif
1343 + || SUCCESS != PHP_MSHUTDOWN_CALL(http_message_object)
1344 + || SUCCESS != PHP_MSHUTDOWN_CALL(http_persistent_handle) /* last */
1345 + ) {
1346 + return FAILURE;
1347 + }
1348 +
1349 + return SUCCESS;
1350 +}
1351 +/* }}} */
1352 +
1353 +/* {{{ PHP_RINIT_FUNCTION */
1354 +PHP_RINIT_FUNCTION(http)
1355 +{
1356 + http_globals_init(HTTP_G);
1357 +
1358 + if (HTTP_G->request.methods.allowed && *HTTP_G->request.methods.allowed) {
1359 + http_check_allowed_methods(HTTP_G->request.methods.allowed);
1360 + }
1361 +
1362 + if (0
1363 +#ifdef HTTP_HAVE_ZLIB
1364 + || SUCCESS != PHP_RINIT_CALL(http_encoding)
1365 +#endif
1366 +#ifdef HTTP_HAVE_CURL
1367 +# ifdef ZEND_ENGINE_2
1368 +# ifdef HTTP_HAVE_EVENT
1369 + || SUCCESS != PHP_RINIT_CALL(http_request_pool)
1370 +# endif
1371 + || SUCCESS != PHP_RINIT_CALL(http_request_datashare)
1372 +# endif
1373 +#endif
1374 + || SUCCESS != PHP_RINIT_CALL(http_request_method)
1375 + ) {
1376 + return FAILURE;
1377 + }
1378 +
1379 + return SUCCESS;
1380 +}
1381 +/* }}} */
1382 +
1383 +/* {{{ PHP_RSHUTDOWN_FUNCTION */
1384 +PHP_RSHUTDOWN_FUNCTION(http)
1385 +{
1386 + STATUS status = SUCCESS;
1387 +
1388 + if (0
1389 +#ifdef HTTP_HAVE_ZLIB
1390 + || SUCCESS != PHP_RSHUTDOWN_CALL(http_encoding)
1391 +#endif
1392 +#ifdef HTTP_HAVE_CURL
1393 +# ifdef ZEND_ENGINE_2
1394 + || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_datashare)
1395 +# endif
1396 +#endif
1397 + || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_method)
1398 + ) {
1399 + status = FAILURE;
1400 + }
1401 +
1402 + http_globals_free(HTTP_G);
1403 + return status;
1404 +}
1405 +/* }}} */
1406 +
1407 +/* {{{ PHP_MINFO_FUNCTION */
1408 +PHP_MINFO_FUNCTION(http)
1409 +{
1410 + php_info_print_table_start();
1411 + {
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
1416 + "none"
1417 +#else
1418 + "HttpUtil, "
1419 + "HttpMessage, "
1420 +# ifdef HTTP_HAVE_CURL
1421 + "HttpRequest, "
1422 + "HttpRequestPool, "
1423 + "HttpRequestDataShare, "
1424 +# endif
1425 +# ifdef HTTP_HAVE_ZLIB
1426 + "HttpDeflateStream, "
1427 + "HttpInflateStream, "
1428 +# endif
1429 +# ifndef WONKY
1430 + "HttpResponse, "
1431 +# endif
1432 + "HttpQueryString"
1433 +#endif
1434 + );
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
1438 + "none"
1439 +#else
1440 + "http.chunked_decode, http.chunked_encode, http.deflate, http.inflate"
1441 +#endif
1442 + );
1443 + }
1444 + php_info_print_table_end();
1445 +
1446 + php_info_print_table_start();
1447 + php_info_print_table_header(3, "Used Library", "Compiled", "Linked");
1448 + {
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);
1452 +#else
1453 + php_info_print_table_row(2, "libcurl", "disabled", "disabled");
1454 +#endif
1455 +#ifdef HTTP_HAVE_EVENT
1456 + php_info_print_table_row(3, "libevent", HTTP_EVENT_VERSION, event_get_version());
1457 +#else
1458 + php_info_print_table_row(3, "libevent", "disabled", "disabled");
1459 +#endif
1460 +#ifdef HTTP_HAVE_ZLIB
1461 + php_info_print_table_row(3, "libz", ZLIB_VERSION, zlibVersion());
1462 +#else
1463 + php_info_print_table_row(3, "libz", "disabled", "disabled");
1464 +#endif
1465 +#if defined(HTTP_HAVE_MAGIC)
1466 + php_info_print_table_row(3, "libmagic", "unknown", "unknown");
1467 +#else
1468 + php_info_print_table_row(3, "libmagic", "disabled", "disabled");
1469 +#endif
1470 + }
1471 + php_info_print_table_end();
1472 +
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");
1476 + {
1477 + HashTable *ht;
1478 + HashPosition pos1, pos2;
1479 + HashKey provider = initHashKey(0), ident = initHashKey(0);
1480 + zval **val, **sub, **zused, **zfree;
1481 +
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);
1493 + } else {
1494 + php_info_print_table_row(4, provider.str, ident.str, "0", "0");
1495 + }
1496 + }
1497 + } else {
1498 + php_info_print_table_row(4, provider.str, "N/A", "0", "0");
1499 + }
1500 + }
1501 + } else {
1502 + php_info_print_table_row(4, "N/A", "N/A", "0", "0");
1503 + }
1504 + if (ht) {
1505 + zend_hash_destroy(ht);
1506 + FREE_HASHTABLE(ht);
1507 + }
1508 + }
1509 + php_info_print_table_end();
1510 +
1511 + php_info_print_table_start();
1512 + php_info_print_table_colspan_header(2, "Request Methods");
1513 + {
1514 + HashPosition pos;
1515 + phpstr *methods = phpstr_new();
1516 + char **name;
1517 +
1518 + FOREACH_HASH_VAL(pos, &HTTP_G->request.methods.registered, name) {
1519 + if (pos->h) {
1520 + phpstr_appendf(methods, "%s, ", *name);
1521 + }
1522 + }
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);
1527 + }
1528 + php_info_print_table_end();
1529 +
1530 + DISPLAY_INI_ENTRIES();
1531 +}
1532 +/* }}} */
1533 +
1534 +/*
1535 + * Local variables:
1536 + * tab-width: 4
1537 + * c-basic-offset: 4
1538 + * End:
1539 + * vim600: noet sw=4 ts=4 fdm=marker
1540 + * vim<600: noet sw=4 ts=4
1541 + */
1542 +
1543 --- /dev/null
1544 +++ b/ext/http/http.dsp
1545 @@ -0,0 +1,257 @@
1546 +# Microsoft Developer Studio Project File - Name="http" - Package Owner=<4>
1547 +# Microsoft Developer Studio Generated Build File, Format Version 6.00
1548 +# ** DO NOT EDIT **
1549 +
1550 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
1551 +
1552 +CFG=http - Win32 Release_TS
1553 +!MESSAGE This is not a valid makefile. To build this project using NMAKE,
1554 +!MESSAGE use the Export Makefile command and run
1555 +!MESSAGE
1556 +!MESSAGE NMAKE /f "http.mak".
1557 +!MESSAGE
1558 +!MESSAGE You can specify a configuration when running NMAKE
1559 +!MESSAGE by defining the macro CFG on the command line. For example:
1560 +!MESSAGE
1561 +!MESSAGE NMAKE /f "http.mak" CFG="http - Win32 Release_TS"
1562 +!MESSAGE
1563 +!MESSAGE Possible choices for configuration are:
1564 +!MESSAGE
1565 +!MESSAGE "http - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
1566 +!MESSAGE "http - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
1567 +!MESSAGE
1568 +
1569 +# Begin Project
1570 +# PROP AllowPerConfigDependencies 0
1571 +# PROP Scc_ProjName ""
1572 +# PROP Scc_LocalPath ""
1573 +CPP=cl.exe
1574 +MTL=midl.exe
1575 +RSC=rc.exe
1576 +
1577 +!IF "$(CFG)" == "http - Win32 Release_TS"
1578 +
1579 +# PROP BASE Use_MFC 0
1580 +# PROP BASE Use_Debug_Libraries 0
1581 +# PROP BASE Output_Dir "Release_TS"
1582 +# PROP BASE Intermediate_Dir "Release_TS"
1583 +# PROP BASE Ignore_Export_Lib 0
1584 +# PROP BASE Target_Dir ""
1585 +# PROP Use_MFC 0
1586 +# PROP Use_Debug_Libraries 0
1587 +# PROP Output_Dir "Release_TS"
1588 +# PROP Intermediate_Dir "Release_TS"
1589 +# PROP Ignore_Export_Lib 0
1590 +# PROP Target_Dir ""
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
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
1593 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
1594 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
1595 +# ADD BASE RSC /l 0x406 /d "NDEBUG"
1596 +# ADD RSC /l 0x406 /d "NDEBUG"
1597 +BSC32=bscmake.exe
1598 +# ADD BASE BSC32 /nologo
1599 +# ADD BSC32 /nologo
1600 +LINK32=link.exe
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
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"
1603 +
1604 +!ELSEIF "$(CFG)" == "http - Win32 Debug_TS"
1605 +
1606 +# PROP BASE Use_MFC 0
1607 +# PROP BASE Use_Debug_Libraries 0
1608 +# PROP BASE Output_Dir "Debug_TS"
1609 +# PROP BASE Intermediate_Dir "Debug_TS"
1610 +# PROP BASE Ignore_Export_Lib 0
1611 +# PROP BASE Target_Dir ""
1612 +# PROP Use_MFC 0
1613 +# PROP Use_Debug_Libraries 0
1614 +# PROP Output_Dir "Debug_TS"
1615 +# PROP Intermediate_Dir "Debug_TS"
1616 +# PROP Ignore_Export_Lib 0
1617 +# PROP Target_Dir ""
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
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
1620 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
1621 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
1622 +# ADD BASE RSC /l 0x406 /d "NDEBUG"
1623 +# ADD RSC /l 0x406 /d "NDEBUG"
1624 +BSC32=bscmake.exe
1625 +# ADD BASE BSC32 /nologo
1626 +# ADD BSC32 /nologo
1627 +LINK32=link.exe
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
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"
1630 +
1631 +!ENDIF
1632 +
1633 +# Begin Target
1634 +
1635 +# Name "http - Win32 Release_TS"
1636 +# Name "http - Win32 Debug_TS"
1637 +# Begin Group "Source Files"
1638 +
1639 +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
1640 +# Begin Source File
1641 +
1642 +SOURCE=.\http.c
1643 +# End Source File
1644 +# Begin Source File
1645 +
1646 +SOURCE=.\http_api.c
1647 +# End Source File
1648 +# Begin Source File
1649 +
1650 +SOURCE=.\http_encoding_api.c
1651 +# End Source File
1652 +# Begin Source File
1653 +
1654 +SOURCE=.\http_request_api.c
1655 +# End Source File
1656 +# Begin Source File
1657 +
1658 +SOURCE=.\http_request_info.c
1659 +# End Source File
1660 +# Begin Source File
1661 +
1662 +SOURCE=.\http_request_body_api.c
1663 +# End Source File
1664 +# Begin Source File
1665 +
1666 +SOURCE=.\http_request_method_api.c
1667 +# End Source File
1668 +# Begin Source File
1669 +
1670 +SOURCE=.\http_functions.c
1671 +# End Source File
1672 +# Begin Source File
1673 +
1674 +SOURCE=.\http_persistent_handle_api.c
1675 +# End Source File
1676 +# Begin Source File
1677 +
1678 +SOURCE=.\http_cache_api.c
1679 +# End Source File
1680 +# Begin Source File
1681 +
1682 +SOURCE=.\http_cookie_api.c
1683 +# End Source File
1684 +# Begin Source File
1685 +
1686 +SOURCE=.\http_date_api.c
1687 +# End Source File
1688 +# Begin Source File
1689 +
1690 +SOURCE=.\http_headers_api.c
1691 +# End Source File
1692 +# Begin Source File
1693 +
1694 +SOURCE=.\http_message_api.c
1695 +# End Source File
1696 +# Begin Source File
1697 +
1698 +SOURCE=.\http_send_api.c
1699 +# End Source File
1700 +# Begin Source File
1701 +
1702 +SOURCE=.\http_url_api.c
1703 +# End Source File
1704 +# Begin Source File
1705 +
1706 +SOURCE=.\http_querystring_api.c
1707 +# End Source File
1708 +# Begin Source File
1709 +
1710 +SOURCE=.\http_info_api.c
1711 +# End Source File
1712 +# Begin Source File
1713 +
1714 +SOURCE=.\phpstr\phpstr.c
1715 +# End Source File
1716 +# End Group
1717 +# Begin Group "Header Files"
1718 +
1719 +# PROP Default_Filter "h;hpp;hxx;hm;inl"
1720 +# Begin Source File
1721 +
1722 +SOURCE=.\php_http.h
1723 +# End Source File
1724 +# Begin Source File
1725 +
1726 +SOURCE=.\php_http_api.h
1727 +# End Source File
1728 +# Begin Source File
1729 +
1730 +SOURCE=.\php_http_encoding_api.h
1731 +# End Source File
1732 +# Begin Source File
1733 +
1734 +SOURCE=.\php_http_request_api.h
1735 +# End Source File
1736 +# Begin Source File
1737 +
1738 +SOURCE=.\php_http_request_int.h
1739 +# End Source File
1740 +# Begin Source File
1741 +
1742 +SOURCE=.\php_http_request_body_api.h
1743 +# End Source File
1744 +# Begin Source File
1745 +
1746 +SOURCE=.\php_http_request_method_api.h
1747 +# End Source File
1748 +# Begin Source File
1749 +
1750 +SOURCE=.\php_http_persistent_handle_api.h
1751 +# End Source File
1752 +# Begin Source File
1753 +
1754 +SOURCE=.\php_http_cache_api.h
1755 +# End Source File
1756 +# Begin Source File
1757 +
1758 +SOURCE=.\php_http_cookie_api.h
1759 +# End Source File
1760 +# Begin Source File
1761 +
1762 +SOURCE=.\php_http_date_api.h
1763 +# End Source File
1764 +# Begin Source File
1765 +
1766 +SOURCE=.\php_http_message_api.h
1767 +# End Source File
1768 +# Begin Source File
1769 +
1770 +SOURCE=.\php_http_send_api.h
1771 +# End Source File
1772 +# Begin Source File
1773 +
1774 +SOURCE=.\php_http_headers_api.h
1775 +# End Source File
1776 +# Begin Source File
1777 +
1778 +SOURCE=.\php_http_url_api.h
1779 +# End Source File
1780 +# Begin Source File
1781 +
1782 +SOURCE=.\php_http_querystring_api.h
1783 +# End Source File
1784 +# Begin Source File
1785 +
1786 +SOURCE=.\php_http_info_api.h
1787 +# End Source File
1788 +# Begin Source File
1789 +
1790 +SOURCE=.\php_http_std_defs.h
1791 +# End Source File
1792 +# Begin Source File
1793 +
1794 +SOURCE=.\phpstr\phpstr.h
1795 +# End Source File
1796 +# End Group
1797 +# Begin Group "Resource Files"
1798 +
1799 +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
1800 +# End Group
1801 +# End Target
1802 +# End Project
1803 --- /dev/null
1804 +++ b/ext/http/http_api.c
1805 @@ -0,0 +1,754 @@
1806 +/*
1807 + +--------------------------------------------------------------------+
1808 + | PECL :: http |
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 + +--------------------------------------------------------------------+
1816 +*/
1817 +
1818 +/* $Id: http_api.c 323405 2012-02-21 10:05:05Z mike $ */
1819 +
1820 +#define HTTP_WANT_SAPI
1821 +#include "php_http.h"
1822 +
1823 +#include "php_output.h"
1824 +#include "ext/standard/url.h"
1825 +#include "ext/standard/php_lcg.h"
1826 +
1827 +#include "php_http_api.h"
1828 +#include "php_http_send_api.h"
1829 +
1830 +#ifdef ZEND_ENGINE_2
1831 +# include "php_http_exception_object.h"
1832 +#endif
1833 +
1834 +PHP_MINIT_FUNCTION(http_support)
1835 +{
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);
1842 +
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);
1847 +
1848 + return SUCCESS;
1849 +}
1850 +
1851 +PHP_HTTP_API long _http_support(long feature)
1852 +{
1853 + long support = HTTP_SUPPORT;
1854 +
1855 +#ifdef HTTP_HAVE_CURL
1856 + support |= HTTP_SUPPORT_REQUESTS;
1857 +# ifdef HTTP_HAVE_SSL
1858 + support |= HTTP_SUPPORT_SSLREQUESTS;
1859 +# endif
1860 +# ifdef HTTP_HAVE_EVENT
1861 + support |= HTTP_SUPPORT_EVENTS;
1862 +# endif
1863 +#endif
1864 +#ifdef HTTP_HAVE_MAGIC
1865 + support |= HTTP_SUPPORT_MAGICMIME;
1866 +#endif
1867 +#ifdef HTTP_HAVE_ZLIB
1868 + support |= HTTP_SUPPORT_ENCODINGS;
1869 +#endif
1870 +
1871 + if (feature) {
1872 + return (feature == (support & feature));
1873 + }
1874 + return support;
1875 +}
1876 +
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)
1879 +{
1880 + size_t i;
1881 + int wasalpha;
1882 +
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]));
1886 + }
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]));
1890 + wasalpha = 1;
1891 + } else {
1892 + if (xhyphen && (key[i] == '_')) {
1893 + key[i] = '-';
1894 + }
1895 + wasalpha = 0;
1896 + }
1897 + }
1898 + }
1899 + return key;
1900 +}
1901 +/* }}} */
1902 +
1903 +/* {{{ http_boundary(char *, size_t) */
1904 +size_t _http_boundary(char *buf, size_t buf_len TSRMLS_DC)
1905 +{
1906 + return snprintf(buf, buf_len, "%lu%0.9f", (ulong) HTTP_G->request.time, (float) php_combined_lcg(TSRMLS_C));
1907 +}
1908 +/* }}} */
1909 +
1910 +/* {{{ void http_error(long, long, char*) */
1911 +void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...)
1912 +{
1913 + va_list args;
1914 +
1915 + va_start(args, format);
1916 +#ifdef ZEND_ENGINE_2
1917 + if ((type == E_THROW) || (GLOBAL_ERROR_HANDLING == EH_THROW)) {
1918 + char *message;
1919 + zend_class_entry *ce = http_exception_get_for_code(code);
1920 +
1921 + http_try {
1922 + vspprintf(&message, 0, format, args);
1923 + zend_throw_exception(ce, message, code TSRMLS_CC);
1924 + efree(message);
1925 + } http_catch(GLOBAL_EXCEPTION_CLASS ? GLOBAL_EXCEPTION_CLASS : HTTP_EX_DEF_CE);
1926 + } else
1927 +#endif
1928 + php_verror(NULL, "", type, format, args TSRMLS_CC);
1929 + va_end(args);
1930 +}
1931 +/* }}} */
1932 +
1933 +#ifdef ZEND_ENGINE_2
1934 +static inline void copy_bt_args(zval *from, zval *to TSRMLS_DC)
1935 +{
1936 + zval **args, **trace_0, *old_trace_0, *trace = NULL;
1937 +
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);
1946 + }
1947 + }
1948 + }
1949 + }
1950 + }
1951 +}
1952 +
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)
1955 +{
1956 + int inner = 1;
1957 + char *message;
1958 + zval *sub_exception, *tmp_exception;
1959 +
1960 + if (!new_exception) {
1961 + MAKE_STD_ZVAL(new_exception);
1962 + object_init_ex(new_exception, ce);
1963 +
1964 + zend_update_property(ce, new_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC);
1965 + copy_bt_args(old_exception, new_exception TSRMLS_CC);
1966 +
1967 + sub_exception = old_exception;
1968 +
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) {
1970 + ++inner;
1971 + }
1972 +
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);
1975 + efree(message);
1976 + } else {
1977 + sub_exception = new_exception;
1978 + tmp_exception = new_exception;
1979 +
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;
1982 + }
1983 +
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);
1987 + }
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);
1991 +#endif
1992 + zval_ptr_dtor(&old_exception);
1993 + return new_exception;
1994 +}
1995 +/* }}} */
1996 +
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)
1999 +{
2000 + zend_class_entry *ce = parent_ce;
2001 +
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))) {
2004 + return FAILURE;
2005 + }
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);
2008 + return FAILURE;
2009 + }
2010 + }
2011 +
2012 + *ov = create(ce, intern_ptr, obj_ptr TSRMLS_CC);
2013 + return SUCCESS;
2014 +}
2015 +/* }}} */
2016 +#endif /* ZEND_ENGINE_2 */
2017 +
2018 +/* {{{ void http_log(char *, char *, char *) */
2019 +void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC)
2020 +{
2021 + time_t now;
2022 + struct tm nowtm;
2023 + char datetime[20] = {0};
2024 +
2025 + now = HTTP_G->request.time;
2026 + strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", php_localtime_r(&now, &nowtm));
2027 +
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); \
2031 + \
2032 + if (log) { \
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); \
2035 + } \
2036 + \
2037 + }
2038 +
2039 + HTTP_LOG_WRITE(file, ident, message);
2040 + HTTP_LOG_WRITE(HTTP_G->log.composite, ident, message);
2041 +}
2042 +/* }}} */
2043 +
2044 +static void http_ob_blackhole(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
2045 +{
2046 + *handled_output = ecalloc(1,1);
2047 + *handled_output_len = 0;
2048 +}
2049 +
2050 +/* {{{ STATUS http_exit(int, char*, char*) */
2051 +STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC)
2052 +{
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));
2056 + STR_FREE(header);
2057 + STR_FREE(body);
2058 + return FAILURE;
2059 + }
2060 +
2061 +#ifndef PHP_OUTPUT_NEWAPI
2062 + if (!OG(ob_lock) &&
2063 + !php_ob_handler_used("zlib output compression" TSRMLS_CC) && !php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) {
2064 + php_end_ob_buffers(0 TSRMLS_CC);
2065 + }
2066 +#endif
2067 +
2068 + if ((SUCCESS == sapi_send_headers(TSRMLS_C)) && body) {
2069 + PHPWRITE(body, strlen(body));
2070 + }
2071 +
2072 + switch (status) {
2073 + case 301: http_log(HTTP_G->log.redirect, "301-REDIRECT", header); break;
2074 + case 302: http_log(HTTP_G->log.redirect, "302-REDIRECT", header); break;
2075 + case 303: http_log(HTTP_G->log.redirect, "303-REDIRECT", header); break;
2076 + case 305: http_log(HTTP_G->log.redirect, "305-REDIRECT", header); break;
2077 + case 307: http_log(HTTP_G->log.redirect, "307-REDIRECT", header); break;
2078 + case 304: http_log(HTTP_G->log.cache, "304-CACHE", header); break;
2079 + case 404: http_log(HTTP_G->log.not_found, "404-NOTFOUND", NULL); break;
2080 + case 405: http_log(HTTP_G->log.allowed_methods, "405-ALLOWED", header); break;
2081 + default: http_log(NULL, header, body); break;
2082 + }
2083 +
2084 + STR_FREE(header);
2085 + STR_FREE(body);
2086 +
2087 + if (HTTP_G->force_exit) {
2088 + zend_bailout();
2089 + } else {
2090 +#ifdef PHP_OUTPUT_NEWAPI
2091 + php_output_start_devnull(TSRMLS_C);
2092 +#else
2093 + php_ob_set_internal_handler(http_ob_blackhole, 4096, "blackhole", 0 TSRMLS_CC);
2094 +#endif
2095 + }
2096 +
2097 + return SUCCESS;
2098 +}
2099 +/* }}} */
2100 +
2101 +/* {{{ STATUS http_check_method(char *) */
2102 +STATUS _http_check_method_ex(const char *method, const char *methods)
2103 +{
2104 + const char *found;
2105 +
2106 + if ( (found = strstr(methods, method)) &&
2107 + (found == method || !HTTP_IS_CTYPE(alpha, found[-1])) &&
2108 + (strlen(found) >= strlen(method) && !HTTP_IS_CTYPE(alpha, found[strlen(method)]))) {
2109 + return SUCCESS;
2110 + }
2111 + return FAILURE;
2112 +}
2113 +/* }}} */
2114 +
2115 +/* {{{ zval *http_get_server_var_ex(char *, size_t) */
2116 +PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC)
2117 +{
2118 + zval **hsv, **var;
2119 + char *env;
2120 +
2121 + /* if available, this is a lot faster than accessing $_SERVER */
2122 + if (sapi_module.getenv) {
2123 + if ((!(env = sapi_module.getenv((char *) key, key_len TSRMLS_CC))) || (check && !*env)) {
2124 + return NULL;
2125 + }
2126 + if (HTTP_G->server_var) {
2127 + zval_ptr_dtor(&HTTP_G->server_var);
2128 + }
2129 + MAKE_STD_ZVAL(HTTP_G->server_var);
2130 + ZVAL_STRING(HTTP_G->server_var, env, 1);
2131 + return HTTP_G->server_var;
2132 + }
2133 +
2134 +#ifdef ZEND_ENGINE_2
2135 + zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
2136 +#endif
2137 +
2138 + if ((SUCCESS != zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) {
2139 + return NULL;
2140 + }
2141 + if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(hsv), HTTP_ZAPI_CONST_CAST(char *) key, key_len + 1, (void *) &var))) {
2142 + return NULL;
2143 + }
2144 + if (check && !((Z_TYPE_PP(var) == IS_STRING) && Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
2145 + return NULL;
2146 + }
2147 + return *var;
2148 +}
2149 +/* }}} */
2150 +
2151 +/* {{{ STATUS http_get_request_body(char **, size_t *) */
2152 +PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC)
2153 +{
2154 + *length = 0;
2155 + *body = NULL;
2156 +
2157 + if (SG(request_info).raw_post_data) {
2158 + *length = SG(request_info).raw_post_data_length;
2159 + *body = SG(request_info).raw_post_data;
2160 +
2161 + if (dup) {
2162 + *body = estrndup(*body, *length);
2163 + }
2164 + return SUCCESS;
2165 + } else if (sapi_module.read_post && !HTTP_G->read_post_data) {
2166 + char *buf = emalloc(4096);
2167 + int len;
2168 +
2169 + HTTP_G->read_post_data = 1;
2170 +
2171 + while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
2172 + SG(read_post_bytes) += len;
2173 + *body = erealloc(*body, *length + len + 1);
2174 + memcpy(*body + *length, buf, len);
2175 + *length += len;
2176 + (*body)[*length] = '\0';
2177 + if (len < 4096) {
2178 + break;
2179 + }
2180 + }
2181 + efree(buf);
2182 +
2183 + /* check for error */
2184 + if (len < 0) {
2185 + STR_FREE(*body);
2186 + *length = 0;
2187 + return FAILURE;
2188 + }
2189 +
2190 + SG(request_info).raw_post_data = *body;
2191 + SG(request_info).raw_post_data_length = *length;
2192 +
2193 + if (dup) {
2194 + *body = estrndup(*body, *length);
2195 + }
2196 + return SUCCESS;
2197 + }
2198 +
2199 + return FAILURE;
2200 +}
2201 +/* }}} */
2202 +
2203 +/* {{{ php_stream *http_get_request_body_stream(void) */
2204 +PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D)
2205 +{
2206 + php_stream *s = NULL;
2207 +
2208 + if (SG(request_info).raw_post_data) {
2209 + s = php_stream_open_wrapper("php://input", "rb", 0, NULL);
2210 + } else if (sapi_module.read_post && !HTTP_G->read_post_data) {
2211 + HTTP_G->read_post_data = 1;
2212 +
2213 + if ((s = php_stream_temp_new())) {
2214 + char *buf = emalloc(4096);
2215 + int len;
2216 +
2217 + while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
2218 + SG(read_post_bytes) += len;
2219 + php_stream_write(s, buf, len);
2220 + if (len < 4096) {
2221 + break;
2222 + }
2223 + }
2224 + efree(buf);
2225 +
2226 + if (len < 0) {
2227 + php_stream_close(s);
2228 + s = NULL;
2229 + } else {
2230 + php_stream_rewind(s);
2231 + }
2232 + }
2233 + }
2234 +
2235 + return s;
2236 +}
2237 +/* }}} */
2238 +
2239 +/* {{{ void http_parse_params_default_callback(...) */
2240 +PHP_HTTP_API void _http_parse_params_default_callback(void *arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
2241 +{
2242 + char *kdup;
2243 + zval tmp, *entry;
2244 + HashTable *ht = (HashTable *) arg;
2245 +
2246 + if (ht) {
2247 + INIT_ZARR(tmp, ht);
2248 +
2249 + if (vallen) {
2250 + MAKE_STD_ZVAL(entry);
2251 + array_init(entry);
2252 + if (keylen) {
2253 + kdup = estrndup(key, keylen);
2254 + add_assoc_stringl_ex(entry, kdup, keylen + 1, (char *) val, vallen, 1);
2255 + efree(kdup);
2256 + } else {
2257 + add_next_index_stringl(entry, (char *) val, vallen, 1);
2258 + }
2259 + add_next_index_zval(&tmp, entry);
2260 + } else {
2261 + add_next_index_stringl(&tmp, (char *) key, keylen, 1);
2262 + }
2263 + }
2264 +}
2265 +/* }}} */
2266 +
2267 +/* {{{ STATUS http_parse_params(const char *, HashTable *) */
2268 +PHP_HTTP_API STATUS _http_parse_params_ex(const char *param, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC)
2269 +{
2270 +#define ST_QUOTE 1
2271 +#define ST_VALUE 2
2272 +#define ST_KEY 3
2273 +#define ST_ASSIGN 4
2274 +#define ST_ADD 5
2275 +
2276 + int st = ST_KEY, keylen = 0, vallen = 0;
2277 + char *s, *c, *key = NULL, *val = NULL;
2278 +
2279 + for(c = s = estrdup(param);;) {
2280 + continued:
2281 +#if 0
2282 + {
2283 + char *tk = NULL, *tv = NULL;
2284 +
2285 + if (key) {
2286 + if (keylen) {
2287 + tk= estrndup(key, keylen);
2288 + } else {
2289 + tk = ecalloc(1, 7);
2290 + memcpy(tk, key, 3);
2291 + tk[3]='.'; tk[4]='.'; tk[5]='.';
2292 + }
2293 + }
2294 + if (val) {
2295 + if (vallen) {
2296 + tv = estrndup(val, vallen);
2297 + } else {
2298 + tv = ecalloc(1, 7);
2299 + memcpy(tv, val, 3);
2300 + tv[3]='.'; tv[4]='.'; tv[5]='.';
2301 + }
2302 + }
2303 + fprintf(stderr, "[%6s] %c \"%s=%s\"\n",
2304 + (
2305 + st == ST_QUOTE ? "QUOTE" :
2306 + st == ST_VALUE ? "VALUE" :
2307 + st == ST_KEY ? "KEY" :
2308 + st == ST_ASSIGN ? "ASSIGN" :
2309 + st == ST_ADD ? "ADD":
2310 + "HUH?"
2311 + ), *c?*c:'0', tk, tv
2312 + );
2313 + STR_FREE(tk); STR_FREE(tv);
2314 + }
2315 +#endif
2316 + switch (st) {
2317 + case ST_QUOTE:
2318 + quote:
2319 + if (*c == '"') {
2320 + if (*(c-1) == '\\') {
2321 + memmove(c-1, c, strlen(c)+1);
2322 + goto quote;
2323 + } else {
2324 + goto add;
2325 + }
2326 + } else {
2327 + if (!val) {
2328 + val = c;
2329 + }
2330 + if (!*c) {
2331 + --val;
2332 + st = ST_ADD;
2333 + }
2334 + }
2335 + break;
2336 +
2337 + case ST_VALUE:
2338 + switch (*c) {
2339 + case '"':
2340 + if (!val) {
2341 + st = ST_QUOTE;
2342 + }
2343 + break;
2344 +
2345 + case ' ':
2346 + break;
2347 +
2348 + case ';':
2349 + case '\0':
2350 + goto add;
2351 + break;
2352 + case ',':
2353 + if (flags & HTTP_PARAMS_ALLOW_COMMA) {
2354 + goto add;
2355 + }
2356 + default:
2357 + if (!val) {
2358 + val = c;
2359 + }
2360 + break;
2361 + }
2362 + break;
2363 +
2364 + case ST_KEY:
2365 + switch (*c) {
2366 + case ',':
2367 + if (flags & HTTP_PARAMS_ALLOW_COMMA) {
2368 + goto allow_comma;
2369 + }
2370 + case '\r':
2371 + case '\n':
2372 + case '\t':
2373 + case '\013':
2374 + case '\014':
2375 + goto failure;
2376 + break;
2377 +
2378 + case ' ':
2379 + if (key) {
2380 + keylen = c - key;
2381 + st = ST_ASSIGN;
2382 + }
2383 + break;
2384 +
2385 + case ';':
2386 + case '\0':
2387 + allow_comma:
2388 + if (key) {
2389 + keylen = c-- - key;
2390 + st = ST_ADD;
2391 + }
2392 + break;
2393 +
2394 + case ':':
2395 + if (!(flags & HTTP_PARAMS_COLON_SEPARATOR)) {
2396 + goto not_separator;
2397 + }
2398 + if (key) {
2399 + keylen = c - key;
2400 + st = ST_VALUE;
2401 + } else {
2402 + goto failure;
2403 + }
2404 + break;
2405 +
2406 + case '=':
2407 + if (flags & HTTP_PARAMS_COLON_SEPARATOR) {
2408 + goto not_separator;
2409 + }
2410 + if (key) {
2411 + keylen = c - key;
2412 + st = ST_VALUE;
2413 + } else {
2414 + goto failure;
2415 + }
2416 + break;
2417 +
2418 + default:
2419 + not_separator:
2420 + if (!key) {
2421 + key = c;
2422 + }
2423 + break;
2424 + }
2425 + break;
2426 +
2427 + case ST_ASSIGN:
2428 + if (*c == '=') {
2429 + st = ST_VALUE;
2430 + } else if (!*c || *c == ';' || ((flags & HTTP_PARAMS_ALLOW_COMMA) && *c == ',')) {
2431 + st = ST_ADD;
2432 + } else if (*c != ' ') {
2433 + goto failure;
2434 + }
2435 + break;
2436 +
2437 + case ST_ADD:
2438 + add:
2439 + if (val) {
2440 + vallen = c - val;
2441 + if (st != ST_QUOTE) {
2442 + while (val[vallen-1] == ' ') --vallen;
2443 + }
2444 + } else {
2445 + val = "";
2446 + vallen = 0;
2447 + }
2448 +
2449 + cb(cb_arg, key, keylen, val, vallen TSRMLS_CC);
2450 +
2451 + st = ST_KEY;
2452 + key = val = NULL;
2453 + keylen = vallen = 0;
2454 + break;
2455 + }
2456 + if (*c) {
2457 + ++c;
2458 + } else if (st == ST_ADD) {
2459 + goto add;
2460 + } else {
2461 + break;
2462 + }
2463 + }
2464 +
2465 + efree(s);
2466 + return SUCCESS;
2467 +
2468 +failure:
2469 + if (flags & HTTP_PARAMS_RAISE_ERROR) {
2470 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Unexpected character (%c) at pos %tu of %zu", *c, c-s, strlen(s));
2471 + }
2472 + if (flags & HTTP_PARAMS_ALLOW_FAILURE) {
2473 + if (st == ST_KEY) {
2474 + if (key) {
2475 + keylen = c - key;
2476 + } else {
2477 + key = c;
2478 + }
2479 + } else {
2480 + --c;
2481 + }
2482 + st = ST_ADD;
2483 + goto continued;
2484 + }
2485 + efree(s);
2486 + return FAILURE;
2487 +}
2488 +/* }}} */
2489 +
2490 +/* {{{ array_join */
2491 +int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
2492 +{
2493 + int flags;
2494 + char *key = NULL;
2495 + HashTable *dst;
2496 + zval **data = NULL, **value = (zval **) pDest;
2497 +
2498 + dst = va_arg(args, HashTable *);
2499 + flags = va_arg(args, int);
2500 +
2501 + if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
2502 + if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
2503 + key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
2504 + zend_hash_find(dst, key, hash_key->nKeyLength, (void *) &data);
2505 + } else {
2506 + zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data);
2507 + }
2508 +
2509 + ZVAL_ADDREF(*value);
2510 + if (data) {
2511 + add_next_index_zval(http_zset(IS_ARRAY, *data), *value);
2512 + } else if (key) {
2513 + zend_hash_add(dst, key, hash_key->nKeyLength, value, sizeof(zval *), NULL);
2514 + } else {
2515 + zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, value, sizeof(zval *), NULL);
2516 + }
2517 +
2518 + if (key) {
2519 + efree(key);
2520 + }
2521 + }
2522 +
2523 + return ZEND_HASH_APPLY_KEEP;
2524 +}
2525 +
2526 +int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
2527 +{
2528 + int flags;
2529 + char *key = NULL;
2530 + HashTable *dst;
2531 + zval **value = (zval **) pDest;
2532 +
2533 + dst = va_arg(args, HashTable *);
2534 + flags = va_arg(args, int);
2535 +
2536 + if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
2537 + ZVAL_ADDREF(*value);
2538 + if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
2539 + key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
2540 + zend_hash_update(dst, key, hash_key->nKeyLength, (void *) value, sizeof(zval *), NULL);
2541 + efree(key);
2542 + } else {
2543 + zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) value, sizeof(zval *), NULL);
2544 + }
2545 + }
2546 +
2547 + return ZEND_HASH_APPLY_KEEP;
2548 +}
2549 +/* }}} */
2550 +
2551 +/*
2552 + * Local variables:
2553 + * tab-width: 4
2554 + * c-basic-offset: 4
2555 + * End:
2556 + * vim600: noet sw=4 ts=4 fdm=marker
2557 + * vim<600: noet sw=4 ts=4
2558 + */
2559 +
2560 --- /dev/null
2561 +++ b/ext/http/http_cache_api.c
2562 @@ -0,0 +1,267 @@
2563 +/*
2564 + +--------------------------------------------------------------------+
2565 + | PECL :: http |
2566 + +--------------------------------------------------------------------+
2567 + | Redistribution and use in source and binary forms, with or without |
2568 + | modification, are permitted provided that the conditions mentioned |
2569 + | in the accompanying LICENSE file are met. |
2570 + +--------------------------------------------------------------------+
2571 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
2572 + +--------------------------------------------------------------------+
2573 +*/
2574 +
2575 +/* $Id: http_cache_api.c 323304 2012-02-17 21:13:24Z mike $ */
2576 +
2577 +#define HTTP_WANT_SAPI
2578 +#include "php_http.h"
2579 +
2580 +#include "php_output.h"
2581 +#include "php_streams.h"
2582 +
2583 +#include "php_http_api.h"
2584 +#include "php_http_cache_api.h"
2585 +#include "php_http_date_api.h"
2586 +#include "php_http_send_api.h"
2587 +
2588 +/* {{{ char *http_etag(void *, size_t, http_send_mode) */
2589 +PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC)
2590 +{
2591 + void *ctx = http_etag_init();
2592 +
2593 + if (data_mode == SEND_DATA) {
2594 + http_etag_update(ctx, data_ptr, data_len);
2595 + } else {
2596 + STATUS ss = FAILURE;
2597 + php_stream_statbuf ssb;
2598 +
2599 + if (data_mode == SEND_RSRC) {
2600 + ss = php_stream_stat((php_stream *) data_ptr, &ssb);
2601 + } else {
2602 + ss = php_stream_stat_path((char *) data_ptr, &ssb);
2603 + }
2604 +
2605 + if (SUCCESS != ss) {
2606 + efree(ctx);
2607 + return NULL;
2608 + } else {
2609 + size_t ssb_len;
2610 + char ssb_buf[128];
2611 +
2612 + ssb_len = snprintf(ssb_buf, sizeof(ssb_buf), "%ld=%ld=%ld", (long) ssb.sb.st_mtime,
2613 + (long) ssb.sb.st_ino,
2614 + (long) ssb.sb.st_size);
2615 + http_etag_update(ctx, ssb_buf, ssb_len);
2616 + }
2617 + }
2618 +
2619 + return http_etag_finish(ctx);
2620 +}
2621 +/* }}} */
2622 +
2623 +/* {{{ time_t http_last_modified(void *, http_send_mode) */
2624 +PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC)
2625 +{
2626 + php_stream_statbuf ssb;
2627 +
2628 + switch (data_mode) {
2629 + case SEND_DATA: return HTTP_G->request.time;
2630 + case SEND_RSRC: return php_stream_stat((php_stream *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime;
2631 + default: return php_stream_stat_path((char *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime;
2632 + }
2633 +}
2634 +/* }}} */
2635 +
2636 +/* {{{ zend_bool http_match_last_modified(char *, time_t) */
2637 +PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC)
2638 +{
2639 + zend_bool retval;
2640 + zval *zmodified;
2641 + char *modified, *chr_ptr;
2642 +
2643 + if (!(zmodified = http_get_server_var(entry, 1))) {
2644 + return !enforce_presence;
2645 + }
2646 +
2647 + modified = estrndup(Z_STRVAL_P(zmodified), Z_STRLEN_P(zmodified));
2648 + if ((chr_ptr = strrchr(modified, ';'))) {
2649 + chr_ptr = 0;
2650 + }
2651 +
2652 + retval = (t <= http_parse_date_ex(modified, 1));
2653 + efree(modified);
2654 + return retval;
2655 +}
2656 +/* }}} */
2657 +
2658 +/* {{{ zend_bool http_match_etag(char *, char *) */
2659 +PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC)
2660 +{
2661 + zval *zetag;
2662 + char *quoted_etag;
2663 + zend_bool result;
2664 +
2665 + if (!(zetag = http_get_server_var_ex(entry, strlen(entry)+1, 1))) {
2666 + return !enforce_presence;
2667 + }
2668 +
2669 + if (NULL != strchr(Z_STRVAL_P(zetag), '*')) {
2670 + return 1;
2671 + }
2672 +
2673 + spprintf(&quoted_etag, 0, "\"%s\"", etag);
2674 + if (!strchr(Z_STRVAL_P(zetag), ',')) {
2675 + result = !strcmp(Z_STRVAL_P(zetag), quoted_etag);
2676 + } else {
2677 + result = (NULL != strstr(Z_STRVAL_P(zetag), quoted_etag));
2678 + }
2679 + efree(quoted_etag);
2680 +
2681 + return result;
2682 +}
2683 +/* }}} */
2684 +
2685 +/* {{{ STATUS http_cache_last_modified(time_t, time_t, char *, size_t) */
2686 +PHP_HTTP_API STATUS _http_cache_last_modified(time_t last_modified,
2687 + time_t send_modified, const char *cache_control, size_t cc_len TSRMLS_DC)
2688 +{
2689 + char *sent_header = NULL;
2690 +
2691 + if (SG(headers_sent)) {
2692 + return FAILURE;
2693 + }
2694 +
2695 + if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
2696 + return FAILURE;
2697 + }
2698 +
2699 + if (SUCCESS != http_send_last_modified_ex(send_modified, &sent_header)) {
2700 + return FAILURE;
2701 + }
2702 +
2703 + if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", last_modified)) {
2704 + http_exit_ex(304, sent_header, NULL, 0);
2705 + } else {
2706 + STR_FREE(sent_header);
2707 + }
2708 +
2709 + return SUCCESS;
2710 +}
2711 +/* }}} */
2712 +
2713 +/* {{{ STATUS http_cache_etag(char *, size_t, char *, size_t) */
2714 +PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len,
2715 + const char *cache_control, size_t cc_len TSRMLS_DC)
2716 +{
2717 + char *sent_header = NULL;
2718 +
2719 + if (SG(headers_sent)) {
2720 + return FAILURE;
2721 + }
2722 +
2723 + if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) {
2724 + return FAILURE;
2725 + }
2726 +
2727 + if (etag_len) {
2728 + if (SUCCESS != http_send_etag_ex(etag, etag_len, &sent_header)) {
2729 + return FAILURE;
2730 + }
2731 + if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
2732 + http_exit_ex(304, sent_header, NULL, 0);
2733 + } else {
2734 + STR_FREE(sent_header);
2735 + }
2736 + return SUCCESS;
2737 + }
2738 +
2739 + /* start ob_etaghandler */
2740 + return http_start_ob_etaghandler();
2741 +}
2742 +/* }}} */
2743 +
2744 +PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D)
2745 +{
2746 + /* already running? */
2747 +#ifdef PHP_OUTPUT_NEWAPI
2748 + STATUS rv;
2749 +
2750 + if (php_output_handler_conflict(ZEND_STRL("ob_etaghandler"), ZEND_STRL("ob_etaghandler") TSRMLS_CC)) {
2751 + return FAILURE;
2752 + }
2753 +#else
2754 + if (php_ob_handler_used("ob_etaghandler" TSRMLS_CC)) {
2755 + http_error(HE_WARNING, HTTP_E_RUNTIME, "ob_etaghandler can only be used once");
2756 + return FAILURE;
2757 + }
2758 +#endif
2759 + HTTP_G->etag.started = 1;
2760 +#ifdef PHP_OUTPUT_NEWAPI
2761 + return php_output_start_internal(ZEND_STRL("ob_etaghandler"), _http_ob_etaghandler, HTTP_G->send.buffer_size, 0 TSRMLS_CC);
2762 +#else
2763 + return php_start_ob_buffer_named("ob_etaghandler", HTTP_G->send.buffer_size, 0 TSRMLS_CC);
2764 +#endif
2765 +}
2766 +
2767 +PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D)
2768 +{
2769 + if (HTTP_G->etag.started) {
2770 + HTTP_G->etag.started = 0;
2771 + if (HTTP_G->etag.ctx) {
2772 + efree(HTTP_G->etag.ctx);
2773 + HTTP_G->etag.ctx = NULL;
2774 + }
2775 + return 1;
2776 + }
2777 + return 0;
2778 +}
2779 +
2780 +/* {{{ void http_ob_etaghandler(char *, uint, char **, uint *, int) */
2781 +void _http_ob_etaghandler(char *output, uint output_len,
2782 + char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
2783 +{
2784 + /* passthru */
2785 + *handled_output_len = output_len;
2786 + *handled_output = estrndup(output, output_len);
2787 +
2788 + /* are we supposed to run? */
2789 + if (HTTP_G->etag.started) {
2790 + /* initialize the etag context */
2791 + if (mode & PHP_OUTPUT_HANDLER_START) {
2792 + HTTP_G->etag.ctx = http_etag_init();
2793 + }
2794 +
2795 + /* update */
2796 + http_etag_update(HTTP_G->etag.ctx, output, output_len);
2797 +
2798 + /* finish */
2799 + if (mode & PHP_OUTPUT_HANDLER_END) {
2800 + char *sent_header = NULL;
2801 + char *etag = http_etag_finish(HTTP_G->etag.ctx);
2802 +
2803 + HTTP_G->etag.ctx = NULL;
2804 +
2805 + http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
2806 + http_send_etag_ex(etag, strlen(etag), &sent_header);
2807 +
2808 + if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
2809 + /* force exit; ob within ob does not work */
2810 + HTTP_G->force_exit = 1;
2811 + http_exit_ex(304, sent_header, etag, 0);
2812 + }
2813 +
2814 + STR_FREE(sent_header);
2815 + STR_FREE(etag);
2816 + }
2817 + }
2818 +}
2819 +/* }}} */
2820 +
2821 +/*
2822 + * Local variables:
2823 + * tab-width: 4
2824 + * c-basic-offset: 4
2825 + * End:
2826 + * vim600: sw=4 ts=4 fdm=marker
2827 + * vim<600: sw=4 ts=4
2828 + */
2829 +
2830 --- /dev/null
2831 +++ b/ext/http/http_cookie_api.c
2832 @@ -0,0 +1,371 @@
2833 +/*
2834 + +--------------------------------------------------------------------+
2835 + | PECL :: http |
2836 + +--------------------------------------------------------------------+
2837 + | Redistribution and use in source and binary forms, with or without |
2838 + | modification, are permitted provided that the conditions mentioned |
2839 + | in the accompanying LICENSE file are met. |
2840 + +--------------------------------------------------------------------+
2841 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
2842 + +--------------------------------------------------------------------+
2843 +*/
2844 +
2845 +/* $Id: http_cookie_api.c 298662 2010-04-27 13:42:32Z mike $ */
2846 +
2847 +#include "php_http.h"
2848 +#include "php_http_api.h"
2849 +#include "php_http_date_api.h"
2850 +#include "php_http_cookie_api.h"
2851 +
2852 +#include "ext/standard/url.h"
2853 +
2854 +/* {{{ PHP_MINIT_FUNCTION(http_cookie) */
2855 +PHP_MINIT_FUNCTION(http_cookie)
2856 +{
2857 + HTTP_LONG_CONSTANT("HTTP_COOKIE_PARSE_RAW", HTTP_COOKIE_PARSE_RAW);
2858 + HTTP_LONG_CONSTANT("HTTP_COOKIE_SECURE", HTTP_COOKIE_SECURE);
2859 + HTTP_LONG_CONSTANT("HTTP_COOKIE_HTTPONLY", HTTP_COOKIE_HTTPONLY);
2860 +
2861 + return SUCCESS;
2862 +}
2863 +/* }}} */
2864 +
2865 +/* {{{ http_cookie_list *http_cookie_list_init(http_cookie_list *) */
2866 +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)
2867 +{
2868 + if (!list) {
2869 + list = emalloc_rel(sizeof(http_cookie_list));
2870 + }
2871 +
2872 + zend_hash_init(&list->cookies, 0, NULL, ZVAL_PTR_DTOR, 0);
2873 + zend_hash_init(&list->extras, 0, NULL, ZVAL_PTR_DTOR, 0);
2874 +
2875 + list->path = NULL;
2876 + list->domain = NULL;
2877 + list->expires = 0;
2878 + list->flags = 0;
2879 +
2880 + return list;
2881 +}
2882 +/* }}} */
2883 +
2884 +/* {{{ void http_cookie_list_dtor(http_cookie_list *) */
2885 +PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC)
2886 +{
2887 + if (list) {
2888 + zend_hash_destroy(&list->cookies);
2889 + zend_hash_destroy(&list->extras);
2890 +
2891 + STR_SET(list->path, NULL);
2892 + STR_SET(list->domain, NULL);
2893 + }
2894 +}
2895 +/* }}} */
2896 +
2897 +/* {{{ void http_cookie_list_free(http_cookie_list **) */
2898 +PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC)
2899 +{
2900 + if (list) {
2901 + http_cookie_list_dtor(*list);
2902 + efree(*list);
2903 + *list = NULL;
2904 + }
2905 +}
2906 +/* }}} */
2907 +
2908 +/* {{{ const char *http_cookie_list_get_cookie(http_cookie_list *, const char*, size_t) */
2909 +PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC)
2910 +{
2911 + zval **cookie = NULL;
2912 + if ((SUCCESS != zend_hash_find(&list->cookies, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &cookie)) || (Z_TYPE_PP(cookie) != IS_STRING)) {
2913 + return NULL;
2914 + }
2915 + return Z_STRVAL_PP(cookie);
2916 +}
2917 +/* }}} */
2918 +
2919 +/* {{{ const char *http_cookie_list_get_extra(http_cookie_list *, const char *, size_t) */
2920 +PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC)
2921 +{
2922 + zval **extra = NULL;
2923 + if ((SUCCESS != zend_hash_find(&list->extras, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &extra)) || (Z_TYPE_PP(extra) != IS_STRING)) {
2924 + return NULL;
2925 + }
2926 + return Z_STRVAL_PP(extra);
2927 +}
2928 +/* }}} */
2929 +
2930 +/* {{{ void http_cookie_list_add_cookie(http_cookie_list *, const char *, size_t, const char *, size_t) */
2931 +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)
2932 +{
2933 + zval *cookie_value;
2934 + char *key = estrndup(name, name_len);
2935 + MAKE_STD_ZVAL(cookie_value);
2936 + ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
2937 + zend_hash_update(&list->cookies, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
2938 + efree(key);
2939 +}
2940 +/* }}} */
2941 +
2942 +/* {{{ void http_cookie_list_add_extr(http_cookie_list *, const char *, size_t, const char *, size_t) */
2943 +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)
2944 +{
2945 + zval *cookie_value;
2946 + char *key = estrndup(name, name_len);
2947 + MAKE_STD_ZVAL(cookie_value);
2948 + ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0);
2949 + zend_hash_update(&list->extras, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL);
2950 + efree(key);
2951 +}
2952 +/* }}} */
2953 +
2954 +typedef struct _http_parse_param_cb_arg_t {
2955 + http_cookie_list *list;
2956 + long flags;
2957 + char **allowed_extras;
2958 +} http_parse_param_cb_arg;
2959 +
2960 +/* {{{ static void http_parse_cookie_callback */
2961 +static void http_parse_cookie_callback(void *ptr, const char *key, int keylen, const char *val, int vallen TSRMLS_DC)
2962 +{
2963 + http_parse_param_cb_arg *arg = (http_parse_param_cb_arg *) ptr;
2964 +
2965 +#define _KEY_IS(s) (keylen == lenof(s) && !strncasecmp(key, (s), keylen))
2966 + if _KEY_IS("path") {
2967 + STR_SET(arg->list->path, estrndup(val, vallen));
2968 + } else if _KEY_IS("domain") {
2969 + STR_SET(arg->list->domain, estrndup(val, vallen));
2970 + } else if _KEY_IS("expires") {
2971 + char *date = estrndup(val, vallen);
2972 + arg->list->expires = http_parse_date(date);
2973 + efree(date);
2974 + } else if _KEY_IS("secure") {
2975 + arg->list->flags |= HTTP_COOKIE_SECURE;
2976 + } else if _KEY_IS("httpOnly") {
2977 + arg->list->flags |= HTTP_COOKIE_HTTPONLY;
2978 + } else {
2979 + /* check for extra */
2980 + if (arg->allowed_extras) {
2981 + char **ae = arg->allowed_extras;
2982 +
2983 + for (; *ae; ++ae) {
2984 + if ((size_t) keylen == strlen(*ae) && !strncasecmp(key, *ae, keylen)) {
2985 + if (arg->flags & HTTP_COOKIE_PARSE_RAW) {
2986 + http_cookie_list_add_extra(arg->list, key, keylen, val, vallen);
2987 + } else {
2988 + char *dec = estrndup(val, vallen);
2989 + int declen = php_url_decode(dec, vallen);
2990 +
2991 + http_cookie_list_add_extra(arg->list, key, keylen, dec, declen);
2992 + efree(dec);
2993 + }
2994 + return;
2995 + }
2996 + }
2997 + }
2998 + /* new cookie */
2999 + if (arg->flags & HTTP_COOKIE_PARSE_RAW) {
3000 + http_cookie_list_add_cookie(arg->list, key, keylen, val, vallen);
3001 + } else {
3002 + char *dec = estrndup(val, vallen);
3003 + int declen = php_url_decode(dec, vallen);
3004 +
3005 + http_cookie_list_add_cookie(arg->list, key, keylen, dec, declen);
3006 + efree(dec);
3007 + }
3008 + }
3009 +}
3010 +/* }}} */
3011 +
3012 +/* {{{ http_cookie_list *http_parse_cookie(char *, long) */
3013 +PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list *list, const char *string, long flags, char **allowed_extras TSRMLS_DC)
3014 +{
3015 + int free_list = !list;
3016 + http_parse_param_cb_arg arg;
3017 +
3018 + list = http_cookie_list_init(list);
3019 +
3020 + arg.list = list;
3021 + arg.flags = flags;
3022 + arg.allowed_extras = allowed_extras;
3023 +
3024 + if (SUCCESS != http_parse_params_ex(string, HTTP_PARAMS_RAISE_ERROR, http_parse_cookie_callback, &arg)) {
3025 + if (free_list) {
3026 + http_cookie_list_free(&list);
3027 + } else {
3028 + http_cookie_list_dtor(list);
3029 + }
3030 + list = NULL;
3031 + }
3032 +
3033 + return list;
3034 +}
3035 +/* }}} */
3036 +
3037 +/* {{{ void http_cookie_list_tostruct(http_cookie_list *, zval *) */
3038 +PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC)
3039 +{
3040 + zval array, *cookies, *extras;
3041 +
3042 + INIT_ZARR(array, HASH_OF(strct));
3043 +
3044 + MAKE_STD_ZVAL(cookies);
3045 + array_init(cookies);
3046 + zend_hash_copy(Z_ARRVAL_P(cookies), &list->cookies, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3047 + add_assoc_zval(&array, "cookies", cookies);
3048 +
3049 + MAKE_STD_ZVAL(extras);
3050 + array_init(extras);
3051 + zend_hash_copy(Z_ARRVAL_P(extras), &list->extras, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3052 + add_assoc_zval(&array, "extras", extras);
3053 +
3054 + add_assoc_long(&array, "flags", list->flags);
3055 + add_assoc_long(&array, "expires", (long) list->expires);
3056 + add_assoc_string(&array, "path", STR_PTR(list->path), 1);
3057 + add_assoc_string(&array, "domain", STR_PTR(list->domain), 1);
3058 +}
3059 +/* }}} */
3060 +
3061 +/* {{{ http_cookie_list *http_cookie_list_fromstruct(http_cookie_list *, zval *strct) */
3062 +PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC)
3063 +{
3064 + zval **tmp, *cpy;
3065 + HashTable *ht = HASH_OF(strct);
3066 +
3067 + list = http_cookie_list_init(list);
3068 +
3069 + if (SUCCESS == zend_hash_find(ht, "cookies", sizeof("cookies"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
3070 + zend_hash_copy(&list->cookies, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3071 + }
3072 + if (SUCCESS == zend_hash_find(ht, "extras", sizeof("extras"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) {
3073 + zend_hash_copy(&list->extras, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3074 + }
3075 + if (SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &tmp)) {
3076 + switch (Z_TYPE_PP(tmp)) {
3077 + case IS_LONG:
3078 + list->flags = Z_LVAL_PP(tmp);
3079 + break;
3080 + case IS_DOUBLE:
3081 + list->flags = (long) Z_DVAL_PP(tmp);
3082 + break;
3083 + case IS_STRING:
3084 + cpy = http_zsep(IS_LONG, *tmp);
3085 + list->flags = Z_LVAL_P(cpy);
3086 + zval_ptr_dtor(&cpy);
3087 + break;
3088 + default:
3089 + break;
3090 + }
3091 + }
3092 + if (SUCCESS == zend_hash_find(ht, "expires", sizeof("expires"), (void *) &tmp)) {
3093 + switch (Z_TYPE_PP(tmp)) {
3094 + case IS_LONG:
3095 + list->expires = Z_LVAL_PP(tmp);
3096 + break;
3097 + case IS_DOUBLE:
3098 + list->expires = (long) Z_DVAL_PP(tmp);
3099 + break;
3100 + case IS_STRING:
3101 + cpy = http_zsep(IS_LONG, *tmp);
3102 + if (Z_LVAL_P(cpy)) {
3103 + list->expires = Z_LVAL_P(cpy);
3104 + } else {
3105 + time_t expires = http_parse_date(Z_STRVAL_PP(tmp));
3106 + if (expires > 0) {
3107 + list->expires = expires;
3108 + }
3109 + }
3110 + zval_ptr_dtor(&cpy);
3111 + break;
3112 + default:
3113 + break;
3114 + }
3115 + }
3116 + if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
3117 + list->path = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3118 + }
3119 + if (SUCCESS == zend_hash_find(ht, "domain", sizeof("domain"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) {
3120 + list->domain = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3121 + }
3122 +
3123 + return list;
3124 +}
3125 +/* }}} */
3126 +
3127 +/* {{{ inline append_encoded */
3128 +static inline void append_encoded(phpstr *buf, const char *key, size_t key_len, const char *val, size_t val_len)
3129 +{
3130 + char *enc_str[2];
3131 + int enc_len[2];
3132 +
3133 + enc_str[0] = php_url_encode(key, key_len, &enc_len[0]);
3134 + enc_str[1] = php_url_encode(val, val_len, &enc_len[1]);
3135 +
3136 + phpstr_append(buf, enc_str[0], enc_len[0]);
3137 + phpstr_appends(buf, "=");
3138 + phpstr_append(buf, enc_str[1], enc_len[1]);
3139 + phpstr_appends(buf, "; ");
3140 +
3141 + efree(enc_str[0]);
3142 + efree(enc_str[1]);
3143 +}
3144 +/* }}} */
3145 +
3146 +/* {{{ void http_cookie_list_tostring(http_cookie_list *, char **, size_t *) */
3147 +PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC)
3148 +{
3149 + phpstr buf;
3150 + zval **val;
3151 + HashKey key = initHashKey(0);
3152 + HashPosition pos;
3153 +
3154 + phpstr_init(&buf);
3155 +
3156 + FOREACH_HASH_KEYVAL(pos, &list->cookies, 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));
3160 + zval_ptr_dtor(&tmp);
3161 + }
3162 + }
3163 +
3164 + if (list->domain && *list->domain) {
3165 + phpstr_appendf(&buf, "domain=%s; ", list->domain);
3166 + }
3167 + if (list->path && *list->path) {
3168 + phpstr_appendf(&buf, "path=%s; ", list->path);
3169 + }
3170 + if (list->expires) {
3171 + char *date = http_date(list->expires);
3172 + phpstr_appendf(&buf, "expires=%s; ", date);
3173 + efree(date);
3174 + }
3175 +
3176 + FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) {
3177 + if (key.type == HASH_KEY_IS_STRING && key.len) {
3178 + zval *tmp = http_zsep(IS_STRING, *val);
3179 + append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp));
3180 + }
3181 + }
3182 +
3183 + if (list->flags & HTTP_COOKIE_SECURE) {
3184 + phpstr_appends(&buf, "secure; ");
3185 + }
3186 + if (list->flags & HTTP_COOKIE_HTTPONLY) {
3187 + phpstr_appends(&buf, "httpOnly; ");
3188 + }
3189 +
3190 + phpstr_fix(&buf);
3191 + *str = PHPSTR_VAL(&buf);
3192 + *len = PHPSTR_LEN(&buf);
3193 +}
3194 +/* }}} */
3195 +
3196 +/*
3197 + * Local variables:
3198 + * tab-width: 4
3199 + * c-basic-offset: 4
3200 + * End:
3201 + * vim600: noet sw=4 ts=4 fdm=marker
3202 + * vim<600: noet sw=4 ts=4
3203 + */
3204 --- /dev/null
3205 +++ b/ext/http/http_date_api.c
3206 @@ -0,0 +1,357 @@
3207 +/*
3208 + +--------------------------------------------------------------------+
3209 + | PECL :: http |
3210 + +--------------------------------------------------------------------+
3211 + | Redistribution and use in source and binary forms, with or without |
3212 + | modification, are permitted provided that the conditions mentioned |
3213 + | in the accompanying LICENSE file are met. |
3214 + +--------------------------------------------------------------------+
3215 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
3216 + +--------------------------------------------------------------------+
3217 +*/
3218 +
3219 +/* $Id: http_date_api.c 292841 2009-12-31 08:48:57Z mike $ */
3220 +
3221 +#include "php_http.h"
3222 +
3223 +#include "php_http_api.h"
3224 +#include "php_http_date_api.h"
3225 +
3226 +static inline int check_day(const char *day, size_t len);
3227 +static inline int check_month(const char *month);
3228 +static inline int check_tzone(const char *tzone);
3229 +static inline time_t parse_date(const char *month);
3230 +
3231 +/* {{{ day/month names */
3232 +static const char *days[] = {
3233 + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
3234 +};
3235 +static const char *wkdays[] = {
3236 + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
3237 +};
3238 +static const char *weekdays[] = {
3239 + "Monday", "Tuesday", "Wednesday",
3240 + "Thursday", "Friday", "Saturday", "Sunday"
3241 +};
3242 +static const char *months[] = {
3243 + "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3244 + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3245 +};
3246 +enum assume_next {
3247 + DATE_MDAY,
3248 + DATE_YEAR,
3249 + DATE_TIME
3250 +};
3251 +#define DS -60
3252 +static const struct time_zone {
3253 + const char *name;
3254 + const int offset;
3255 +} time_zones[] = {
3256 + {"GMT", 0}, /* Greenwich Mean */
3257 + {"UTC", 0}, /* Universal (Coordinated) */
3258 + {"WET", 0}, /* Western European */
3259 + {"BST", 0 DS}, /* British Summer */
3260 + {"WAT", 60}, /* West Africa */
3261 + {"AST", 240}, /* Atlantic Standard */
3262 + {"ADT", 240 DS},/* Atlantic Daylight */
3263 + {"EST", 300}, /* Eastern Standard */
3264 + {"EDT", 300 DS},/* Eastern Daylight */
3265 + {"CST", 360}, /* Central Standard */
3266 + {"CDT", 360 DS},/* Central Daylight */
3267 + {"MST", 420}, /* Mountain Standard */
3268 + {"MDT", 420 DS},/* Mountain Daylight */
3269 + {"PST", 480}, /* Pacific Standard */
3270 + {"PDT", 480 DS},/* Pacific Daylight */
3271 + {"YST", 540}, /* Yukon Standard */
3272 + {"YDT", 540 DS},/* Yukon Daylight */
3273 + {"HST", 600}, /* Hawaii Standard */
3274 + {"HDT", 600 DS},/* Hawaii Daylight */
3275 + {"CAT", 600}, /* Central Alaska */
3276 + {"AHST", 600}, /* Alaska-Hawaii Standard */
3277 + {"NT", 660}, /* Nome */
3278 + {"IDLW", 720}, /* International Date Line West */
3279 + {"CET", -60}, /* Central European */
3280 + {"MET", -60}, /* Middle European */
3281 + {"MEWT", -60}, /* Middle European Winter */
3282 + {"MEST", -60 DS},/* Middle European Summer */
3283 + {"CEST", -60 DS},/* Central European Summer */
3284 + {"MESZ", -60 DS},/* Middle European Summer */
3285 + {"FWT", -60}, /* French Winter */
3286 + {"FST", -60 DS},/* French Summer */
3287 + {"EET", -120}, /* Eastern Europe, USSR Zone 1 */
3288 + {"WAST", -420}, /* West Australian Standard */
3289 + {"WADT", -420 DS},/* West Australian Daylight */
3290 + {"CCT", -480}, /* China Coast, USSR Zone 7 */
3291 + {"JST", -540}, /* Japan Standard, USSR Zone 8 */
3292 + {"EAST", -600}, /* Eastern Australian Standard */
3293 + {"EADT", -600 DS},/* Eastern Australian Daylight */
3294 + {"GST", -600}, /* Guam Standard, USSR Zone 9 */
3295 + {"NZT", -720}, /* New Zealand */
3296 + {"NZST", -720}, /* New Zealand Standard */
3297 + {"NZDT", -720 DS},/* New Zealand Daylight */
3298 + {"IDLE", -720}, /* International Date Line East */
3299 +};
3300 +/* }}} */
3301 +
3302 +/* {{{ Day/Month/TZ checks for http_parse_date()
3303 + Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
3304 +static inline int check_day(const char *day, size_t len)
3305 +{
3306 + int i;
3307 + const char * const *check = (len > 3) ? &weekdays[0] : &wkdays[0];
3308 + for (i = 0; i < 7; i++) {
3309 + if (!strcmp(day, check[0])) {
3310 + return i;
3311 + }
3312 + check++;
3313 + }
3314 + return -1;
3315 +}
3316 +
3317 +static inline int check_month(const char *month)
3318 +{
3319 + int i;
3320 + const char * const *check = &months[0];
3321 + for (i = 0; i < 12; i++) {
3322 + if (!strcmp(month, check[0])) {
3323 + return i;
3324 + }
3325 + check++;
3326 + }
3327 + return -1;
3328 +}
3329 +
3330 +/* return the time zone offset between GMT and the input one, in number
3331 + of seconds or -1 if the timezone wasn't found/legal */
3332 +
3333 +static inline int check_tzone(const char *tzone)
3334 +{
3335 + unsigned i;
3336 + const struct time_zone *check = time_zones;
3337 + for (i = 0; i < sizeof(time_zones) / sizeof(time_zones[0]); i++) {
3338 + if (!strcmp(tzone, check->name)) {
3339 + return check->offset * 60;
3340 + }
3341 + check++;
3342 + }
3343 + return -1;
3344 +}
3345 +/* }}} */
3346 +
3347 +/* {{{ char *http_date(time_t) */
3348 +PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC)
3349 +{
3350 + char *date = NULL;
3351 + struct tm *gmtime = NULL, tmbuf;
3352 +
3353 + memset(&tmbuf, 0, sizeof(tmbuf));
3354 + if ((gmtime = php_gmtime_r(&t, &tmbuf))) {
3355 + spprintf(&date, 0,
3356 + "%s, %02d %s %04d %02d:%02d:%02d GMT",
3357 + days[gmtime->tm_wday], gmtime->tm_mday,
3358 + months[gmtime->tm_mon], gmtime->tm_year + 1900,
3359 + gmtime->tm_hour, gmtime->tm_min, gmtime->tm_sec
3360 + );
3361 + }
3362 +
3363 + return date;
3364 +}
3365 +/* }}} */
3366 +
3367 +/* {{{ time_t http_parse_date(char *) */
3368 +PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC)
3369 +{
3370 + time_t t = parse_date(date);
3371 +
3372 + if (-1 == t && !silent) {
3373 + http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Could not parse date: %s", date);
3374 + }
3375 +
3376 + return t;
3377 +}
3378 +/* }}} */
3379 +
3380 +/* time_t parse_date(char *)
3381 + Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
3382 +static inline time_t parse_date(const char *date)
3383 +{
3384 + time_t t = 0;
3385 + int tz_offset = -1, year = -1, month = -1, monthday = -1, weekday = -1,
3386 + hours = -1, minutes = -1, seconds = -1;
3387 + struct tm tm;
3388 + enum assume_next dignext = DATE_MDAY;
3389 + const char *indate = date;
3390 +
3391 + int part = 0; /* max 6 parts */
3392 +
3393 + while (*date && (part < 6)) {
3394 + int found = 0;
3395 +
3396 + while (*date && !HTTP_IS_CTYPE(alnum, *date)) {
3397 + date++;
3398 + }
3399 +
3400 + if (HTTP_IS_CTYPE(alpha, *date)) {
3401 + /* a name coming up */
3402 + char buf[32] = "";
3403 + size_t len;
3404 + sscanf(date, "%31[A-Za-z]", buf);
3405 + len = strlen(buf);
3406 +
3407 + if (weekday == -1) {
3408 + weekday = check_day(buf, len);
3409 + if (weekday != -1) {
3410 + found = 1;
3411 + }
3412 + }
3413 +
3414 + if (!found && (month == -1)) {
3415 + month = check_month(buf);
3416 + if (month != -1) {
3417 + found = 1;
3418 + }
3419 + }
3420 +
3421 + if (!found && (tz_offset == -1)) {
3422 + /* this just must be a time zone string */
3423 + tz_offset = check_tzone(buf);
3424 + if (tz_offset != -1) {
3425 + found = 1;
3426 + }
3427 + }
3428 +
3429 + if (!found) {
3430 + return -1; /* bad string */
3431 + }
3432 + date += len;
3433 + }
3434 + else if (HTTP_IS_CTYPE(digit, *date)) {
3435 + /* a digit */
3436 + int val;
3437 + char *end;
3438 + if ((seconds == -1) &&
3439 + (3 == sscanf(date, "%02d:%02d:%02d", &hours, &minutes, &seconds))) {
3440 + /* time stamp! */
3441 + date += 8;
3442 + found = 1;
3443 + }
3444 + else {
3445 + val = (int) strtol(date, &end, 10);
3446 +
3447 + if ((tz_offset == -1) && ((end - date) == 4) && (val < 1300) &&
3448 + (indate < date) && ((date[-1] == '+' || date[-1] == '-'))) {
3449 + /* four digits and a value less than 1300 and it is preceeded with
3450 + a plus or minus. This is a time zone indication. */
3451 + found = 1;
3452 + tz_offset = (val / 100 * 60 + val % 100) * 60;
3453 +
3454 + /* the + and - prefix indicates the local time compared to GMT,
3455 + this we need ther reversed math to get what we want */
3456 + tz_offset = date[-1] == '+' ? -tz_offset : tz_offset;
3457 + }
3458 +
3459 + if (((end - date) == 8) && (year == -1) && (month == -1) && (monthday == -1)) {
3460 + /* 8 digits, no year, month or day yet. This is YYYYMMDD */
3461 + found = 1;
3462 + year = val / 10000;
3463 + month = (val % 10000) / 100 - 1; /* month is 0 - 11 */
3464 + monthday = val % 100;
3465 + }
3466 +
3467 + if (!found && (dignext == DATE_MDAY) && (monthday == -1)) {
3468 + if ((val > 0) && (val < 32)) {
3469 + monthday = val;
3470 + found = 1;
3471 + }
3472 + dignext = DATE_YEAR;
3473 + }
3474 +
3475 + if (!found && (dignext == DATE_YEAR) && (year == -1)) {
3476 + year = val;
3477 + found = 1;
3478 + if (year < 1900) {
3479 + year += year > 70 ? 1900 : 2000;
3480 + }
3481 + if(monthday == -1) {
3482 + dignext = DATE_MDAY;
3483 + }
3484 + }
3485 +
3486 + if (!found) {
3487 + return -1;
3488 + }
3489 +
3490 + date = end;
3491 + }
3492 + }
3493 +
3494 + part++;
3495 + }
3496 +
3497 + if (-1 == seconds) {
3498 + seconds = minutes = hours = 0; /* no time, make it zero */
3499 + }
3500 +
3501 + if ((-1 == monthday) || (-1 == month) || (-1 == year)) {
3502 + /* lacks vital info, fail */
3503 + return -1;
3504 + }
3505 +
3506 + if (sizeof(time_t) < 5) {
3507 + /* 32 bit time_t can only hold dates to the beginning of 2038 */
3508 + if (year > 2037) {
3509 + return 0x7fffffff;
3510 + }
3511 + }
3512 +
3513 + tm.tm_sec = seconds;
3514 + tm.tm_min = minutes;
3515 + tm.tm_hour = hours;
3516 + tm.tm_mday = monthday;
3517 + tm.tm_mon = month;
3518 + tm.tm_year = year - 1900;
3519 + tm.tm_wday = 0;
3520 + tm.tm_yday = 0;
3521 + tm.tm_isdst = 0;
3522 +
3523 + t = mktime(&tm);
3524 +
3525 + /* time zone adjust */
3526 + if (t != -1) {
3527 + struct tm *gmt, keeptime2;
3528 + long delta;
3529 + time_t t2;
3530 +
3531 + if((gmt = php_gmtime_r(&t, &keeptime2))) {
3532 + tm = *gmt; /* MSVC quirks */
3533 + } else {
3534 + return -1; /* illegal date/time */
3535 + }
3536 +
3537 + t2 = mktime(&tm);
3538 +
3539 + /* Add the time zone diff (between the given timezone and GMT) and the
3540 + diff between the local time zone and GMT. */
3541 + delta = (tz_offset != -1 ? tz_offset : 0) + (t - t2);
3542 +
3543 + if((delta > 0) && (t + delta < t)) {
3544 + return -1; /* time_t overflow */
3545 + }
3546 +
3547 + t += delta;
3548 + }
3549 +
3550 + return t;
3551 +}
3552 +/* }}} */
3553 +
3554 +
3555 +/*
3556 + * Local variables:
3557 + * tab-width: 4
3558 + * c-basic-offset: 4
3559 + * End:
3560 + * vim600: sw=4 ts=4 fdm=marker
3561 + * vim<600: sw=4 ts=4
3562 + */
3563 +
3564 --- /dev/null
3565 +++ b/ext/http/http_deflatestream_object.c
3566 @@ -0,0 +1,317 @@
3567 +/*
3568 + +--------------------------------------------------------------------+
3569 + | PECL :: http |
3570 + +--------------------------------------------------------------------+
3571 + | Redistribution and use in source and binary forms, with or without |
3572 + | modification, are permitted provided that the conditions mentioned |
3573 + | in the accompanying LICENSE file are met. |
3574 + +--------------------------------------------------------------------+
3575 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
3576 + +--------------------------------------------------------------------+
3577 +*/
3578 +
3579 +/* $Id: http_deflatestream_object.c 323304 2012-02-17 21:13:24Z mike $ */
3580 +
3581 +#define HTTP_WANT_ZLIB
3582 +#include "php_http.h"
3583 +
3584 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB)
3585 +
3586 +#include "php_http_api.h"
3587 +#include "php_http_encoding_api.h"
3588 +#include "php_http_exception_object.h"
3589 +#include "php_http_deflatestream_object.h"
3590 +
3591 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpDeflateStream, method, 0, req_args)
3592 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpDeflateStream, method, 0)
3593 +#define HTTP_DEFLATE_ME(method, visibility) PHP_ME(HttpDeflateStream, method, HTTP_ARGS(HttpDeflateStream, method), visibility)
3594 +
3595 +HTTP_BEGIN_ARGS(__construct, 0)
3596 + HTTP_ARG_VAL(flags, 0)
3597 +HTTP_END_ARGS;
3598 +
3599 +HTTP_BEGIN_ARGS(factory, 0)
3600 + HTTP_ARG_VAL(flags, 0)
3601 + HTTP_ARG_VAL(class_name, 0)
3602 +HTTP_END_ARGS;
3603 +
3604 +HTTP_BEGIN_ARGS(update, 1)
3605 + HTTP_ARG_VAL(data, 0)
3606 +HTTP_END_ARGS;
3607 +
3608 +HTTP_BEGIN_ARGS(flush, 0)
3609 + HTTP_ARG_VAL(data, 0)
3610 +HTTP_END_ARGS;
3611 +
3612 +HTTP_BEGIN_ARGS(finish, 0)
3613 + HTTP_ARG_VAL(data, 0)
3614 +HTTP_END_ARGS;
3615 +
3616 +#define THIS_CE http_deflatestream_object_ce
3617 +zend_class_entry *http_deflatestream_object_ce;
3618 +zend_function_entry http_deflatestream_object_fe[] = {
3619 + HTTP_DEFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
3620 + HTTP_DEFLATE_ME(update, ZEND_ACC_PUBLIC)
3621 + HTTP_DEFLATE_ME(flush, ZEND_ACC_PUBLIC)
3622 + HTTP_DEFLATE_ME(finish, ZEND_ACC_PUBLIC)
3623 +
3624 + HTTP_DEFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
3625 +
3626 + EMPTY_FUNCTION_ENTRY
3627 +};
3628 +static zend_object_handlers http_deflatestream_object_handlers;
3629 +
3630 +PHP_MINIT_FUNCTION(http_deflatestream_object)
3631 +{
3632 + HTTP_REGISTER_CLASS_EX(HttpDeflateStream, http_deflatestream_object, NULL, 0);
3633 + http_deflatestream_object_handlers.clone_obj = _http_deflatestream_object_clone_obj;
3634 +
3635 +#ifndef WONKY
3636 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_GZIP")-1, HTTP_DEFLATE_TYPE_GZIP TSRMLS_CC);
3637 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ZLIB")-1, HTTP_DEFLATE_TYPE_ZLIB TSRMLS_CC);
3638 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RAW")-1, HTTP_DEFLATE_TYPE_RAW TSRMLS_CC);
3639 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_DEF")-1, HTTP_DEFLATE_LEVEL_DEF TSRMLS_CC);
3640 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MIN")-1, HTTP_DEFLATE_LEVEL_MIN TSRMLS_CC);
3641 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MAX")-1, HTTP_DEFLATE_LEVEL_MAX TSRMLS_CC);
3642 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_DEF")-1, HTTP_DEFLATE_STRATEGY_DEF TSRMLS_CC);
3643 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FILT")-1, HTTP_DEFLATE_STRATEGY_FILT TSRMLS_CC);
3644 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_HUFF")-1, HTTP_DEFLATE_STRATEGY_HUFF TSRMLS_CC);
3645 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_RLE")-1, HTTP_DEFLATE_STRATEGY_RLE TSRMLS_CC);
3646 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FIXED")-1, HTTP_DEFLATE_STRATEGY_FIXED TSRMLS_CC);
3647 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
3648 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
3649 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
3650 +#endif
3651 +
3652 + return SUCCESS;
3653 +}
3654 +
3655 +zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
3656 +{
3657 + return http_deflatestream_object_new_ex(ce, NULL, NULL);
3658 +}
3659 +
3660 +zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC)
3661 +{
3662 + zend_object_value ov;
3663 + http_deflatestream_object *o;
3664 +
3665 + o = ecalloc(1, sizeof(http_deflatestream_object));
3666 + o->zo.ce = ce;
3667 +
3668 + if (ptr) {
3669 + *ptr = o;
3670 + }
3671 +
3672 + if (s) {
3673 + o->stream = s;
3674 + }
3675 +
3676 +#ifdef ZEND_ENGINE_2_4
3677 + zend_object_std_init(o, ce TSRMLS_CC);
3678 + object_properties_init(o, ce);
3679 +#else
3680 + ALLOC_HASHTABLE(OBJ_PROP(o));
3681 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
3682 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3683 +#endif
3684 +
3685 + ov.handle = putObject(http_deflatestream_object, o);
3686 + ov.handlers = &http_deflatestream_object_handlers;
3687 +
3688 + return ov;
3689 +}
3690 +
3691 +zend_object_value _http_deflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
3692 +{
3693 + http_encoding_stream *s;
3694 + zend_object_value new_ov;
3695 + http_deflatestream_object *new_obj = NULL;
3696 + getObject(http_deflatestream_object, old_obj);
3697 +
3698 + s = ecalloc(1, sizeof(http_encoding_stream));
3699 + s->flags = old_obj->stream->flags;
3700 + deflateCopy(&s->stream, &old_obj->stream->stream);
3701 + s->stream.opaque = phpstr_dup(s->stream.opaque);
3702 +
3703 + new_ov = http_deflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
3704 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
3705 +
3706 + return new_ov;
3707 +}
3708 +
3709 +void _http_deflatestream_object_free(zend_object *object TSRMLS_DC)
3710 +{
3711 + http_deflatestream_object *o = (http_deflatestream_object *) object;
3712 +
3713 + if (o->stream) {
3714 + http_encoding_deflate_stream_free(&o->stream);
3715 + }
3716 + freeObject(o);
3717 +}
3718 +
3719 +/* {{{ proto void HttpDeflateStream::__construct([int flags = 0])
3720 + Creates a new HttpDeflateStream object instance. */
3721 +PHP_METHOD(HttpDeflateStream, __construct)
3722 +{
3723 + long flags = 0;
3724 +
3725 + SET_EH_THROW_HTTP();
3726 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
3727 + getObject(http_deflatestream_object, obj);
3728 +
3729 + if (!obj->stream) {
3730 + obj->stream = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
3731 + } else {
3732 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpDeflateStream cannot be initialized twice");
3733 + }
3734 + }
3735 + SET_EH_NORMAL();
3736 +}
3737 +/* }}} */
3738 +
3739 +/* {{{ proto HttpDeflateStream HttpDeflateStream::factory([int flags[, string class = "HttpDeflateStream"]])
3740 + Creates a new HttpDeflateStream object instance. */
3741 +PHP_METHOD(HttpDeflateStream, factory)
3742 +{
3743 + long flags = 0;
3744 + char *cn = NULL;
3745 + int cl = 0;
3746 +
3747 + SET_EH_THROW_HTTP();
3748 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
3749 + zend_object_value ov;
3750 + http_encoding_stream *s = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff);
3751 +
3752 + if (SUCCESS == http_object_new(&ov, cn, cl, _http_deflatestream_object_new_ex, http_deflatestream_object_ce, s, NULL)) {
3753 + RETVAL_OBJVAL(ov, 0);
3754 + }
3755 + }
3756 + SET_EH_NORMAL();
3757 +}
3758 +/* }}} */
3759 +
3760 +/* {{{ proto string HttpDeflateStream::update(string data)
3761 + Passes more data through the deflate stream. */
3762 +PHP_METHOD(HttpDeflateStream, update)
3763 +{
3764 + int data_len;
3765 + size_t encoded_len = 0;
3766 + char *data, *encoded = NULL;
3767 + getObject(http_deflatestream_object, obj);
3768 +
3769 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
3770 + RETURN_FALSE;
3771 + }
3772 +
3773 + if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
3774 + RETURN_FALSE;
3775 + }
3776 +
3777 + if (SUCCESS == http_encoding_deflate_stream_update(obj->stream, data, data_len, &encoded, &encoded_len)) {
3778 + RETURN_STRINGL(encoded, encoded_len, 0);
3779 + } else {
3780 + RETURN_FALSE;
3781 + }
3782 +}
3783 +/* }}} */
3784 +
3785 +/* {{{ proto string HttpDeflateStream::flush([string data])
3786 + Flushes the deflate stream. */
3787 +PHP_METHOD(HttpDeflateStream, flush)
3788 +{
3789 + int data_len = 0;
3790 + size_t updated_len = 0, encoded_len = 0;
3791 + char *updated = NULL, *encoded = NULL, *data = NULL;
3792 + getObject(http_deflatestream_object, obj);
3793 +
3794 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
3795 + RETURN_FALSE;
3796 + }
3797 +
3798 + if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
3799 + RETURN_FALSE;
3800 + }
3801 +
3802 + if (data_len) {
3803 + if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
3804 + RETURN_FALSE;
3805 + }
3806 + }
3807 +
3808 + if (SUCCESS == http_encoding_deflate_stream_flush(obj->stream, &encoded, &encoded_len)) {
3809 + if (updated_len) {
3810 + updated = erealloc(updated, updated_len + encoded_len + 1);
3811 + updated[updated_len + encoded_len] = '\0';
3812 + memcpy(updated + updated_len, encoded, encoded_len);
3813 + STR_FREE(encoded);
3814 + updated_len += encoded_len;
3815 + RETURN_STRINGL(updated, updated_len, 0);
3816 + } else if (encoded) {
3817 + RETVAL_STRINGL(encoded, encoded_len, 0);
3818 + } else {
3819 + RETVAL_NULL();
3820 + }
3821 + } else {
3822 + RETVAL_FALSE;
3823 + }
3824 + STR_FREE(updated);
3825 +}
3826 +/* }}} */
3827 +
3828 +/* {{{ proto string HttpDeflateStream::finish([string data])
3829 + Finalizes the deflate stream. The deflate stream can be reused after finalizing. */
3830 +PHP_METHOD(HttpDeflateStream, finish)
3831 +{
3832 + int data_len = 0;
3833 + size_t updated_len = 0, encoded_len = 0;
3834 + char *updated = NULL, *encoded = NULL, *data = NULL;
3835 + getObject(http_deflatestream_object, obj);
3836 +
3837 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
3838 + RETURN_FALSE;
3839 + }
3840 +
3841 + if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) {
3842 + RETURN_FALSE;
3843 + }
3844 +
3845 + if (data_len) {
3846 + if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
3847 + RETURN_FALSE;
3848 + }
3849 + }
3850 +
3851 + if (SUCCESS == http_encoding_deflate_stream_finish(obj->stream, &encoded, &encoded_len)) {
3852 + if (updated_len) {
3853 + updated = erealloc(updated, updated_len + encoded_len + 1);
3854 + updated[updated_len + encoded_len] = '\0';
3855 + memcpy(updated + updated_len, encoded, encoded_len);
3856 + STR_FREE(encoded);
3857 + updated_len += encoded_len;
3858 + RETVAL_STRINGL(updated, updated_len, 0);
3859 + } else {
3860 + STR_FREE(updated);
3861 + RETVAL_STRINGL(encoded, encoded_len, 0);
3862 + }
3863 + } else {
3864 + STR_FREE(updated);
3865 + RETVAL_FALSE;
3866 + }
3867 +
3868 + http_encoding_deflate_stream_dtor(obj->stream);
3869 + http_encoding_deflate_stream_init(obj->stream, obj->stream->flags);
3870 +}
3871 +/* }}} */
3872 +
3873 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
3874 +
3875 +/*
3876 + * Local variables:
3877 + * tab-width: 4
3878 + * c-basic-offset: 4
3879 + * End:
3880 + * vim600: noet sw=4 ts=4 fdm=marker
3881 + * vim<600: noet sw=4 ts=4
3882 + */
3883 +
3884 --- /dev/null
3885 +++ b/ext/http/http_encoding_api.c
3886 @@ -0,0 +1,796 @@
3887 +/*
3888 + +--------------------------------------------------------------------+
3889 + | PECL :: http |
3890 + +--------------------------------------------------------------------+
3891 + | Redistribution and use in source and binary forms, with or without |
3892 + | modification, are permitted provided that the conditions mentioned |
3893 + | in the accompanying LICENSE file are met. |
3894 + +--------------------------------------------------------------------+
3895 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
3896 + +--------------------------------------------------------------------+
3897 +*/
3898 +
3899 +/* $Id: http_encoding_api.c 323304 2012-02-17 21:13:24Z mike $ */
3900 +
3901 +#define HTTP_WANT_ZLIB
3902 +#include "php_http.h"
3903 +
3904 +#include "php_http_api.h"
3905 +#include "php_http_encoding_api.h"
3906 +#include "php_http_send_api.h"
3907 +#include "php_http_headers_api.h"
3908 +
3909 +/* {{{ */
3910 +#ifdef HTTP_HAVE_ZLIB
3911 +PHP_MINIT_FUNCTION(http_encoding)
3912 +{
3913 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_DEF", HTTP_DEFLATE_LEVEL_DEF);
3914 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MIN", HTTP_DEFLATE_LEVEL_MIN);
3915 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MAX", HTTP_DEFLATE_LEVEL_MAX);
3916 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_ZLIB", HTTP_DEFLATE_TYPE_ZLIB);
3917 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_GZIP", HTTP_DEFLATE_TYPE_GZIP);
3918 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_RAW", HTTP_DEFLATE_TYPE_RAW);
3919 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_DEF", HTTP_DEFLATE_STRATEGY_DEF);
3920 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FILT", HTTP_DEFLATE_STRATEGY_FILT);
3921 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_HUFF", HTTP_DEFLATE_STRATEGY_HUFF);
3922 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_RLE", HTTP_DEFLATE_STRATEGY_RLE);
3923 + HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FIXED", HTTP_DEFLATE_STRATEGY_FIXED);
3924 +
3925 + HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_NONE", HTTP_ENCODING_STREAM_FLUSH_NONE);
3926 + HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_SYNC", HTTP_ENCODING_STREAM_FLUSH_SYNC);
3927 + HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_FULL", HTTP_ENCODING_STREAM_FLUSH_FULL);
3928 +
3929 + return SUCCESS;
3930 +}
3931 +
3932 +PHP_RINIT_FUNCTION(http_encoding)
3933 +{
3934 + if (HTTP_G->send.inflate.start_auto) {
3935 +#ifdef PHP_OUTPUT_NEWAPI
3936 + php_output_start_internal(ZEND_STRL("http inflate"), _http_ob_inflatehandler, HTTP_INFLATE_BUFFER_SIZE, 0 TSRMLS_CC);
3937 +#else
3938 + php_ob_set_internal_handler(_http_ob_inflatehandler, HTTP_INFLATE_BUFFER_SIZE, "http inflate", 0 TSRMLS_CC);
3939 +#endif
3940 + }
3941 + if (HTTP_G->send.deflate.start_auto) {
3942 +#ifdef PHP_OUTPUT_NEWAPI
3943 + php_output_start_internal(ZEND_STRL("http deflate"), _http_ob_deflatehandler, HTTP_DEFLATE_BUFFER_SIZE, 0 TSRMLS_CC);
3944 +#else
3945 + php_ob_set_internal_handler(_http_ob_deflatehandler, HTTP_DEFLATE_BUFFER_SIZE, "http deflate", 0 TSRMLS_CC);
3946 +#endif
3947 + }
3948 + return SUCCESS;
3949 +}
3950 +
3951 +PHP_RSHUTDOWN_FUNCTION(http_encoding)
3952 +{
3953 + if (HTTP_G->send.deflate.stream) {
3954 + http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream);
3955 + }
3956 + if (HTTP_G->send.inflate.stream) {
3957 + http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream);
3958 + }
3959 + return SUCCESS;
3960 +}
3961 +#endif
3962 +/* }}} */
3963 +
3964 +/* {{{ eol_match(char **, int *) */
3965 +static inline int eol_match(char **line, int *eol_len)
3966 +{
3967 + char *ptr = *line;
3968 +
3969 + while (' ' == *ptr) ++ptr;
3970 +
3971 + if (ptr == http_locate_eol(*line, eol_len)) {
3972 + *line = ptr;
3973 + return 1;
3974 + } else {
3975 + return 0;
3976 + }
3977 +}
3978 +/* }}} */
3979 +
3980 +/* {{{ char *http_encoding_dechunk(char *, size_t, char **, size_t *) */
3981 +PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC)
3982 +{
3983 + int eol_len = 0;
3984 + char *n_ptr = NULL;
3985 + const char *e_ptr = encoded;
3986 +
3987 + *decoded_len = 0;
3988 + *decoded = ecalloc(1, encoded_len);
3989 +
3990 + while ((encoded + encoded_len - e_ptr) > 0) {
3991 + ulong chunk_len = 0, rest;
3992 +
3993 + chunk_len = strtoul(e_ptr, &n_ptr, 16);
3994 +
3995 + /* we could not read in chunk size */
3996 + if (n_ptr == e_ptr) {
3997 + /*
3998 + * if this is the first turn and there doesn't seem to be a chunk
3999 + * size at the begining of the body, do not fail on apparently
4000 + * not encoded data and return a copy
4001 + */
4002 + if (e_ptr == encoded) {
4003 + http_error(HE_NOTICE, HTTP_E_ENCODING, "Data does not seem to be chunked encoded");
4004 + memcpy(*decoded, encoded, encoded_len);
4005 + *decoded_len = encoded_len;
4006 + return encoded + encoded_len;
4007 + } else {
4008 + efree(*decoded);
4009 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected chunk size at pos %tu of %zu but got trash", n_ptr - encoded, encoded_len);
4010 + return NULL;
4011 + }
4012 + }
4013 +
4014 + /* reached the end */
4015 + if (!chunk_len) {
4016 + /* move over '0' chunked encoding terminator */
4017 + while (*e_ptr == '0') ++e_ptr;
4018 + break;
4019 + }
4020 +
4021 + /* there should be CRLF after the chunk size, but we'll ignore SP+ too */
4022 + if (*n_ptr && !eol_match(&n_ptr, &eol_len)) {
4023 + if (eol_len == 2) {
4024 + 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));
4025 + } else {
4026 + 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);
4027 + }
4028 + }
4029 + n_ptr += eol_len;
4030 +
4031 + /* chunk size pretends more data than we actually got, so it's probably a truncated message */
4032 + if (chunk_len > (rest = encoded + encoded_len - n_ptr)) {
4033 + 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);
4034 + chunk_len = rest;
4035 + }
4036 +
4037 + /* copy the chunk */
4038 + memcpy(*decoded + *decoded_len, n_ptr, chunk_len);
4039 + *decoded_len += chunk_len;
4040 +
4041 + if (chunk_len == rest) {
4042 + e_ptr = n_ptr + chunk_len;
4043 + break;
4044 + } else {
4045 + /* advance to next chunk */
4046 + e_ptr = n_ptr + chunk_len + eol_len;
4047 + }
4048 + }
4049 +
4050 + return e_ptr;
4051 +}
4052 +/* }}} */
4053 +
4054 +/* {{{ int http_encoding_response_start(size_t) */
4055 +PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC)
4056 +{
4057 + int response = HTTP_G->send.deflate.response;
4058 +#ifdef PHP_OUTPUT_NEWAPI
4059 + int ohandler = php_output_handler_started(ZEND_STRL("ob_gzhandler") TSRMLS_CC) || php_output_handler_started(ZEND_STRL("zlib output compression") TSRMLS_CC);
4060 +#else
4061 + int ohandler = php_ob_handler_used("ob_gzhandler" TSRMLS_CC) || php_ob_handler_used("zlib output compression" TSRMLS_CC);
4062 +#endif
4063 +
4064 + if (!ohandler && !ignore_http_ohandler) {
4065 +#ifdef PHP_OUTPUT_NEWAPI
4066 + ohandler = php_output_handler_started(ZEND_STRL("ob_defaltehandler") TSRMLS_CC) || php_output_handler_started(ZEND_STRL("http deflate") TSRMLS_CC);
4067 +#else
4068 + ohandler = php_ob_handler_used("ob_deflatehandler" TSRMLS_CC) || php_ob_handler_used("http deflate" TSRMLS_CC);
4069 +#endif
4070 + }
4071 +
4072 + if (response && !ohandler) {
4073 +#ifdef HTTP_HAVE_ZLIB
4074 + HashTable *selected;
4075 + zval zsupported;
4076 +
4077 + HTTP_G->send.deflate.encoding = 0;
4078 +
4079 + INIT_PZVAL(&zsupported);
4080 + array_init(&zsupported);
4081 + add_next_index_stringl(&zsupported, "gzip", lenof("gzip"), 1);
4082 + add_next_index_stringl(&zsupported, "x-gzip", lenof("x-gzip"), 1);
4083 + add_next_index_stringl(&zsupported, "deflate", lenof("deflate"), 1);
4084 +
4085 + if ((selected = http_negotiate_encoding(&zsupported))) {
4086 + STATUS hs = FAILURE;
4087 + char *encoding = NULL;
4088 + ulong idx;
4089 +
4090 + if (HASH_KEY_IS_STRING == zend_hash_get_current_key(selected, &encoding, &idx, 0) && encoding) {
4091 + if (!strcmp(encoding, "gzip") || !strcmp(encoding, "x-gzip")) {
4092 + if (SUCCESS == (hs = http_send_header_string("Content-Encoding: gzip"))) {
4093 + HTTP_G->send.deflate.encoding = HTTP_ENCODING_GZIP;
4094 + }
4095 + } else if (!strcmp(encoding, "deflate")) {
4096 + if (SUCCESS == (hs = http_send_header_string("Content-Encoding: deflate"))) {
4097 + HTTP_G->send.deflate.encoding = HTTP_ENCODING_DEFLATE;
4098 + }
4099 + }
4100 + if (SUCCESS == hs) {
4101 + http_send_header_string("Vary: Accept-Encoding");
4102 + }
4103 + }
4104 +
4105 + zend_hash_destroy(selected);
4106 + FREE_HASHTABLE(selected);
4107 + }
4108 +
4109 + zval_dtor(&zsupported);
4110 +#else
4111 + HTTP_G->send.deflate.encoding = 0;
4112 + php_start_ob_buffer_named("ob_gzhandler", 0, 0 TSRMLS_CC);
4113 +#endif /* HTTP_HAVE_ZLIB */
4114 + } else if (content_length && !ohandler) {
4115 + /* emit a content-length header */
4116 + phpstr header;
4117 +
4118 + phpstr_init(&header);
4119 + phpstr_appendf(&header, "Content-Length: %zu", content_length);
4120 + phpstr_fix(&header);
4121 + http_send_header_string_ex(PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
4122 + phpstr_dtor(&header);
4123 + } else {
4124 + HTTP_G->send.deflate.encoding = 0;
4125 + }
4126 +
4127 + return HTTP_G->send.deflate.encoding;
4128 +}
4129 +/* }}} */
4130 +
4131 +#ifdef HTTP_HAVE_ZLIB
4132 +
4133 +/* {{{ inline int http_inflate_rounds */
4134 +static inline int http_inflate_rounds(z_stream *Z, int flush, char **buf, size_t *len)
4135 +{
4136 + int status = 0, round = 0;
4137 + phpstr buffer;
4138 +
4139 + *buf = NULL;
4140 + *len = 0;
4141 +
4142 + phpstr_init_ex(&buffer, Z->avail_in, PHPSTR_INIT_PREALLOC);
4143 +
4144 + do {
4145 + if (PHPSTR_NOMEM == phpstr_resize_ex(&buffer, buffer.size, 0, 1)) {
4146 + status = Z_MEM_ERROR;
4147 + } else {
4148 + Z->avail_out = buffer.free;
4149 + Z->next_out = (Bytef *) buffer.data + buffer.used;
4150 +#if 0
4151 + 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);
4152 +#endif
4153 + status = inflate(Z, flush);
4154 +
4155 + buffer.used += buffer.free - Z->avail_out;
4156 + buffer.free = Z->avail_out;
4157 +#if 0
4158 + 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);
4159 +#endif
4160 + HTTP_INFLATE_BUFFER_SIZE_ALIGN(buffer.size);
4161 + }
4162 + } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < HTTP_INFLATE_ROUNDS);
4163 +
4164 + if (status == Z_OK || status == Z_STREAM_END) {
4165 + phpstr_shrink(&buffer);
4166 + phpstr_fix(&buffer);
4167 + *buf = buffer.data;
4168 + *len = buffer.used;
4169 + } else {
4170 + phpstr_dtor(&buffer);
4171 + }
4172 +
4173 + return status;
4174 +}
4175 +/* }}} */
4176 +
4177 +/* {{{ STATUS http_encoding_deflate(int, char *, size_t, char **, size_t *) */
4178 +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)
4179 +{
4180 + int status, level, wbits, strategy;
4181 + z_stream Z;
4182 +
4183 + HTTP_DEFLATE_LEVEL_SET(flags, level);
4184 + HTTP_DEFLATE_WBITS_SET(flags, wbits);
4185 + HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
4186 +
4187 + memset(&Z, 0, sizeof(z_stream));
4188 + *encoded = NULL;
4189 + *encoded_len = 0;
4190 +
4191 + status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy);
4192 + if (Z_OK == status) {
4193 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
4194 + *encoded = emalloc_rel(*encoded_len);
4195 +
4196 + Z.next_in = (Bytef *) data;
4197 + Z.next_out = (Bytef *) *encoded;
4198 + Z.avail_in = data_len;
4199 + Z.avail_out = *encoded_len;
4200 +
4201 + status = deflate(&Z, Z_FINISH);
4202 + deflateEnd(&Z);
4203 +
4204 + if (Z_STREAM_END == status) {
4205 + /* size buffer down to actual length */
4206 + *encoded = erealloc_rel(*encoded, Z.total_out + 1);
4207 + (*encoded)[*encoded_len = Z.total_out] = '\0';
4208 + return SUCCESS;
4209 + } else {
4210 + STR_SET(*encoded, NULL);
4211 + *encoded_len = 0;
4212 + }
4213 + }
4214 +
4215 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not deflate data: %s", zError(status));
4216 + return FAILURE;
4217 +}
4218 +/* }}} */
4219 +
4220 +/* {{{ STATUS http_encoding_inflate(char *, size_t, char **, size_t) */
4221 +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)
4222 +{
4223 + z_stream Z;
4224 + int status, wbits = HTTP_WINDOW_BITS_ANY;
4225 +
4226 + memset(&Z, 0, sizeof(z_stream));
4227 +
4228 +retry_raw_inflate:
4229 + status = inflateInit2(&Z, wbits);
4230 + if (Z_OK == status) {
4231 + Z.next_in = (Bytef *) data;
4232 + Z.avail_in = data_len;
4233 +
4234 + switch (status = http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) {
4235 + case Z_STREAM_END:
4236 + inflateEnd(&Z);
4237 + return SUCCESS;
4238 +
4239 + case Z_OK:
4240 + status = Z_DATA_ERROR;
4241 + break;
4242 +
4243 + case Z_DATA_ERROR:
4244 + /* raw deflated data? */
4245 + if (HTTP_WINDOW_BITS_ANY == wbits) {
4246 + inflateEnd(&Z);
4247 + wbits = HTTP_WINDOW_BITS_RAW;
4248 + goto retry_raw_inflate;
4249 + }
4250 + }
4251 + inflateEnd(&Z);
4252 + }
4253 +
4254 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s", zError(status));
4255 + return FAILURE;
4256 +}
4257 +/* }}} */
4258 +
4259 +/* {{{ http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *, int) */
4260 +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)
4261 +{
4262 + int status, level, wbits, strategy, free_stream;
4263 +
4264 + if ((free_stream = !s)) {
4265 + s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));
4266 + }
4267 + memset(s, 0, sizeof(http_encoding_stream));
4268 + s->flags = flags;
4269 +
4270 + HTTP_DEFLATE_LEVEL_SET(flags, level);
4271 + HTTP_DEFLATE_WBITS_SET(flags, wbits);
4272 + HTTP_DEFLATE_STRATEGY_SET(flags, strategy);
4273 +
4274 + if (Z_OK == (status = deflateInit2(&s->stream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy))) {
4275 + int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
4276 +
4277 + if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) {
4278 + return s;
4279 + }
4280 + deflateEnd(&s->stream);
4281 + status = Z_MEM_ERROR;
4282 + }
4283 +
4284 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize deflate encoding stream: %s", zError(status));
4285 + if (free_stream) {
4286 + efree(s);
4287 + }
4288 + return NULL;
4289 +}
4290 +/* }}} */
4291 +
4292 +/* {{{ http_encoding_stream *http_encoding_inflate_stream_init(http_encoding_stream *, int) */
4293 +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)
4294 +{
4295 + int status, wbits, free_stream;
4296 +
4297 + if ((free_stream = !s)) {
4298 + s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT));
4299 + }
4300 + memset(s, 0, sizeof(http_encoding_stream));
4301 + s->flags = flags;
4302 +
4303 + HTTP_INFLATE_WBITS_SET(flags, wbits);
4304 +
4305 + if (Z_OK == (status = inflateInit2(&s->stream, wbits))) {
4306 + int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0;
4307 +
4308 + if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) {
4309 + return s;
4310 + }
4311 + inflateEnd(&s->stream);
4312 + status = Z_MEM_ERROR;
4313 + }
4314 +
4315 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize inflate stream: %s", zError(status));
4316 + if (free_stream) {
4317 + efree(s);
4318 + }
4319 + return NULL;
4320 +}
4321 +/* }}} */
4322 +
4323 +/* {{{ STATUS http_encoding_deflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */
4324 +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)
4325 +{
4326 + int status;
4327 +
4328 + /* append input to our buffer */
4329 + phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
4330 +
4331 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4332 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4333 +
4334 + /* deflate */
4335 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len);
4336 + *encoded = emalloc_rel(*encoded_len);
4337 + s->stream.avail_out = *encoded_len;
4338 + s->stream.next_out = (Bytef *) *encoded;
4339 +
4340 + switch (status = deflate(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags))) {
4341 + case Z_OK:
4342 + case Z_STREAM_END:
4343 + /* cut processed chunk off the buffer */
4344 + if (s->stream.avail_in) {
4345 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4346 + } else {
4347 + phpstr_reset(PHPSTR(s->stream.opaque));
4348 + }
4349 +
4350 + /* size buffer down to actual size */
4351 + *encoded_len -= s->stream.avail_out;
4352 + *encoded = erealloc_rel(*encoded, *encoded_len + 1);
4353 + (*encoded)[*encoded_len] = '\0';
4354 + return SUCCESS;
4355 + }
4356 +
4357 + STR_SET(*encoded, NULL);
4358 + *encoded_len = 0;
4359 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update deflate stream: %s", zError(status));
4360 + return FAILURE;
4361 +}
4362 +/* }}} */
4363 +
4364 +/* {{{ STATUS http_encoding_inflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */
4365 +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)
4366 +{
4367 + int status;
4368 +
4369 + /* append input to buffer */
4370 + phpstr_append(PHPSTR(s->stream.opaque), data, data_len);
4371 +
4372 +retry_raw_inflate:
4373 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4374 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4375 +
4376 + switch (status = http_inflate_rounds(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags), decoded, decoded_len)) {
4377 + case Z_OK:
4378 + case Z_STREAM_END:
4379 + /* cut off */
4380 + if (s->stream.avail_in) {
4381 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4382 + } else {
4383 + phpstr_reset(PHPSTR(s->stream.opaque));
4384 + }
4385 + return SUCCESS;
4386 +
4387 + case Z_DATA_ERROR:
4388 + /* raw deflated data ? */
4389 + if (!(s->flags & HTTP_INFLATE_TYPE_RAW) && !s->stream.total_out) {
4390 + inflateEnd(&s->stream);
4391 + s->flags |= HTTP_INFLATE_TYPE_RAW;
4392 + inflateInit2(&s->stream, HTTP_WINDOW_BITS_RAW);
4393 + goto retry_raw_inflate;
4394 + }
4395 + }
4396 +
4397 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update inflate stream: %s", zError(status));
4398 + return FAILURE;
4399 +}
4400 +/* }}} */
4401 +
4402 +/* {{{ STATUS http_encoding_deflate_stream_flush(http_encoding_stream *, char **, size_t *) */
4403 +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)
4404 +{
4405 + int status;
4406 +
4407 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE;
4408 + *encoded = emalloc_rel(*encoded_len);
4409 +
4410 + s->stream.avail_in = 0;
4411 + s->stream.next_in = NULL;
4412 + s->stream.avail_out = *encoded_len;
4413 + s->stream.next_out = (Bytef *) *encoded;
4414 +
4415 + switch (status = deflate(&s->stream, Z_FULL_FLUSH)) {
4416 + case Z_OK:
4417 + case Z_STREAM_END:
4418 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE - s->stream.avail_out;
4419 + *encoded = erealloc_rel(*encoded, *encoded_len + 1);
4420 + (*encoded)[*encoded_len] = '\0';
4421 + return SUCCESS;
4422 + }
4423 +
4424 + STR_SET(*encoded, NULL);
4425 + *encoded_len = 0;
4426 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to flush deflate stream: %s", zError(status));
4427 + return FAILURE;
4428 +}
4429 +/* }}} */
4430 +
4431 +/* {{{ STATUS http_encoding_inflate_straem_flush(http_encoding_stream *, char **, size_t *) */
4432 +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)
4433 +{
4434 + /* noop */
4435 + *decoded = estrndup("", *decoded_len = 0);
4436 + return SUCCESS;
4437 +}
4438 +/* }}} */
4439 +
4440 +/* {{{ STATUS http_encoding_deflate_stream_finish(http_encoding_stream *, char **, size_t *) */
4441 +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)
4442 +{
4443 + int status;
4444 +
4445 + *encoded_len = HTTP_DEFLATE_BUFFER_SIZE;
4446 + *encoded = emalloc_rel(*encoded_len);
4447 +
4448 + /* deflate remaining input */
4449 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4450 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4451 +
4452 + s->stream.avail_out = *encoded_len;
4453 + s->stream.next_out = (Bytef *) *encoded;
4454 +
4455 + do {
4456 + status = deflate(&s->stream, Z_FINISH);
4457 + } while (Z_OK == status);
4458 +
4459 + if (Z_STREAM_END == status) {
4460 + /* cut processed intp off */
4461 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4462 +
4463 + /* size down */
4464 + *encoded_len -= s->stream.avail_out;
4465 + *encoded = erealloc_rel(*encoded, *encoded_len + 1);
4466 + (*encoded)[*encoded_len] = '\0';
4467 + return SUCCESS;
4468 + }
4469 +
4470 + STR_SET(*encoded, NULL);
4471 + *encoded_len = 0;
4472 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish deflate stream: %s", zError(status));
4473 + return FAILURE;
4474 +}
4475 +/* }}} */
4476 +
4477 +/* {{{ STATUS http_encoding_inflate_stream_finish(http_encoding_stream *, char **, size_t *) */
4478 +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)
4479 +{
4480 + int status;
4481 +
4482 + if (!PHPSTR_LEN(s->stream.opaque)) {
4483 + *decoded = NULL;
4484 + *decoded_len = 0;
4485 + return SUCCESS;
4486 + }
4487 +
4488 + *decoded_len = (PHPSTR_LEN(s->stream.opaque) + 1) * HTTP_INFLATE_ROUNDS;
4489 + *decoded = emalloc_rel(*decoded_len);
4490 +
4491 + /* inflate remaining input */
4492 + s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque);
4493 + s->stream.avail_in = PHPSTR_LEN(s->stream.opaque);
4494 +
4495 + s->stream.avail_out = *decoded_len;
4496 + s->stream.next_out = (Bytef *) *decoded;
4497 +
4498 + if (Z_STREAM_END == (status = inflate(&s->stream, Z_FINISH))) {
4499 + /* cut processed input off */
4500 + phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in);
4501 +
4502 + /* size down */
4503 + *decoded_len -= s->stream.avail_out;
4504 + *decoded = erealloc_rel(*decoded, *decoded_len + 1);
4505 + (*decoded)[*decoded_len] = '\0';
4506 + return SUCCESS;
4507 + }
4508 +
4509 + STR_SET(*decoded, NULL);
4510 + *decoded_len = 0;
4511 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish inflate stream: %s", zError(status));
4512 + return FAILURE;
4513 +}
4514 +/* }}} */
4515 +
4516 +/* {{{ void http_encoding_deflate_stream_dtor(http_encoding_stream *) */
4517 +PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
4518 +{
4519 + if (s) {
4520 + if (s->stream.opaque) {
4521 + phpstr_free((phpstr **) &s->stream.opaque);
4522 + }
4523 + deflateEnd(&s->stream);
4524 + }
4525 +}
4526 +/* }}} */
4527 +
4528 +/* {{{ void http_encoding_inflate_stream_dtor(http_encoding_stream *) */
4529 +PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC)
4530 +{
4531 + if (s) {
4532 + if (s->stream.opaque) {
4533 + phpstr_free((phpstr **) &s->stream.opaque);
4534 + }
4535 + inflateEnd(&s->stream);
4536 + }
4537 +}
4538 +/* }}} */
4539 +
4540 +/* {{{ void http_encoding_deflate_stream_free(http_encoding_stream **) */
4541 +PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC)
4542 +{
4543 + if (s) {
4544 + http_encoding_deflate_stream_dtor(*s);
4545 + if (*s) {
4546 + pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
4547 + }
4548 + *s = NULL;
4549 + }
4550 +}
4551 +/* }}} */
4552 +
4553 +/* {{{ void http_encoding_inflate_stream_free(http_encoding_stream **) */
4554 +PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC)
4555 +{
4556 + if (s) {
4557 + http_encoding_inflate_stream_dtor(*s);
4558 + if (*s) {
4559 + pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT);
4560 + }
4561 + *s = NULL;
4562 + }
4563 +}
4564 +/* }}} */
4565 +
4566 +/* {{{ void http_ob_deflatehandler(char *, uint, char **, uint *, int) */
4567 +void _http_ob_deflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
4568 +{
4569 + int encoding;
4570 +
4571 + *handled_output = NULL;
4572 + *handled_output_len = 0;
4573 +
4574 + if (mode & PHP_OUTPUT_HANDLER_START) {
4575 + int flags;
4576 +
4577 + if (HTTP_G->send.deflate.stream) {
4578 + zend_error(E_ERROR, "ob_deflatehandler() can only be used once");
4579 + return;
4580 + }
4581 +
4582 + HTTP_G->send.deflate.response = 1;
4583 + encoding = http_encoding_response_start(0, 1);
4584 + HTTP_G->send.deflate.response = 0;
4585 +
4586 + switch (encoding) {
4587 + case HTTP_ENCODING_GZIP:
4588 + flags = HTTP_DEFLATE_TYPE_GZIP;
4589 + break;
4590 +
4591 + case HTTP_ENCODING_DEFLATE:
4592 + flags = HTTP_DEFLATE_TYPE_ZLIB;
4593 + break;
4594 +
4595 + default:
4596 + goto deflate_passthru_plain;
4597 + }
4598 +
4599 + flags |= (HTTP_G->send.deflate.start_flags &~ 0xf0);
4600 + HTTP_G->send.deflate.stream = http_encoding_deflate_stream_init(NULL, flags);
4601 + }
4602 +
4603 + if (HTTP_G->send.deflate.stream) {
4604 + if (output_len) {
4605 + size_t tmp_len;
4606 +
4607 + http_encoding_deflate_stream_update((http_encoding_stream *) HTTP_G->send.deflate.stream, output, output_len, handled_output, &tmp_len);
4608 + *handled_output_len = tmp_len;
4609 + }
4610 +
4611 + if (mode & PHP_OUTPUT_HANDLER_END) {
4612 + char *remaining = NULL;
4613 + size_t remaining_len = 0;
4614 +
4615 + http_encoding_deflate_stream_finish((http_encoding_stream *) HTTP_G->send.deflate.stream, &remaining, &remaining_len);
4616 + http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream);
4617 + if (remaining) {
4618 + *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1);
4619 + memcpy(*handled_output + *handled_output_len, remaining, remaining_len);
4620 + (*handled_output)[*handled_output_len += remaining_len] = '\0';
4621 + efree(remaining);
4622 + }
4623 + }
4624 + } else {
4625 +deflate_passthru_plain:
4626 + *handled_output = estrndup(output, *handled_output_len = output_len);
4627 + }
4628 +}
4629 +/* }}} */
4630 +
4631 +/* {{{ void http_ob_inflatehandler(char *, uint, char **, uint *, int) */
4632 +void _http_ob_inflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
4633 +{
4634 + *handled_output = NULL;
4635 + *handled_output_len = 0;
4636 +
4637 + if (mode & PHP_OUTPUT_HANDLER_START) {
4638 + if (HTTP_G->send.inflate.stream) {
4639 + zend_error(E_ERROR, "ob_inflatehandler() can only be used once");
4640 + return;
4641 + }
4642 + HTTP_G->send.inflate.stream = http_encoding_inflate_stream_init(NULL, (HTTP_G->send.inflate.start_flags &~ 0xf0));
4643 + }
4644 +
4645 + if (HTTP_G->send.inflate.stream) {
4646 + if (output_len) {
4647 + size_t tmp_len;
4648 +
4649 + http_encoding_inflate_stream_update((http_encoding_stream *) HTTP_G->send.inflate.stream, output, output_len, handled_output, &tmp_len);
4650 + *handled_output_len = tmp_len;
4651 + }
4652 +
4653 + if (mode & PHP_OUTPUT_HANDLER_END) {
4654 + char *remaining = NULL;
4655 + size_t remaining_len = 0;
4656 +
4657 + http_encoding_inflate_stream_finish((http_encoding_stream *) HTTP_G->send.inflate.stream, &remaining, &remaining_len);
4658 + http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream);
4659 + if (remaining) {
4660 + *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1);
4661 + memcpy(*handled_output + *handled_output_len, remaining, remaining_len);
4662 + (*handled_output)[*handled_output_len += remaining_len] = '\0';
4663 + efree(remaining);
4664 + }
4665 + }
4666 + } else {
4667 + *handled_output = estrndup(output, *handled_output_len = output_len);
4668 + }
4669 +}
4670 +/* }}} */
4671 +
4672 +#endif /* HTTP_HAVE_ZLIB */
4673 +
4674 +/*
4675 + * Local variables:
4676 + * tab-width: 4
4677 + * c-basic-offset: 4
4678 + * End:
4679 + * vim600: noet sw=4 ts=4 fdm=marker
4680 + * vim<600: noet sw=4 ts=4
4681 + */
4682 +
4683 --- /dev/null
4684 +++ b/ext/http/http_exception_object.c
4685 @@ -0,0 +1,186 @@
4686 +/*
4687 + +--------------------------------------------------------------------+
4688 + | PECL :: http |
4689 + +--------------------------------------------------------------------+
4690 + | Redistribution and use in source and binary forms, with or without |
4691 + | modification, are permitted provided that the conditions mentioned |
4692 + | in the accompanying LICENSE file are met. |
4693 + +--------------------------------------------------------------------+
4694 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
4695 + +--------------------------------------------------------------------+
4696 +*/
4697 +
4698 +/* $Id: http_exception_object.c 292841 2009-12-31 08:48:57Z mike $ */
4699 +
4700 +#include "php_http.h"
4701 +
4702 +#ifdef ZEND_ENGINE_2
4703 +
4704 +#ifndef HTTP_DBG_EXCEPTIONS
4705 +# define HTTP_DBG_EXCEPTIONS 0
4706 +#endif
4707 +
4708 +#include "zend_interfaces.h"
4709 +#include "zend_exceptions.h"
4710 +#include "php_http_exception_object.h"
4711 +
4712 +zend_class_entry *http_exception_object_ce;
4713 +zend_class_entry *HTTP_EX_CE(runtime);
4714 +zend_class_entry *HTTP_EX_CE(header);
4715 +zend_class_entry *HTTP_EX_CE(malformed_headers);
4716 +zend_class_entry *HTTP_EX_CE(request_method);
4717 +zend_class_entry *HTTP_EX_CE(message_type);
4718 +zend_class_entry *HTTP_EX_CE(invalid_param);
4719 +zend_class_entry *HTTP_EX_CE(encoding);
4720 +zend_class_entry *HTTP_EX_CE(request);
4721 +zend_class_entry *HTTP_EX_CE(request_pool);
4722 +zend_class_entry *HTTP_EX_CE(socket);
4723 +zend_class_entry *HTTP_EX_CE(response);
4724 +zend_class_entry *HTTP_EX_CE(url);
4725 +zend_class_entry *HTTP_EX_CE(querystring);
4726 +
4727 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpException, method, 0)
4728 +#define HTTP_EXCEPTION_ME(method, visibility) PHP_ME(HttpException, method, HTTP_ARGS(HttpException, method), visibility)
4729 +
4730 +HTTP_EMPTY_ARGS(__toString);
4731 +
4732 +zend_function_entry http_exception_object_fe[] = {
4733 + HTTP_EXCEPTION_ME(__toString, ZEND_ACC_PUBLIC)
4734 +
4735 + EMPTY_FUNCTION_ENTRY
4736 +};
4737 +
4738 +#if HTTP_DBG_EXCEPTIONS
4739 +static void http_exception_hook(zval *ex TSRMLS_DC)
4740 +{
4741 + if (ex) {
4742 + zval *m = zend_read_property(Z_OBJCE_P(ex), ex, "message", lenof("message"), 0 TSRMLS_CC);
4743 + fprintf(stderr, "*** Threw exception '%s'\n", Z_STRVAL_P(m));
4744 + } else {
4745 + fprintf(stderr, "*** Threw NULL exception\n");
4746 + }
4747 +}
4748 +#endif
4749 +
4750 +PHP_MINIT_FUNCTION(http_exception_object)
4751 +{
4752 + HTTP_REGISTER_CLASS(HttpException, http_exception_object, ZEND_EXCEPTION_GET_DEFAULT(), 0);
4753 +
4754 + zend_declare_property_null(HTTP_EX_DEF_CE, "innerException", lenof("innerException"), ZEND_ACC_PUBLIC TSRMLS_CC);
4755 +
4756 + HTTP_REGISTER_EXCEPTION(HttpRuntimeException, HTTP_EX_CE(runtime), HTTP_EX_DEF_CE);
4757 + HTTP_REGISTER_EXCEPTION(HttpInvalidParamException, HTTP_EX_CE(invalid_param), HTTP_EX_DEF_CE);
4758 + HTTP_REGISTER_EXCEPTION(HttpHeaderException, HTTP_EX_CE(header), HTTP_EX_DEF_CE);
4759 + HTTP_REGISTER_EXCEPTION(HttpMalformedHeadersException, HTTP_EX_CE(malformed_headers), HTTP_EX_DEF_CE);
4760 + HTTP_REGISTER_EXCEPTION(HttpRequestMethodException, HTTP_EX_CE(request_method), HTTP_EX_DEF_CE);
4761 + HTTP_REGISTER_EXCEPTION(HttpMessageTypeException, HTTP_EX_CE(message_type), HTTP_EX_DEF_CE);
4762 + HTTP_REGISTER_EXCEPTION(HttpEncodingException, HTTP_EX_CE(encoding), HTTP_EX_DEF_CE);
4763 + HTTP_REGISTER_EXCEPTION(HttpRequestException, HTTP_EX_CE(request), HTTP_EX_DEF_CE);
4764 +
4765 + zend_declare_property_long(HTTP_EX_CE(request), "curlCode", lenof("curlCode"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
4766 +
4767 + HTTP_REGISTER_EXCEPTION(HttpRequestPoolException, HTTP_EX_CE(request_pool), HTTP_EX_DEF_CE);
4768 + HTTP_REGISTER_EXCEPTION(HttpSocketException, HTTP_EX_CE(socket), HTTP_EX_DEF_CE);
4769 + HTTP_REGISTER_EXCEPTION(HttpResponseException, HTTP_EX_CE(response), HTTP_EX_DEF_CE);
4770 + HTTP_REGISTER_EXCEPTION(HttpUrlException, HTTP_EX_CE(url), HTTP_EX_DEF_CE);
4771 + HTTP_REGISTER_EXCEPTION(HttpQueryStringException, HTTP_EX_CE(querystring), HTTP_EX_DEF_CE);
4772 +
4773 + HTTP_LONG_CONSTANT("HTTP_E_RUNTIME", HTTP_E_RUNTIME);
4774 + HTTP_LONG_CONSTANT("HTTP_E_INVALID_PARAM", HTTP_E_INVALID_PARAM);
4775 + HTTP_LONG_CONSTANT("HTTP_E_HEADER", HTTP_E_HEADER);
4776 + HTTP_LONG_CONSTANT("HTTP_E_MALFORMED_HEADERS", HTTP_E_MALFORMED_HEADERS);
4777 + HTTP_LONG_CONSTANT("HTTP_E_REQUEST_METHOD", HTTP_E_REQUEST_METHOD);
4778 + HTTP_LONG_CONSTANT("HTTP_E_MESSAGE_TYPE", HTTP_E_MESSAGE_TYPE);
4779 + HTTP_LONG_CONSTANT("HTTP_E_ENCODING", HTTP_E_ENCODING);
4780 + HTTP_LONG_CONSTANT("HTTP_E_REQUEST", HTTP_E_REQUEST);
4781 + HTTP_LONG_CONSTANT("HTTP_E_REQUEST_POOL", HTTP_E_REQUEST_POOL);
4782 + HTTP_LONG_CONSTANT("HTTP_E_SOCKET", HTTP_E_SOCKET);
4783 + HTTP_LONG_CONSTANT("HTTP_E_RESPONSE", HTTP_E_RESPONSE);
4784 + HTTP_LONG_CONSTANT("HTTP_E_URL", HTTP_E_URL);
4785 + HTTP_LONG_CONSTANT("HTTP_E_QUERYSTRING", HTTP_E_QUERYSTRING);
4786 +
4787 +#if HTTP_DBG_EXCEPTIONS
4788 + zend_throw_exception_hook=http_exception_hook;
4789 +#endif
4790 +
4791 + return SUCCESS;
4792 +}
4793 +
4794 +zend_class_entry *_http_exception_get_default()
4795 +{
4796 + return http_exception_object_ce;
4797 +}
4798 +
4799 +zend_class_entry *_http_exception_get_for_code(long code)
4800 +{
4801 + zend_class_entry *ex = http_exception_object_ce;
4802 +
4803 + switch (code) {
4804 + case HTTP_E_RUNTIME: ex = HTTP_EX_CE(runtime); break;
4805 + case HTTP_E_INVALID_PARAM: ex = HTTP_EX_CE(invalid_param); break;
4806 + case HTTP_E_HEADER: ex = HTTP_EX_CE(header); break;
4807 + case HTTP_E_MALFORMED_HEADERS: ex = HTTP_EX_CE(malformed_headers); break;
4808 + case HTTP_E_REQUEST_METHOD: ex = HTTP_EX_CE(request_method); break;
4809 + case HTTP_E_MESSAGE_TYPE: ex = HTTP_EX_CE(message_type); break;
4810 + case HTTP_E_ENCODING: ex = HTTP_EX_CE(encoding); break;
4811 + case HTTP_E_REQUEST: ex = HTTP_EX_CE(request); break;
4812 + case HTTP_E_REQUEST_POOL: ex = HTTP_EX_CE(request_pool); break;
4813 + case HTTP_E_SOCKET: ex = HTTP_EX_CE(socket); break;
4814 + case HTTP_E_RESPONSE: ex = HTTP_EX_CE(response); break;
4815 + case HTTP_E_URL: ex = HTTP_EX_CE(url); break;
4816 + case HTTP_E_QUERYSTRING: ex = HTTP_EX_CE(querystring); break;
4817 + }
4818 +
4819 + return ex;
4820 +}
4821 +
4822 +PHP_METHOD(HttpException, __toString)
4823 +{
4824 + phpstr full_str;
4825 + zend_class_entry *ce;
4826 + zval *zobj = getThis(), *retval = NULL, *m, *f, *l;
4827 +
4828 + phpstr_init(&full_str);
4829 +
4830 + do {
4831 + ce = Z_OBJCE_P(zobj);
4832 +
4833 + m = zend_read_property(ce, zobj, "message", lenof("message"), 0 TSRMLS_CC);
4834 + f = zend_read_property(ce, zobj, "file", lenof("file"), 0 TSRMLS_CC);
4835 + l = zend_read_property(ce, zobj, "line", lenof("line"), 0 TSRMLS_CC);
4836 +
4837 + if (m && f && l && Z_TYPE_P(m) == IS_STRING && Z_TYPE_P(f) == IS_STRING && Z_TYPE_P(l) == IS_LONG) {
4838 + if (zobj != getThis()) {
4839 + phpstr_appends(&full_str, " inner ");
4840 + }
4841 +
4842 + phpstr_appendf(&full_str, "exception '%.*s' with message '%.*s' in %.*s:%ld" PHP_EOL,
4843 + 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)
4844 + );
4845 + } else {
4846 + break;
4847 + }
4848 +
4849 + zobj = zend_read_property(ce, zobj, "innerException", lenof("innerException"), 0 TSRMLS_CC);
4850 + } while (Z_TYPE_P(zobj) == IS_OBJECT);
4851 +
4852 + if (zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "gettraceasstring", &retval) && Z_TYPE_P(retval) == IS_STRING) {
4853 + phpstr_appends(&full_str, "Stack trace:" PHP_EOL);
4854 + phpstr_append(&full_str, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
4855 + zval_ptr_dtor(&retval);
4856 + }
4857 +
4858 + RETURN_PHPSTR_VAL(&full_str);
4859 +}
4860 +
4861 +#endif
4862 +
4863 +/*
4864 + * Local variables:
4865 + * tab-width: 4
4866 + * c-basic-offset: 4
4867 + * End:
4868 + * vim600: noet sw=4 ts=4 fdm=marker
4869 + * vim<600: noet sw=4 ts=4
4870 + */
4871 +
4872 --- /dev/null
4873 +++ b/ext/http/http_filter_api.c
4874 @@ -0,0 +1,534 @@
4875 +/*
4876 + +--------------------------------------------------------------------+
4877 + | PECL :: http |
4878 + +--------------------------------------------------------------------+
4879 + | Redistribution and use in source and binary forms, with or without |
4880 + | modification, are permitted provided that the conditions mentioned |
4881 + | in the accompanying LICENSE file are met. |
4882 + +--------------------------------------------------------------------+
4883 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
4884 + +--------------------------------------------------------------------+
4885 +*/
4886 +
4887 +/* $Id: http_filter_api.c 292841 2009-12-31 08:48:57Z mike $ */
4888 +
4889 +#define HTTP_WANT_ZLIB
4890 +#include "php_http.h"
4891 +
4892 +#ifdef ZEND_ENGINE_2
4893 +
4894 +#include "php_streams.h"
4895 +#include "php_http_api.h"
4896 +#include "php_http_encoding_api.h"
4897 +#include "php_http_filter_api.h"
4898 +
4899 +PHP_MINIT_FUNCTION(http_filter)
4900 +{
4901 + php_stream_filter_register_factory("http.*", &http_filter_factory TSRMLS_CC);
4902 + return SUCCESS;
4903 +}
4904 +
4905 +/*
4906 + -
4907 +*/
4908 +
4909 +#define HTTP_FILTER_PARAMS \
4910 + php_stream *stream, \
4911 + php_stream_filter *this, \
4912 + php_stream_bucket_brigade *buckets_in, \
4913 + php_stream_bucket_brigade *buckets_out, \
4914 + size_t *bytes_consumed, int flags \
4915 + TSRMLS_DC
4916 +#define HTTP_FILTER_OP(filter) \
4917 + http_filter_op_ ##filter
4918 +#define HTTP_FILTER_OPS(filter) \
4919 + php_stream_filter_ops HTTP_FILTER_OP(filter)
4920 +#define HTTP_FILTER_DTOR(filter) \
4921 + http_filter_ ##filter## _dtor
4922 +#define HTTP_FILTER_DESTRUCTOR(filter) \
4923 + void HTTP_FILTER_DTOR(filter)(php_stream_filter *this TSRMLS_DC)
4924 +#define HTTP_FILTER_FUNC(filter) \
4925 + http_filter_ ##filter
4926 +#define HTTP_FILTER_FUNCTION(filter) \
4927 + php_stream_filter_status_t HTTP_FILTER_FUNC(filter)(HTTP_FILTER_PARAMS)
4928 +#define HTTP_FILTER_BUFFER(filter) \
4929 + http_filter_ ##filter## _buffer
4930 +
4931 +#define NEW_BUCKET(data, length) \
4932 + { \
4933 + char *__data; \
4934 + php_stream_bucket *__buck; \
4935 + \
4936 + __data = pemalloc(length, this->is_persistent); \
4937 + if (!__data) { \
4938 + return PSFS_ERR_FATAL; \
4939 + } \
4940 + memcpy(__data, data, length); \
4941 + \
4942 + __buck = php_stream_bucket_new(stream, __data, length, 1, this->is_persistent TSRMLS_CC); \
4943 + if (!__buck) { \
4944 + pefree(__data, this->is_persistent); \
4945 + return PSFS_ERR_FATAL; \
4946 + } \
4947 + \
4948 + php_stream_bucket_append(buckets_out, __buck TSRMLS_CC); \
4949 + }
4950 +
4951 +typedef struct _http_chunked_decode_filter_buffer_t {
4952 + phpstr buffer;
4953 + ulong hexlen;
4954 +} HTTP_FILTER_BUFFER(chunked_decode);
4955 +
4956 +#ifdef HTTP_HAVE_ZLIB
4957 +typedef http_encoding_stream HTTP_FILTER_BUFFER(deflate);
4958 +typedef http_encoding_stream HTTP_FILTER_BUFFER(inflate);
4959 +#endif /* HTTP_HAVE_ZLIB */
4960 +
4961 +
4962 +static HTTP_FILTER_FUNCTION(chunked_decode)
4963 +{
4964 + int out_avail = 0;
4965 + php_stream_bucket *ptr, *nxt;
4966 + HTTP_FILTER_BUFFER(chunked_decode) *buffer = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract);
4967 +
4968 + if (bytes_consumed) {
4969 + *bytes_consumed = 0;
4970 + }
4971 +
4972 + /* new data available? */
4973 + if (buckets_in->head) {
4974 +
4975 + /* fetch available bucket data */
4976 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
4977 + nxt = ptr->next;
4978 + if (bytes_consumed) {
4979 + *bytes_consumed += ptr->buflen;
4980 + }
4981 +
4982 + if (PHPSTR_NOMEM == phpstr_append(PHPSTR(buffer), ptr->buf, ptr->buflen)) {
4983 + return PSFS_ERR_FATAL;
4984 + }
4985 +
4986 + php_stream_bucket_unlink(ptr TSRMLS_CC);
4987 + php_stream_bucket_delref(ptr TSRMLS_CC);
4988 + }
4989 + }
4990 + if (!phpstr_fix(PHPSTR(buffer))) {
4991 + return PSFS_ERR_FATAL;
4992 + }
4993 +
4994 + /* we have data in our buffer */
4995 + while (PHPSTR_LEN(buffer)) {
4996 +
4997 + /* we already know the size of the chunk and are waiting for data */
4998 + if (buffer->hexlen) {
4999 +
5000 + /* not enough data buffered */
5001 + if (PHPSTR_LEN(buffer) < buffer->hexlen) {
5002 +
5003 + /* flush anyway? */
5004 + if (flags & PSFS_FLAG_FLUSH_INC) {
5005 +
5006 + /* flush all data (should only be chunk data) */
5007 + out_avail = 1;
5008 + NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer));
5009 +
5010 + /* waiting for less data now */
5011 + buffer->hexlen -= PHPSTR_LEN(buffer);
5012 + /* no more buffered data */
5013 + phpstr_reset(PHPSTR(buffer));
5014 + /* break */
5015 + }
5016 +
5017 + /* we have too less data and don't need to flush */
5018 + else {
5019 + break;
5020 + }
5021 + }
5022 +
5023 + /* we seem to have all data of the chunk */
5024 + else {
5025 + out_avail = 1;
5026 + NEW_BUCKET(PHPSTR_VAL(buffer), buffer->hexlen);
5027 +
5028 + /* remove outgoing data from the buffer */
5029 + phpstr_cut(PHPSTR(buffer), 0, buffer->hexlen);
5030 + /* reset hexlen */
5031 + buffer->hexlen = 0;
5032 + /* continue */
5033 + }
5034 + }
5035 +
5036 + /* we don't know the length of the chunk yet */
5037 + else {
5038 + size_t off = 0;
5039 +
5040 + /* ignore preceeding CRLFs (too loose?) */
5041 + while (off < PHPSTR_LEN(buffer) && (
5042 + PHPSTR_VAL(buffer)[off] == '\n' ||
5043 + PHPSTR_VAL(buffer)[off] == '\r')) {
5044 + ++off;
5045 + }
5046 + if (off) {
5047 + phpstr_cut(PHPSTR(buffer), 0, off);
5048 + }
5049 +
5050 + /* still data there? */
5051 + if (PHPSTR_LEN(buffer)) {
5052 + int eollen;
5053 + const char *eolstr;
5054 +
5055 + /* we need eol, so we can be sure we have all hex digits */
5056 + phpstr_fix(PHPSTR(buffer));
5057 + if ((eolstr = http_locate_eol(PHPSTR_VAL(buffer), &eollen))) {
5058 + char *stop = NULL;
5059 +
5060 + /* read in chunk size */
5061 + buffer->hexlen = strtoul(PHPSTR_VAL(buffer), &stop, 16);
5062 +
5063 + /* if strtoul() stops at the beginning of the buffered data
5064 + there's domething oddly wrong, i.e. bad input */
5065 + if (stop == PHPSTR_VAL(buffer)) {
5066 + return PSFS_ERR_FATAL;
5067 + }
5068 +
5069 + /* cut out <chunk size hex><chunk extension><eol> */
5070 + phpstr_cut(PHPSTR(buffer), 0, eolstr + eollen - PHPSTR_VAL(buffer));
5071 + /* buffer->hexlen is 0 now or contains the size of the next chunk */
5072 + /* continue */
5073 + } else {
5074 + /* we have not enough data buffered to read in chunk size */
5075 + break;
5076 + }
5077 + }
5078 + /* break */
5079 + }
5080 + }
5081 +
5082 + /* flush before close, but only if we are already waiting for more data */
5083 + if ((flags & PSFS_FLAG_FLUSH_CLOSE) && buffer->hexlen && PHPSTR_LEN(buffer)) {
5084 + out_avail = 1;
5085 + NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer));
5086 + phpstr_reset(PHPSTR(buffer));
5087 + buffer->hexlen = 0;
5088 + }
5089 +
5090 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5091 +}
5092 +
5093 +static HTTP_FILTER_DESTRUCTOR(chunked_decode)
5094 +{
5095 + HTTP_FILTER_BUFFER(chunked_decode) *b = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract);
5096 +
5097 + phpstr_dtor(PHPSTR(b));
5098 + pefree(b, this->is_persistent);
5099 +}
5100 +
5101 +static HTTP_FILTER_FUNCTION(chunked_encode)
5102 +{
5103 + int out_avail = 0;
5104 + php_stream_bucket *ptr, *nxt;
5105 +
5106 + if (bytes_consumed) {
5107 + *bytes_consumed = 0;
5108 + }
5109 +
5110 + /* new data available? */
5111 + if (buckets_in->head) {
5112 + phpstr buf;
5113 + out_avail = 1;
5114 +
5115 + phpstr_init(&buf);
5116 +
5117 + /* fetch available bucket data */
5118 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
5119 + nxt = ptr->next;
5120 + if (bytes_consumed) {
5121 + *bytes_consumed += ptr->buflen;
5122 + }
5123 +
5124 + phpstr_appendf(&buf, "%x" HTTP_CRLF, ptr->buflen);
5125 + phpstr_append(&buf, ptr->buf, ptr->buflen);
5126 + phpstr_appends(&buf, HTTP_CRLF);
5127 +
5128 + /* pass through */
5129 + NEW_BUCKET(PHPSTR_VAL(&buf), PHPSTR_LEN(&buf));
5130 + /* reset */
5131 + phpstr_reset(&buf);
5132 +
5133 + php_stream_bucket_unlink(ptr TSRMLS_CC);
5134 + php_stream_bucket_delref(ptr TSRMLS_CC);
5135 + }
5136 +
5137 + /* free buffer */
5138 + phpstr_dtor(&buf);
5139 + }
5140 +
5141 + /* terminate with "0" */
5142 + if (flags & PSFS_FLAG_FLUSH_CLOSE) {
5143 + out_avail = 1;
5144 + NEW_BUCKET("0" HTTP_CRLF, lenof("0" HTTP_CRLF));
5145 + }
5146 +
5147 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5148 +}
5149 +
5150 +static HTTP_FILTER_OPS(chunked_decode) = {
5151 + HTTP_FILTER_FUNC(chunked_decode),
5152 + HTTP_FILTER_DTOR(chunked_decode),
5153 + "http.chunked_decode"
5154 +};
5155 +
5156 +static HTTP_FILTER_OPS(chunked_encode) = {
5157 + HTTP_FILTER_FUNC(chunked_encode),
5158 + NULL,
5159 + "http.chunked_encode"
5160 +};
5161 +
5162 +#ifdef HTTP_HAVE_ZLIB
5163 +
5164 +static HTTP_FILTER_FUNCTION(deflate)
5165 +{
5166 + int out_avail = 0;
5167 + php_stream_bucket *ptr, *nxt;
5168 + HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
5169 +
5170 + if (bytes_consumed) {
5171 + *bytes_consumed = 0;
5172 + }
5173 +
5174 + /* new data available? */
5175 + if (buckets_in->head) {
5176 +
5177 + /* fetch available bucket data */
5178 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
5179 + char *encoded = NULL;
5180 + size_t encoded_len = 0;
5181 +
5182 + nxt = ptr->next;
5183 + if (bytes_consumed) {
5184 + *bytes_consumed += ptr->buflen;
5185 + }
5186 +
5187 + if (ptr->buflen) {
5188 + http_encoding_deflate_stream_update(buffer, ptr->buf, ptr->buflen, &encoded, &encoded_len);
5189 + if (encoded) {
5190 + if (encoded_len) {
5191 + out_avail = 1;
5192 + NEW_BUCKET(encoded, encoded_len);
5193 + }
5194 + efree(encoded);
5195 + }
5196 + }
5197 +
5198 + php_stream_bucket_unlink(ptr TSRMLS_CC);
5199 + php_stream_bucket_delref(ptr TSRMLS_CC);
5200 + }
5201 + }
5202 +
5203 + /* flush & close */
5204 + if (flags & PSFS_FLAG_FLUSH_INC) {
5205 + char *encoded = NULL;
5206 + size_t encoded_len = 0;
5207 +
5208 + http_encoding_deflate_stream_flush(buffer, &encoded, &encoded_len);
5209 + if (encoded) {
5210 + if (encoded_len) {
5211 + out_avail = 1;
5212 + NEW_BUCKET(encoded, encoded_len);
5213 + }
5214 + efree(encoded);
5215 + }
5216 + }
5217 +
5218 + if (flags & PSFS_FLAG_FLUSH_CLOSE) {
5219 + char *encoded = NULL;
5220 + size_t encoded_len = 0;
5221 +
5222 + http_encoding_deflate_stream_finish(buffer, &encoded, &encoded_len);
5223 + if (encoded) {
5224 + if (encoded_len) {
5225 + out_avail = 1;
5226 + NEW_BUCKET(encoded, encoded_len);
5227 + }
5228 + efree(encoded);
5229 + }
5230 + }
5231 +
5232 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5233 +}
5234 +
5235 +static HTTP_FILTER_FUNCTION(inflate)
5236 +{
5237 + int out_avail = 0;
5238 + php_stream_bucket *ptr, *nxt;
5239 + HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
5240 +
5241 + if (bytes_consumed) {
5242 + *bytes_consumed = 0;
5243 + }
5244 +
5245 + /* new data available? */
5246 + if (buckets_in->head) {
5247 +
5248 + /* fetch available bucket data */
5249 + for (ptr = buckets_in->head; ptr; ptr = nxt) {
5250 + char *decoded = NULL;
5251 + size_t decoded_len = 0;
5252 +
5253 + nxt = ptr->next;
5254 + if (bytes_consumed) {
5255 + *bytes_consumed += ptr->buflen;
5256 + }
5257 +
5258 + if (ptr->buflen) {
5259 + http_encoding_inflate_stream_update(buffer, ptr->buf, ptr->buflen, &decoded, &decoded_len);
5260 + if (decoded) {
5261 + if (decoded_len) {
5262 + out_avail = 1;
5263 + NEW_BUCKET(decoded, decoded_len);
5264 + }
5265 + efree(decoded);
5266 + }
5267 + }
5268 +
5269 + php_stream_bucket_unlink(ptr TSRMLS_CC);
5270 + php_stream_bucket_delref(ptr TSRMLS_CC);
5271 + }
5272 + }
5273 +
5274 + /* flush & close */
5275 + if (flags & PSFS_FLAG_FLUSH_INC) {
5276 + char *decoded = NULL;
5277 + size_t decoded_len = 0;
5278 +
5279 + http_encoding_inflate_stream_flush(buffer, &decoded, &decoded_len);
5280 + if (decoded) {
5281 + if (decoded_len) {
5282 + out_avail = 1;
5283 + NEW_BUCKET(decoded, decoded_len);
5284 + }
5285 + efree(decoded);
5286 + }
5287 + }
5288 +
5289 + if (flags & PSFS_FLAG_FLUSH_CLOSE) {
5290 + char *decoded = NULL;
5291 + size_t decoded_len = 0;
5292 +
5293 + http_encoding_inflate_stream_finish(buffer, &decoded, &decoded_len);
5294 + if (decoded) {
5295 + if (decoded_len) {
5296 + out_avail = 1;
5297 + NEW_BUCKET(decoded, decoded_len);
5298 + }
5299 + efree(decoded);
5300 + }
5301 + }
5302 +
5303 + return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME;
5304 +}
5305 +
5306 +static HTTP_FILTER_DESTRUCTOR(deflate)
5307 +{
5308 + HTTP_FILTER_BUFFER(deflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract;
5309 + http_encoding_deflate_stream_free(&buffer);
5310 +}
5311 +
5312 +static HTTP_FILTER_DESTRUCTOR(inflate)
5313 +{
5314 + HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract;
5315 + http_encoding_inflate_stream_free(&buffer);
5316 +}
5317 +
5318 +static HTTP_FILTER_OPS(deflate) = {
5319 + HTTP_FILTER_FUNC(deflate),
5320 + HTTP_FILTER_DTOR(deflate),
5321 + "http.deflate"
5322 +};
5323 +
5324 +static HTTP_FILTER_OPS(inflate) = {
5325 + HTTP_FILTER_FUNC(inflate),
5326 + HTTP_FILTER_DTOR(inflate),
5327 + "http.inflate"
5328 +};
5329 +
5330 +#endif /* HTTP_HAVE_ZLIB */
5331 +
5332 +static php_stream_filter *http_filter_create(const char *name, zval *params, int p TSRMLS_DC)
5333 +{
5334 + zval **tmp = &params;
5335 + php_stream_filter *f = NULL;
5336 +
5337 + if (!strcasecmp(name, "http.chunked_decode")) {
5338 + HTTP_FILTER_BUFFER(chunked_decode) *b = NULL;
5339 +
5340 + if ((b = pecalloc(1, sizeof(HTTP_FILTER_BUFFER(chunked_decode)), p))) {
5341 + phpstr_init_ex(PHPSTR(b), 4096, p ? PHPSTR_INIT_PERSISTENT : 0);
5342 + if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_decode), b, p))) {
5343 + pefree(b, p);
5344 + }
5345 + }
5346 + } else
5347 +
5348 + if (!strcasecmp(name, "http.chunked_encode")) {
5349 + f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_encode), NULL, p);
5350 +#ifdef HTTP_HAVE_ZLIB
5351 + } else
5352 +
5353 + if (!strcasecmp(name, "http.inflate")) {
5354 + int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
5355 + HTTP_FILTER_BUFFER(inflate) *b = NULL;
5356 +
5357 + if ((b = http_encoding_inflate_stream_init(NULL, flags))) {
5358 + if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(inflate), b, p))) {
5359 + http_encoding_inflate_stream_free(&b);
5360 + }
5361 + }
5362 + } else
5363 +
5364 + if (!strcasecmp(name, "http.deflate")) {
5365 + int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0;
5366 + HTTP_FILTER_BUFFER(deflate) *b = NULL;
5367 +
5368 + if (params) {
5369 + switch (Z_TYPE_P(params)) {
5370 + case IS_ARRAY:
5371 + case IS_OBJECT:
5372 + if (SUCCESS != zend_hash_find(HASH_OF(params), "flags", sizeof("flags"), (void *) &tmp)) {
5373 + break;
5374 + }
5375 + default:
5376 + {
5377 + zval *num = http_zsep(IS_LONG, *tmp);
5378 +
5379 + flags |= (Z_LVAL_P(num) & 0x0fffffff);
5380 + zval_ptr_dtor(&num);
5381 + }
5382 + }
5383 + }
5384 + if ((b = http_encoding_deflate_stream_init(NULL, flags))) {
5385 + if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(deflate), b, p))) {
5386 + http_encoding_deflate_stream_free(&b);
5387 + }
5388 + }
5389 +#endif /* HTTP_HAVE_ZLIB */
5390 + }
5391 +
5392 + return f;
5393 +}
5394 +
5395 +php_stream_filter_factory http_filter_factory = {
5396 + http_filter_create
5397 +};
5398 +
5399 +#endif /* ZEND_ENGINE_2 */
5400 +
5401 +/*
5402 + * Local variables:
5403 + * tab-width: 4
5404 + * c-basic-offset: 4
5405 + * End:
5406 + * vim600: noet sw=4 ts=4 fdm=marker
5407 + * vim<600: noet sw=4 ts=4
5408 + */
5409 --- /dev/null
5410 +++ b/ext/http/http_functions.c
5411 @@ -0,0 +1,1424 @@
5412 +/*
5413 + +--------------------------------------------------------------------+
5414 + | PECL :: http |
5415 + +--------------------------------------------------------------------+
5416 + | Redistribution and use in source and binary forms, with or without |
5417 + | modification, are permitted provided that the conditions mentioned |
5418 + | in the accompanying LICENSE file are met. |
5419 + +--------------------------------------------------------------------+
5420 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
5421 + +--------------------------------------------------------------------+
5422 +*/
5423 +
5424 +/* $Id: http_functions.c 300301 2010-06-09 08:30:34Z mike $ */
5425 +
5426 +#define HTTP_WANT_SAPI
5427 +#define HTTP_WANT_CURL
5428 +#define HTTP_WANT_ZLIB
5429 +#include "php_http.h"
5430 +
5431 +#include "php_ini.h"
5432 +#include "ext/standard/php_string.h"
5433 +#include "zend_operators.h"
5434 +
5435 +#ifdef HTTP_HAVE_SESSION
5436 +# include "ext/session/php_session.h"
5437 +#endif
5438 +
5439 +#include "php_http_api.h"
5440 +#include "php_http_cache_api.h"
5441 +#include "php_http_cookie_api.h"
5442 +#include "php_http_date_api.h"
5443 +#include "php_http_encoding_api.h"
5444 +#include "php_http_headers_api.h"
5445 +#include "php_http_message_api.h"
5446 +#include "php_http_request_api.h"
5447 +#include "php_http_request_method_api.h"
5448 +#include "php_http_persistent_handle_api.h"
5449 +#include "php_http_send_api.h"
5450 +#include "php_http_url_api.h"
5451 +
5452 +/* {{{ proto string http_date([int timestamp])
5453 + Compose a valid HTTP date regarding RFC 1123 looking like: "Wed, 22 Dec 2004 11:34:47 GMT" */
5454 +PHP_FUNCTION(http_date)
5455 +{
5456 + long t = -1;
5457 + char *date;
5458 +
5459 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
5460 + RETURN_FALSE;
5461 + }
5462 +
5463 + if (t == -1) {
5464 + t = HTTP_G->request.time;
5465 + }
5466 +
5467 + if (!(date = http_date(t))) {
5468 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Could not compose date of timestamp %ld", t);
5469 + RETURN_FALSE;
5470 + }
5471 +
5472 + RETURN_STRING(date, 0);
5473 +}
5474 +/* }}} */
5475 +
5476 +/* {{{ proto string http_build_url([mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV[, array &new_url]]]])
5477 + Build an URL. */
5478 +PHP_FUNCTION(http_build_url)
5479 +{
5480 + char *url_str = NULL;
5481 + size_t url_len = 0;
5482 + long flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV;
5483 + zval *z_old_url = NULL, *z_new_url = NULL, *z_composed_url = NULL;
5484 + php_url *old_url = NULL, *new_url = NULL, *composed_url = NULL;
5485 +
5486 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z!/lz", &z_old_url, &z_new_url, &flags, &z_composed_url) != SUCCESS) {
5487 + RETURN_FALSE;
5488 + }
5489 +
5490 + if (z_new_url) {
5491 + if (Z_TYPE_P(z_new_url) == IS_ARRAY || Z_TYPE_P(z_new_url) == IS_OBJECT) {
5492 + new_url = http_url_from_struct(NULL, HASH_OF(z_new_url));
5493 + } else {
5494 + convert_to_string(z_new_url);
5495 + if (!(new_url = php_url_parse_ex(Z_STRVAL_P(z_new_url), Z_STRLEN_P(z_new_url)))) {
5496 + http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_new_url));
5497 + RETURN_FALSE;
5498 + }
5499 + }
5500 + }
5501 +
5502 + if (z_old_url) {
5503 + if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) {
5504 + old_url = http_url_from_struct(NULL, HASH_OF(z_old_url));
5505 + } else {
5506 + convert_to_string(z_old_url);
5507 + if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) {
5508 + if (new_url) {
5509 + php_url_free(new_url);
5510 + }
5511 + http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_old_url));
5512 + RETURN_FALSE;
5513 + }
5514 + }
5515 + }
5516 +
5517 + if (z_composed_url) {
5518 + http_build_url(flags, old_url, new_url, &composed_url, &url_str, &url_len);
5519 + http_url_tostruct(composed_url, z_composed_url);
5520 + php_url_free(composed_url);
5521 + } else {
5522 + http_build_url(flags, old_url, new_url, NULL, &url_str, &url_len);
5523 + }
5524 +
5525 + if (new_url) {
5526 + php_url_free(new_url);
5527 + }
5528 + if (old_url) {
5529 + php_url_free(old_url);
5530 + }
5531 +
5532 + RETURN_STRINGL(url_str, url_len, 0);
5533 +}
5534 +/* }}} */
5535 +
5536 +/* {{{ proto string http_build_str(array query [, string prefix[, string arg_separator]])
5537 + Opponent to parse_str(). */
5538 +PHP_FUNCTION(http_build_str)
5539 +{
5540 + zval *formdata;
5541 + char *prefix = NULL, *arg_sep = INI_STR("arg_separator.output");
5542 + int prefix_len = 0, arg_sep_len = strlen(arg_sep);
5543 + phpstr formstr;
5544 +
5545 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) {
5546 + RETURN_FALSE;
5547 + }
5548 +
5549 + if (!arg_sep_len) {
5550 + arg_sep = HTTP_URL_ARGSEP;
5551 + arg_sep_len = lenof(HTTP_URL_ARGSEP);
5552 + }
5553 +
5554 + phpstr_init(&formstr);
5555 + if (SUCCESS != http_urlencode_hash_recursive(HASH_OF(formdata), &formstr, arg_sep, arg_sep_len, prefix, prefix_len)) {
5556 + RETURN_FALSE;
5557 + }
5558 +
5559 + if (!formstr.used) {
5560 + phpstr_dtor(&formstr);
5561 + RETURN_NULL();
5562 + }
5563 +
5564 + RETURN_PHPSTR_VAL(&formstr);
5565 +}
5566 +/* }}} */
5567 +
5568 +#define HTTP_DO_NEGOTIATE_DEFAULT(supported) \
5569 + { \
5570 + zval **value; \
5571 + \
5572 + zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \
5573 + if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void *) &value)) { \
5574 + RETVAL_ZVAL(*value, 1, 0); \
5575 + } else { \
5576 + RETVAL_NULL(); \
5577 + } \
5578 + }
5579 +
5580 +#define HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array) \
5581 + HTTP_DO_NEGOTIATE_DEFAULT(supported); \
5582 + if (rs_array) { \
5583 + HashPosition pos; \
5584 + zval **value_ptr; \
5585 + \
5586 + FOREACH_VAL(pos, supported, value_ptr) { \
5587 + zval *value = http_zsep(IS_STRING, *value_ptr); \
5588 + add_assoc_double(rs_array, Z_STRVAL_P(value), 1.0); \
5589 + zval_ptr_dtor(&value); \
5590 + } \
5591 + }
5592 +
5593 +#define HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array) \
5594 + { \
5595 + char *key; \
5596 + uint key_len; \
5597 + ulong idx; \
5598 + \
5599 + if (zend_hash_num_elements(result) && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \
5600 + RETVAL_STRINGL(key, key_len-1, 0); \
5601 + } else { \
5602 + HTTP_DO_NEGOTIATE_DEFAULT(supported); \
5603 + } \
5604 + \
5605 + if (rs_array) { \
5606 + zend_hash_copy(Z_ARRVAL_P(rs_array), result, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); \
5607 + } \
5608 + \
5609 + zend_hash_destroy(result); \
5610 + FREE_HASHTABLE(result); \
5611 + }
5612 +
5613 +#define HTTP_DO_NEGOTIATE(type, supported, rs_array) \
5614 + { \
5615 + HashTable *result; \
5616 + if ((result = http_negotiate_ ##type(supported))) { \
5617 + HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array); \
5618 + } else { \
5619 + HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array); \
5620 + } \
5621 + }
5622 +
5623 +/* {{{ proto string http_negotiate_language(array supported[, array &result])
5624 + Negotiate the clients preferred language. */
5625 +PHP_FUNCTION(http_negotiate_language)
5626 +{
5627 + zval *supported, *rs_array = NULL;
5628 +
5629 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
5630 + RETURN_FALSE;
5631 + }
5632 +
5633 + if (rs_array) {
5634 + zval_dtor(rs_array);
5635 + array_init(rs_array);
5636 + }
5637 +
5638 + HTTP_DO_NEGOTIATE(language, supported, rs_array);
5639 +}
5640 +/* }}} */
5641 +
5642 +/* {{{ proto string http_negotiate_charset(array supported[, array &result])
5643 + Negotiate the clients preferred charset. */
5644 +PHP_FUNCTION(http_negotiate_charset)
5645 +{
5646 + zval *supported, *rs_array = NULL;
5647 +
5648 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
5649 + RETURN_FALSE;
5650 + }
5651 +
5652 + if (rs_array) {
5653 + zval_dtor(rs_array);
5654 + array_init(rs_array);
5655 + }
5656 +
5657 + HTTP_DO_NEGOTIATE(charset, supported, rs_array);
5658 +}
5659 +/* }}} */
5660 +
5661 +/* {{{ proto string http_negotiate_content_type(array supported[, array &result])
5662 + Negotiate the clients preferred content type. */
5663 +PHP_FUNCTION(http_negotiate_content_type)
5664 +{
5665 + zval *supported, *rs_array = NULL;
5666 +
5667 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array)) {
5668 + RETURN_FALSE;
5669 + }
5670 +
5671 + if (rs_array) {
5672 + zval_dtor(rs_array);
5673 + array_init(rs_array);
5674 + }
5675 +
5676 + HTTP_DO_NEGOTIATE(content_type, supported, rs_array);
5677 +}
5678 +/* }}} */
5679 +
5680 +/* {{{ proto string http_negotiate(mixed value, array supported[, array &result])
5681 + Negotiate the user supplied value. */
5682 +PHP_FUNCTION(http_negotiate)
5683 +{
5684 + zval *value, *supported, *rs_array = NULL;
5685 + HashTable *rs;
5686 +
5687 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|z", &value, &supported, &rs_array)) {
5688 + RETURN_FALSE;
5689 + }
5690 +
5691 + if (rs_array) {
5692 + zval_dtor(rs_array);
5693 + array_init(rs_array);
5694 + }
5695 +
5696 + if ((rs = http_negotiate_z(value, Z_ARRVAL_P(supported), http_negotiate_default_func))) {
5697 + HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs, supported, rs_array);
5698 + } else {
5699 + HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array);
5700 + }
5701 +}
5702 +/* }}} */
5703 +
5704 +/* {{{ proto bool http_send_status(int status)
5705 + Send HTTP status code. */
5706 +PHP_FUNCTION(http_send_status)
5707 +{
5708 + long status = 0;
5709 +
5710 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) {
5711 + RETURN_FALSE;
5712 + }
5713 + if (status < 100 || status > 510) {
5714 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
5715 + RETURN_FALSE;
5716 + }
5717 +
5718 + RETURN_SUCCESS(http_send_status(status));
5719 +}
5720 +/* }}} */
5721 +
5722 +/* {{{ proto bool http_send_last_modified([int timestamp])
5723 + Send a "Last-Modified" header with a valid HTTP date. */
5724 +PHP_FUNCTION(http_send_last_modified)
5725 +{
5726 + long t = -1;
5727 +
5728 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
5729 + RETURN_FALSE;
5730 + }
5731 +
5732 + if (t == -1) {
5733 + t = HTTP_G->request.time;
5734 + }
5735 +
5736 + RETURN_SUCCESS(http_send_last_modified(t));
5737 +}
5738 +/* }}} */
5739 +
5740 +/* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream'])
5741 + Send the Content-Type of the sent entity. This is particularly important if you use the http_send() API. */
5742 +PHP_FUNCTION(http_send_content_type)
5743 +{
5744 + char *ct = "application/x-octetstream";
5745 + int ct_len = lenof("application/x-octetstream");
5746 +
5747 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) {
5748 + RETURN_FALSE;
5749 + }
5750 +
5751 + RETURN_SUCCESS(http_send_content_type(ct, ct_len));
5752 +}
5753 +/* }}} */
5754 +
5755 +/* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false])
5756 + Send the Content-Disposition. */
5757 +PHP_FUNCTION(http_send_content_disposition)
5758 +{
5759 + char *filename;
5760 + int f_len;
5761 + zend_bool send_inline = 0;
5762 +
5763 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) {
5764 + RETURN_FALSE;
5765 + }
5766 + RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline));
5767 +}
5768 +/* }}} */
5769 +
5770 +/* {{{ proto bool http_match_modified([int timestamp[, bool for_range = false]])
5771 + Matches the given unix timestamp against the clients "If-Modified-Since" resp. "If-Unmodified-Since" HTTP headers. */
5772 +PHP_FUNCTION(http_match_modified)
5773 +{
5774 + long t = -1;
5775 + zend_bool for_range = 0;
5776 +
5777 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &t, &for_range) != SUCCESS) {
5778 + RETURN_FALSE;
5779 + }
5780 +
5781 + // current time if not supplied (senseless though)
5782 + if (t == -1) {
5783 + t = HTTP_G->request.time;
5784 + }
5785 +
5786 + if (for_range) {
5787 + RETURN_BOOL(http_match_last_modified("HTTP_IF_UNMODIFIED_SINCE", t));
5788 + }
5789 + RETURN_BOOL(http_match_last_modified("HTTP_IF_MODIFIED_SINCE", t));
5790 +}
5791 +/* }}} */
5792 +
5793 +/* {{{ proto bool http_match_etag(string etag[, bool for_range = false])
5794 + Matches the given ETag against the clients "If-Match" resp. "If-None-Match" HTTP headers. */
5795 +PHP_FUNCTION(http_match_etag)
5796 +{
5797 + int etag_len;
5798 + char *etag;
5799 + zend_bool for_range = 0;
5800 +
5801 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &etag, &etag_len, &for_range) != SUCCESS) {
5802 + RETURN_FALSE;
5803 + }
5804 +
5805 + if (for_range) {
5806 + RETURN_BOOL(http_match_etag("HTTP_IF_MATCH", etag));
5807 + }
5808 + RETURN_BOOL(http_match_etag("HTTP_IF_NONE_MATCH", etag));
5809 +}
5810 +/* }}} */
5811 +
5812 +/* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]])
5813 + Attempts to cache the sent entity by its last modification date. */
5814 +PHP_FUNCTION(http_cache_last_modified)
5815 +{
5816 + long last_modified = 0, send_modified = 0, t;
5817 + zval *zlm;
5818 +
5819 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
5820 + RETURN_FALSE;
5821 + }
5822 +
5823 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
5824 +
5825 + t = HTTP_G->request.time;
5826 +
5827 + /* 0 or omitted */
5828 + if (!last_modified) {
5829 + /* does the client have? (att: caching "forever") */
5830 + if ((zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE", 1))) {
5831 + last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm));
5832 + /* send current time */
5833 + } else {
5834 + send_modified = t;
5835 + }
5836 + /* negative value is supposed to be expiration time */
5837 + } else if (last_modified < 0) {
5838 + last_modified += t;
5839 + send_modified = t;
5840 + /* send supplied time explicitly */
5841 + } else {
5842 + send_modified = last_modified;
5843 + }
5844 +
5845 + RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
5846 +}
5847 +/* }}} */
5848 +
5849 +/* {{{ proto bool http_cache_etag([string etag])
5850 + 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". */
5851 +PHP_FUNCTION(http_cache_etag)
5852 +{
5853 + char *etag = NULL;
5854 + int etag_len = 0;
5855 +
5856 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
5857 + RETURN_FALSE;
5858 + }
5859 +
5860 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
5861 +
5862 + RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
5863 +}
5864 +/* }}} */
5865 +
5866 +/* {{{ proto string ob_etaghandler(string data, int mode)
5867 + For use with ob_start(). Output buffer handler generating an ETag with the hash algorithm specified with the INI setting "http.etag.mode". */
5868 +PHP_FUNCTION(ob_etaghandler)
5869 +{
5870 + char *data;
5871 + int data_len;
5872 + long mode;
5873 +
5874 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
5875 + RETURN_FALSE;
5876 + }
5877 +
5878 + Z_TYPE_P(return_value) = IS_STRING;
5879 + http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
5880 +}
5881 +/* }}} */
5882 +
5883 +/* {{{ proto void http_throttle(double sec[, int bytes = 40960])
5884 + Sets the throttle delay and send buffer size for use with http_send() API. */
5885 +PHP_FUNCTION(http_throttle)
5886 +{
5887 + long chunk_size = HTTP_SENDBUF_SIZE;
5888 + double interval;
5889 +
5890 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &interval, &chunk_size)) {
5891 + return;
5892 + }
5893 +
5894 + HTTP_G->send.throttle_delay = interval;
5895 + HTTP_G->send.buffer_size = chunk_size;
5896 +}
5897 +/* }}} */
5898 +
5899 +/* {{{ proto void http_redirect([string url[, array params[, bool session = false[, int status = 302]]]])
5900 + Redirect to the given url. */
5901 +PHP_FUNCTION(http_redirect)
5902 +{
5903 + int url_len = 0;
5904 + size_t query_len = 0;
5905 + zend_bool session = 0, free_params = 0;
5906 + zval *params = NULL;
5907 + long status = HTTP_REDIRECT;
5908 + char *query = NULL, *url = NULL, *URI, *LOC, *RED = NULL;
5909 +
5910 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bl", &url, &url_len, &params, &session, &status) != SUCCESS) {
5911 + RETURN_FALSE;
5912 + }
5913 +
5914 +#ifdef HTTP_HAVE_SESSION
5915 + /* append session info */
5916 + if (session) {
5917 + if (!params) {
5918 + free_params = 1;
5919 + MAKE_STD_ZVAL(params);
5920 + array_init(params);
5921 + }
5922 + if (PS(session_status) == php_session_active) {
5923 + if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
5924 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not append session information");
5925 + }
5926 + }
5927 + }
5928 +#endif
5929 +
5930 + /* treat params array with http_build_query() */
5931 + if (params) {
5932 + if (SUCCESS != http_urlencode_hash_ex(Z_ARRVAL_P(params), 0, NULL, 0, &query, &query_len)) {
5933 + if (free_params) {
5934 + zval_dtor(params);
5935 + FREE_ZVAL(params);
5936 + }
5937 + if (query) {
5938 + efree(query);
5939 + }
5940 + RETURN_FALSE;
5941 + }
5942 + }
5943 +
5944 + URI = http_absolute_url_ex(url, HTTP_URL_FROM_ENV);
5945 +
5946 + if (query_len) {
5947 + spprintf(&LOC, 0, "Location: %s?%s", URI, query);
5948 + if (status != 300) {
5949 + spprintf(&RED, 0, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, query, URI, query);
5950 + }
5951 + } else {
5952 + spprintf(&LOC, 0, "Location: %s", URI);
5953 + if (status != 300) {
5954 + spprintf(&RED, 0, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
5955 + }
5956 + }
5957 +
5958 + efree(URI);
5959 + if (query) {
5960 + efree(query);
5961 + }
5962 + if (free_params) {
5963 + zval_dtor(params);
5964 + FREE_ZVAL(params);
5965 + }
5966 +
5967 + switch (status) {
5968 + case 300:
5969 + RETVAL_SUCCESS(http_send_status_header(status, LOC));
5970 + efree(LOC);
5971 + return;
5972 +
5973 + case HTTP_REDIRECT_PERM:
5974 + case HTTP_REDIRECT_FOUND:
5975 + case HTTP_REDIRECT_POST:
5976 + case HTTP_REDIRECT_PROXY:
5977 + case HTTP_REDIRECT_TEMP:
5978 + break;
5979 +
5980 + case 306:
5981 + default:
5982 + http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Unsupported redirection status code: %ld", status);
5983 + case HTTP_REDIRECT:
5984 + if ( SG(request_info).request_method &&
5985 + strcasecmp(SG(request_info).request_method, "HEAD") &&
5986 + strcasecmp(SG(request_info).request_method, "GET")) {
5987 + status = HTTP_REDIRECT_POST;
5988 + } else {
5989 + status = HTTP_REDIRECT_FOUND;
5990 + }
5991 + break;
5992 + }
5993 +
5994 + RETURN_SUCCESS(http_exit_ex(status, LOC, RED, 1));
5995 +}
5996 +/* }}} */
5997 +
5998 +/* {{{ proto bool http_send_data(string data)
5999 + Sends raw data with support for (multiple) range requests. */
6000 +PHP_FUNCTION(http_send_data)
6001 +{
6002 + int data_len;
6003 + char *data_buf;
6004 +
6005 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data_buf, &data_len) != SUCCESS) {
6006 + RETURN_FALSE;
6007 + }
6008 +
6009 + RETURN_SUCCESS(http_send_data(data_buf, data_len));
6010 +}
6011 +/* }}} */
6012 +
6013 +/* {{{ proto bool http_send_file(string file)
6014 + Sends a file with support for (multiple) range requests. */
6015 +PHP_FUNCTION(http_send_file)
6016 +{
6017 + char *file;
6018 + int flen = 0;
6019 +
6020 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &flen) != SUCCESS) {
6021 + RETURN_FALSE;
6022 + }
6023 + if (!flen) {
6024 + RETURN_FALSE;
6025 + }
6026 +
6027 + RETURN_SUCCESS(http_send_file(file));
6028 +}
6029 +/* }}} */
6030 +
6031 +/* {{{ proto bool http_send_stream(resource stream)
6032 + Sends an already opened stream with support for (multiple) range requests. */
6033 +PHP_FUNCTION(http_send_stream)
6034 +{
6035 + zval *zstream;
6036 + php_stream *file;
6037 +
6038 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) {
6039 + RETURN_FALSE;
6040 + }
6041 +
6042 + php_stream_from_zval(file, &zstream);
6043 + RETURN_SUCCESS(http_send_stream(file));
6044 +}
6045 +/* }}} */
6046 +
6047 +/* {{{ proto string http_chunked_decode(string encoded)
6048 + Decodes a string that was HTTP-chunked encoded. */
6049 +PHP_FUNCTION(http_chunked_decode)
6050 +{
6051 + char *encoded = NULL, *decoded = NULL;
6052 + size_t decoded_len = 0;
6053 + int encoded_len = 0;
6054 +
6055 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) {
6056 + RETURN_FALSE;
6057 + }
6058 +
6059 + if (NULL != http_encoding_dechunk(encoded, encoded_len, &decoded, &decoded_len)) {
6060 + RETURN_STRINGL(decoded, (int) decoded_len, 0);
6061 + } else {
6062 + RETURN_FALSE;
6063 + }
6064 +}
6065 +/* }}} */
6066 +
6067 +/* {{{ proto object http_parse_message(string message)
6068 + Parses (a) http_message(s) into a simple recursive object structure. */
6069 +PHP_FUNCTION(http_parse_message)
6070 +{
6071 + char *message;
6072 + int message_len;
6073 + http_message *msg = NULL;
6074 +
6075 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &message, &message_len)) {
6076 + RETURN_NULL();
6077 + }
6078 +
6079 + if ((msg = http_message_parse(message, message_len))) {
6080 + object_init(return_value);
6081 + http_message_tostruct_recursive(msg, return_value);
6082 + http_message_free(&msg);
6083 + } else {
6084 + RETURN_NULL();
6085 + }
6086 +}
6087 +/* }}} */
6088 +
6089 +/* {{{ proto array http_parse_headers(string header)
6090 + Parses HTTP headers into an associative array. */
6091 +PHP_FUNCTION(http_parse_headers)
6092 +{
6093 + char *header;
6094 + int header_len;
6095 +
6096 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) {
6097 + RETURN_FALSE;
6098 + }
6099 +
6100 + array_init(return_value);
6101 + if (SUCCESS != http_parse_headers(header, return_value)) {
6102 + zval_dtor(return_value);
6103 + http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse headers");
6104 + RETURN_FALSE;
6105 + }
6106 +}
6107 +/* }}}*/
6108 +
6109 +/* {{{ proto object http_parse_cookie(string cookie[, int flags[, array allowed_extras]])
6110 + Parses HTTP cookies like sent in a response into a struct. */
6111 +PHP_FUNCTION(http_parse_cookie)
6112 +{
6113 + char *cookie, **allowed_extras = NULL;
6114 + int i = 0, cookie_len;
6115 + long flags = 0;
6116 + zval *allowed_extras_array = NULL, **entry = NULL;
6117 + HashPosition pos;
6118 + http_cookie_list list;
6119 +
6120 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!", &cookie, &cookie_len, &flags, &allowed_extras_array)) {
6121 + RETURN_FALSE;
6122 + }
6123 +
6124 + if (allowed_extras_array) {
6125 + allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
6126 + FOREACH_VAL(pos, allowed_extras_array, entry) {
6127 + zval *data = http_zsep(IS_STRING, *entry);
6128 + allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
6129 + zval_ptr_dtor(&data);
6130 + }
6131 + }
6132 +
6133 + if (http_parse_cookie_ex(&list, cookie, flags, allowed_extras)) {
6134 + object_init(return_value);
6135 + http_cookie_list_tostruct(&list, return_value);
6136 + http_cookie_list_dtor(&list);
6137 + } else {
6138 + RETVAL_FALSE;
6139 + }
6140 +
6141 + if (allowed_extras) {
6142 + for (i = 0; allowed_extras[i]; ++i) {
6143 + efree(allowed_extras[i]);
6144 + }
6145 + efree(allowed_extras);
6146 + }
6147 +}
6148 +/* }}} */
6149 +
6150 +/* {{{ proto string http_build_cookie(array cookie)
6151 + Build a cookie string from an array/object like returned by http_parse_cookie(). */
6152 +PHP_FUNCTION(http_build_cookie)
6153 +{
6154 + char *str = NULL;
6155 + size_t len = 0;
6156 + zval *strct;
6157 + http_cookie_list list;
6158 +
6159 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &strct)) {
6160 + RETURN_FALSE;
6161 + }
6162 +
6163 + http_cookie_list_fromstruct(&list, strct);
6164 + http_cookie_list_tostring(&list, &str, &len);
6165 + http_cookie_list_dtor(&list);
6166 +
6167 + RETURN_STRINGL(str, len, 0);
6168 +}
6169 +/* }}} */
6170 +
6171 +/* {{{ proto object http_parse_params(string param[, int flags = HTTP_PARAMS_DEFAULT])
6172 + Parse parameter list. */
6173 +PHP_FUNCTION(http_parse_params)
6174 +{
6175 + char *param;
6176 + int param_len;
6177 + zval *params;
6178 + long flags = HTTP_PARAMS_DEFAULT;
6179 +
6180 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &param, &param_len, &flags)) {
6181 + RETURN_FALSE;
6182 + }
6183 +
6184 + MAKE_STD_ZVAL(params);
6185 + array_init(params);
6186 + if (SUCCESS != http_parse_params(param, flags, Z_ARRVAL_P(params))) {
6187 + zval_ptr_dtor(&params);
6188 + RETURN_FALSE;
6189 + }
6190 +
6191 + object_init(return_value);
6192 + add_property_zval(return_value, "params", params);
6193 +#ifdef ZEND_ENGINE_2
6194 + zval_ptr_dtor(&params);
6195 +#endif
6196 +}
6197 +/* }}} */
6198 +
6199 +/* {{{ proto array http_get_request_headers(void)
6200 + Get a list of incoming HTTP headers. */
6201 +PHP_FUNCTION(http_get_request_headers)
6202 +{
6203 + NO_ARGS;
6204 +
6205 + array_init(return_value);
6206 + http_get_request_headers(Z_ARRVAL_P(return_value));
6207 +}
6208 +/* }}} */
6209 +
6210 +/* {{{ proto string http_get_request_body(void)
6211 + Get the raw request body (e.g. POST or PUT data). */
6212 +PHP_FUNCTION(http_get_request_body)
6213 +{
6214 + char *body;
6215 + size_t length;
6216 +
6217 + NO_ARGS;
6218 +
6219 + if (SUCCESS == http_get_request_body(&body, &length)) {
6220 + RETURN_STRINGL(body, (int) length, 0);
6221 + } else {
6222 + RETURN_NULL();
6223 + }
6224 +}
6225 +/* }}} */
6226 +
6227 +/* {{{ proto resource http_get_request_body_stream(void)
6228 + 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. */
6229 +PHP_FUNCTION(http_get_request_body_stream)
6230 +{
6231 + php_stream *s;
6232 +
6233 + NO_ARGS;
6234 +
6235 + if ((s = http_get_request_body_stream())) {
6236 + php_stream_to_zval(s, return_value);
6237 + } else {
6238 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Failed to create request body stream");
6239 + RETURN_NULL();
6240 + }
6241 +}
6242 +/* }}} */
6243 +
6244 +/* {{{ proto bool http_match_request_header(string header, string value[, bool match_case = false])
6245 + Match an incoming HTTP header. */
6246 +PHP_FUNCTION(http_match_request_header)
6247 +{
6248 + char *header, *value;
6249 + int header_len, value_len;
6250 + zend_bool match_case = 0;
6251 +
6252 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &header, &header_len, &value, &value_len, &match_case)) {
6253 + RETURN_FALSE;
6254 + }
6255 +
6256 + RETURN_BOOL(http_match_request_header_ex(header, value, match_case));
6257 +}
6258 +/* }}} */
6259 +
6260 +/* {{{ proto object http_persistent_handles_count() */
6261 +PHP_FUNCTION(http_persistent_handles_count)
6262 +{
6263 + NO_ARGS;
6264 + object_init(return_value);
6265 + if (!http_persistent_handle_statall_ex(HASH_OF(return_value))) {
6266 + zval_dtor(return_value);
6267 + RETURN_NULL();
6268 + }
6269 +}
6270 +/* }}} */
6271 +
6272 +/* {{{ proto void http_persistent_handles_clean([string name]) */
6273 +PHP_FUNCTION(http_persistent_handles_clean)
6274 +{
6275 + char *name_str = NULL;
6276 + int name_len = 0;
6277 +
6278 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) {
6279 + http_persistent_handle_cleanup_ex(name_str, name_len, 1);
6280 + }
6281 +}
6282 +/* }}} */
6283 +
6284 +/* {{{ proto string http_persistent_handles_ident([string ident]) */
6285 +PHP_FUNCTION(http_persistent_handles_ident)
6286 +{
6287 + char *ident_str = NULL;
6288 + int ident_len = 0;
6289 +
6290 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ident_str, &ident_len)) {
6291 + RETVAL_STRING(zend_ini_string(ZEND_STRS("http.persistent.handles.ident"), 0), 1);
6292 + if (ident_str && ident_len) {
6293 + zend_alter_ini_entry(ZEND_STRS("http.persistent.handles.ident"), ident_str, ident_len, ZEND_INI_USER, PHP_INI_STAGE_RUNTIME);
6294 + }
6295 + }
6296 +}
6297 +/* }}} */
6298 +
6299 +/* {{{ HAVE_CURL */
6300 +#ifdef HTTP_HAVE_CURL
6301 +
6302 +#define RETVAL_RESPONSE_OR_BODY(request) \
6303 + { \
6304 + zval **bodyonly; \
6305 + \
6306 + /* check if only the body should be returned */ \
6307 + if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void *) &bodyonly)) && i_zend_is_true(*bodyonly)) { \
6308 + http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \
6309 + \
6310 + if (msg) { \
6311 + RETVAL_STRINGL(PHPSTR_VAL(&msg->body), PHPSTR_LEN(&msg->body), 1); \
6312 + http_message_free(&msg); \
6313 + } \
6314 + } else { \
6315 + RETVAL_STRINGL(request.conv.response.data, request.conv.response.used, 1); \
6316 + } \
6317 + }
6318 +
6319 +/* {{{ proto string http_get(string url[, array options[, array &info]])
6320 + Performs an HTTP GET request on the supplied url. */
6321 +PHP_FUNCTION(http_get)
6322 +{
6323 + zval *options = NULL, *info = NULL;
6324 + char *URL;
6325 + int URL_len;
6326 + http_request request;
6327 +
6328 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
6329 + RETURN_FALSE;
6330 + }
6331 +
6332 + if (info) {
6333 + zval_dtor(info);
6334 + array_init(info);
6335 + }
6336 +
6337 + RETVAL_FALSE;
6338 +
6339 + http_request_init_ex(&request, NULL, HTTP_GET, URL);
6340 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6341 + http_request_exec(&request);
6342 + if (info) {
6343 + http_request_info(&request, Z_ARRVAL_P(info));
6344 + }
6345 + RETVAL_RESPONSE_OR_BODY(request);
6346 + }
6347 + http_request_dtor(&request);
6348 +}
6349 +/* }}} */
6350 +
6351 +/* {{{ proto string http_head(string url[, array options[, array &info]])
6352 + Performs an HTTP HEAD request on the supplied url. */
6353 +PHP_FUNCTION(http_head)
6354 +{
6355 + zval *options = NULL, *info = NULL;
6356 + char *URL;
6357 + int URL_len;
6358 + http_request request;
6359 +
6360 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
6361 + RETURN_FALSE;
6362 + }
6363 +
6364 + if (info) {
6365 + zval_dtor(info);
6366 + array_init(info);
6367 + }
6368 +
6369 + RETVAL_FALSE;
6370 +
6371 + http_request_init_ex(&request, NULL, HTTP_HEAD, URL);
6372 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6373 + http_request_exec(&request);
6374 + if (info) {
6375 + http_request_info(&request, Z_ARRVAL_P(info));
6376 + }
6377 + RETVAL_RESPONSE_OR_BODY(request);
6378 + }
6379 + http_request_dtor(&request);
6380 +}
6381 +/* }}} */
6382 +
6383 +/* {{{ proto string http_post_data(string url, string data[, array options[, array &info]])
6384 + Performs an HTTP POST request on the supplied url. */
6385 +PHP_FUNCTION(http_post_data)
6386 +{
6387 + zval *options = NULL, *info = NULL;
6388 + char *URL, *postdata;
6389 + int postdata_len, URL_len;
6390 + http_request_body body;
6391 + http_request request;
6392 +
6393 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
6394 + RETURN_FALSE;
6395 + }
6396 +
6397 + if (info) {
6398 + zval_dtor(info);
6399 + array_init(info);
6400 + }
6401 +
6402 + RETVAL_FALSE;
6403 +
6404 + http_request_init_ex(&request, NULL, HTTP_POST, URL);
6405 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, postdata, postdata_len, 0);
6406 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6407 + http_request_exec(&request);
6408 + if (info) {
6409 + http_request_info(&request, Z_ARRVAL_P(info));
6410 + }
6411 + RETVAL_RESPONSE_OR_BODY(request);
6412 + }
6413 + http_request_dtor(&request);
6414 +}
6415 +/* }}} */
6416 +
6417 +/* {{{ proto string http_post_fields(string url, array data[, array files[, array options[, array &info]]])
6418 + Performs an HTTP POST request on the supplied url. */
6419 +PHP_FUNCTION(http_post_fields)
6420 +{
6421 + zval *options = NULL, *info = NULL, *fields = NULL, *files = NULL;
6422 + char *URL;
6423 + int URL_len;
6424 + http_request_body body;
6425 + http_request request;
6426 +
6427 + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa!|a!a/!z", &URL, &URL_len, &fields, &files, &options, &info) != SUCCESS) {
6428 + RETURN_FALSE;
6429 + }
6430 +
6431 + if (!http_request_body_fill(&body, fields ? Z_ARRVAL_P(fields) : NULL, files ? Z_ARRVAL_P(files) : NULL)) {
6432 + RETURN_FALSE;
6433 + }
6434 +
6435 + if (info) {
6436 + zval_dtor(info);
6437 + array_init(info);
6438 + }
6439 +
6440 + RETVAL_FALSE;
6441 +
6442 + http_request_init_ex(&request, NULL, HTTP_POST, URL);
6443 + request.body = &body;
6444 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6445 + http_request_exec(&request);
6446 + if (info) {
6447 + http_request_info(&request, Z_ARRVAL_P(info));
6448 + }
6449 + RETVAL_RESPONSE_OR_BODY(request);
6450 + }
6451 + http_request_dtor(&request);
6452 +}
6453 +/* }}} */
6454 +
6455 +/* {{{ proto string http_put_file(string url, string file[, array options[, array &info]])
6456 + Performs an HTTP PUT request on the supplied url. */
6457 +PHP_FUNCTION(http_put_file)
6458 +{
6459 + char *URL, *file;
6460 + int URL_len, f_len;
6461 + zval *options = NULL, *info = NULL;
6462 + php_stream *stream;
6463 + php_stream_statbuf ssb;
6464 + http_request_body body;
6465 + http_request request;
6466 +
6467 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &file, &f_len, &options, &info)) {
6468 + RETURN_FALSE;
6469 + }
6470 +
6471 + if (!(stream = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) {
6472 + RETURN_FALSE;
6473 + }
6474 + if (php_stream_stat(stream, &ssb)) {
6475 + php_stream_close(stream);
6476 + RETURN_FALSE;
6477 + }
6478 +
6479 + if (info) {
6480 + zval_dtor(info);
6481 + array_init(info);
6482 + }
6483 +
6484 + RETVAL_FALSE;
6485 +
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, 1);
6488 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6489 + http_request_exec(&request);
6490 + if (info) {
6491 + http_request_info(&request, Z_ARRVAL_P(info));
6492 + }
6493 + RETVAL_RESPONSE_OR_BODY(request);
6494 + }
6495 + http_request_dtor(&request);
6496 +}
6497 +/* }}} */
6498 +
6499 +/* {{{ proto string http_put_stream(string url, resource stream[, array options[, array &info]])
6500 + Performs an HTTP PUT request on the supplied url. */
6501 +PHP_FUNCTION(http_put_stream)
6502 +{
6503 + zval *resource, *options = NULL, *info = NULL;
6504 + char *URL;
6505 + int URL_len;
6506 + php_stream *stream;
6507 + php_stream_statbuf ssb;
6508 + http_request_body body;
6509 + http_request request;
6510 +
6511 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) {
6512 + RETURN_FALSE;
6513 + }
6514 +
6515 + php_stream_from_zval(stream, &resource);
6516 + if (php_stream_stat(stream, &ssb)) {
6517 + RETURN_FALSE;
6518 + }
6519 +
6520 + if (info) {
6521 + zval_dtor(info);
6522 + array_init(info);
6523 + }
6524 +
6525 + RETVAL_FALSE;
6526 +
6527 + http_request_init_ex(&request, NULL, HTTP_PUT, URL);
6528 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 0);
6529 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6530 + http_request_exec(&request);
6531 + if (info) {
6532 + http_request_info(&request, Z_ARRVAL_P(info));
6533 + }
6534 + RETVAL_RESPONSE_OR_BODY(request);
6535 + }
6536 + http_request_dtor(&request);
6537 +}
6538 +/* }}} */
6539 +
6540 +/* {{{ proto string http_put_data(string url, string data[, array options[, array &info]])
6541 + Performs an HTTP PUT request on the supplied url. */
6542 +PHP_FUNCTION(http_put_data)
6543 +{
6544 + char *URL, *data;
6545 + int URL_len, data_len;
6546 + zval *options = NULL, *info = NULL;
6547 + http_request_body body;
6548 + http_request request;
6549 +
6550 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &data, &data_len, &options, &info)) {
6551 + RETURN_FALSE;
6552 + }
6553 +
6554 + if (info) {
6555 + zval_dtor(info);
6556 + array_init(info);
6557 + }
6558 +
6559 + RETVAL_FALSE;
6560 +
6561 + http_request_init_ex(&request, NULL, HTTP_PUT, URL);
6562 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
6563 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6564 + http_request_exec(&request);
6565 + if (info) {
6566 + http_request_info(&request, Z_ARRVAL_P(info));
6567 + }
6568 + RETVAL_RESPONSE_OR_BODY(request);
6569 + }
6570 + http_request_dtor(&request);
6571 +}
6572 +/* }}} */
6573 +
6574 +/* {{{ proto string http_request(int method, string url[, string body[, array options[, array &info]]])
6575 + Performs a custom HTTP request on the supplied url. */
6576 +PHP_FUNCTION(http_request)
6577 +{
6578 + long meth;
6579 + char *URL, *data = NULL;
6580 + int URL_len, data_len = 0;
6581 + zval *options = NULL, *info = NULL;
6582 + http_request_body body;
6583 + http_request request;
6584 +
6585 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|sa/!z", &meth, &URL, &URL_len, &data, &data_len, &options, &info)) {
6586 + RETURN_FALSE;
6587 + }
6588 +
6589 + if (info) {
6590 + zval_dtor(info);
6591 + array_init(info);
6592 + }
6593 +
6594 + RETVAL_FALSE;
6595 +
6596 + http_request_init_ex(&request, NULL, meth, URL);
6597 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
6598 + if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
6599 + http_request_exec(&request);
6600 + if (info) {
6601 + http_request_info(&request, Z_ARRVAL_P(info));
6602 + }
6603 + RETVAL_RESPONSE_OR_BODY(request);
6604 + }
6605 + http_request_dtor(&request);
6606 +}
6607 +/* }}} */
6608 +
6609 +/* {{{ proto string http_request_body_encode(array fields, array files)
6610 + Generate x-www-form-urlencoded resp. form-data encoded request body. */
6611 +PHP_FUNCTION(http_request_body_encode)
6612 +{
6613 + zval *fields = NULL, *files = NULL;
6614 + HashTable *fields_ht, *files_ht;
6615 + http_request_body body;
6616 + char *buf;
6617 + size_t len;
6618 +
6619 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!", &fields, &files)) {
6620 + RETURN_FALSE;
6621 + }
6622 +
6623 + fields_ht = (fields && Z_TYPE_P(fields) == IS_ARRAY) ? Z_ARRVAL_P(fields) : NULL;
6624 + files_ht = (files && Z_TYPE_P(files) == IS_ARRAY) ? Z_ARRVAL_P(files) : NULL;
6625 + if (http_request_body_fill(&body, fields_ht, files_ht) && (SUCCESS == http_request_body_encode(&body, &buf, &len))) {
6626 + RETVAL_STRINGL(buf, len, 0);
6627 + } else {
6628 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not encode request body");
6629 + RETVAL_FALSE;
6630 + }
6631 + http_request_body_dtor(&body);
6632 +}
6633 +#endif /* HTTP_HAVE_CURL */
6634 +/* }}} HAVE_CURL */
6635 +
6636 +/* {{{ proto int http_request_method_register(string method)
6637 + Register a custom request method. */
6638 +PHP_FUNCTION(http_request_method_register)
6639 +{
6640 + char *method;
6641 + int method_len;
6642 + ulong existing;
6643 +
6644 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
6645 + RETURN_FALSE;
6646 + }
6647 + if ((existing = http_request_method_exists(1, 0, method))) {
6648 + RETURN_LONG((long) existing);
6649 + }
6650 +
6651 + RETVAL_LONG((long) http_request_method_register(method, method_len));
6652 +}
6653 +/* }}} */
6654 +
6655 +/* {{{ proto bool http_request_method_unregister(mixed method)
6656 + Unregister a previously registered custom request method. */
6657 +PHP_FUNCTION(http_request_method_unregister)
6658 +{
6659 + zval *method;
6660 +
6661 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
6662 + RETURN_FALSE;
6663 + }
6664 +
6665 + switch (Z_TYPE_P(method)) {
6666 + case IS_OBJECT:
6667 + convert_to_string(method);
6668 + case IS_STRING:
6669 + if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
6670 + convert_to_long(method);
6671 + } else {
6672 + int mn;
6673 + if (!(mn = http_request_method_exists(1, 0, Z_STRVAL_P(method)))) {
6674 + RETURN_FALSE;
6675 + }
6676 + zval_dtor(method);
6677 + ZVAL_LONG(method, (long)mn);
6678 + }
6679 + case IS_LONG:
6680 + RETURN_SUCCESS(http_request_method_unregister(Z_LVAL_P(method)));
6681 + default:
6682 + RETURN_FALSE;
6683 + }
6684 +}
6685 +/* }}} */
6686 +
6687 +/* {{{ proto int http_request_method_exists(mixed method)
6688 + Check if a request method is registered (or available by default). */
6689 +PHP_FUNCTION(http_request_method_exists)
6690 +{
6691 + if (return_value_used) {
6692 + zval *method;
6693 +
6694 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
6695 + RETURN_FALSE;
6696 + }
6697 +
6698 + switch (Z_TYPE_P(method)) {
6699 + case IS_OBJECT:
6700 + convert_to_string(method);
6701 + case IS_STRING:
6702 + if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
6703 + convert_to_long(method);
6704 + } else {
6705 + RETURN_LONG((long) http_request_method_exists(1, 0, Z_STRVAL_P(method)));
6706 + }
6707 + case IS_LONG:
6708 + RETURN_LONG((long) http_request_method_exists(0, (int) Z_LVAL_P(method), NULL));
6709 + default:
6710 + RETURN_FALSE;
6711 + }
6712 + }
6713 +}
6714 +/* }}} */
6715 +
6716 +/* {{{ proto string http_request_method_name(int method)
6717 + Get the literal string representation of a standard or registered request method. */
6718 +PHP_FUNCTION(http_request_method_name)
6719 +{
6720 + if (return_value_used) {
6721 + long method;
6722 +
6723 + if ((SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method)) || (method < 0)) {
6724 + RETURN_FALSE;
6725 + }
6726 +
6727 + RETURN_STRING(estrdup(http_request_method_name((int) method)), 0);
6728 + }
6729 +}
6730 +/* }}} */
6731 +
6732 +/* {{{ */
6733 +#ifdef HTTP_HAVE_ZLIB
6734 +
6735 +/* {{{ proto string http_deflate(string data[, int flags = 0])
6736 + Compress data with gzip, zlib AKA deflate or raw deflate encoding. */
6737 +PHP_FUNCTION(http_deflate)
6738 +{
6739 + char *data;
6740 + int data_len;
6741 + long flags = 0;
6742 +
6743 + RETVAL_NULL();
6744 +
6745 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags)) {
6746 + char *encoded;
6747 + size_t encoded_len;
6748 +
6749 + if (SUCCESS == http_encoding_deflate(flags, data, data_len, &encoded, &encoded_len)) {
6750 + RETURN_STRINGL(encoded, (int) encoded_len, 0);
6751 + }
6752 + }
6753 +}
6754 +/* }}} */
6755 +
6756 +/* {{{ proto string http_inflate(string data)
6757 + Decompress data compressed with either gzip, deflate AKA zlib or raw deflate encoding. */
6758 +PHP_FUNCTION(http_inflate)
6759 +{
6760 + char *data;
6761 + int data_len;
6762 +
6763 + RETVAL_NULL();
6764 +
6765 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
6766 + char *decoded;
6767 + size_t decoded_len;
6768 +
6769 + if (SUCCESS == http_encoding_inflate(data, data_len, &decoded, &decoded_len)) {
6770 + RETURN_STRINGL(decoded, (int) decoded_len, 0);
6771 + }
6772 + }
6773 +}
6774 +/* }}} */
6775 +
6776 +/* {{{ proto string ob_deflatehandler(string data, int mode)
6777 + For use with ob_start(). The deflate output buffer handler can only be used once. */
6778 +PHP_FUNCTION(ob_deflatehandler)
6779 +{
6780 + char *data;
6781 + int data_len;
6782 + long mode;
6783 +
6784 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
6785 + RETURN_FALSE;
6786 + }
6787 +
6788 + http_ob_deflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
6789 + Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
6790 +}
6791 +/* }}} */
6792 +
6793 +/* {{{ proto string ob_inflatehandler(string data, int mode)
6794 + For use with ob_start(). Same restrictions as with ob_deflatehandler apply. */
6795 +PHP_FUNCTION(ob_inflatehandler)
6796 +{
6797 + char *data;
6798 + int data_len;
6799 + long mode;
6800 +
6801 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
6802 + RETURN_FALSE;
6803 + }
6804 +
6805 + http_ob_inflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
6806 + Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
6807 +}
6808 +/* }}} */
6809 +
6810 +#endif /* HTTP_HAVE_ZLIB */
6811 +/* }}} */
6812 +
6813 +/* {{{ proto int http_support([int feature = 0])
6814 + Check for feature that require external libraries. */
6815 +PHP_FUNCTION(http_support)
6816 +{
6817 + long feature = 0;
6818 +
6819 + RETVAL_LONG(0L);
6820 +
6821 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &feature)) {
6822 + RETVAL_LONG(http_support(feature));
6823 + }
6824 +}
6825 +/* }}} */
6826 +
6827 +/*
6828 + * Local variables:
6829 + * tab-width: 4
6830 + * c-basic-offset: 4
6831 + * End:
6832 + * vim600: noet sw=4 ts=4 fdm=marker
6833 + * vim<600: noet sw=4 ts=4
6834 + */
6835 +
6836 --- /dev/null
6837 +++ b/ext/http/http_headers_api.c
6838 @@ -0,0 +1,534 @@
6839 +/*
6840 + +--------------------------------------------------------------------+
6841 + | PECL :: http |
6842 + +--------------------------------------------------------------------+
6843 + | Redistribution and use in source and binary forms, with or without |
6844 + | modification, are permitted provided that the conditions mentioned |
6845 + | in the accompanying LICENSE file are met. |
6846 + +--------------------------------------------------------------------+
6847 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
6848 + +--------------------------------------------------------------------+
6849 +*/
6850 +
6851 +/* $Id: http_headers_api.c 300300 2010-06-09 07:29:35Z mike $ */
6852 +
6853 +#define HTTP_WANT_SAPI
6854 +#include "php_http.h"
6855 +
6856 +#include "ext/standard/url.h"
6857 +#include "ext/standard/php_string.h"
6858 +
6859 +#include "php_http_api.h"
6860 +#include "php_http_headers_api.h"
6861 +
6862 +#ifndef HTTP_DBG_NEG
6863 +# define HTTP_DBG_NEG 0
6864 +#endif
6865 +
6866 +/* {{{ static void http_grab_response_headers(void *, void *) */
6867 +static void http_grab_response_headers(void *data, void *arg TSRMLS_DC)
6868 +{
6869 + phpstr_appendl(PHPSTR(arg), ((sapi_header_struct *)data)->header);
6870 + phpstr_appends(PHPSTR(arg), HTTP_CRLF);
6871 +}
6872 +/* }}} */
6873 +
6874 +/* {{{ static int http_sort_q(const void *, const void *) */
6875 +static int http_sort_q(const void *a, const void *b TSRMLS_DC)
6876 +{
6877 + Bucket *f, *s;
6878 + zval result, *first, *second;
6879 +
6880 + f = *((Bucket **) a);
6881 + s = *((Bucket **) b);
6882 +
6883 + first = *((zval **) f->pData);
6884 + second= *((zval **) s->pData);
6885 +
6886 + if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) {
6887 + return 0;
6888 + }
6889 + return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0));
6890 +}
6891 +/* }}} */
6892 +
6893 +/* {{{ char *http_negotiate_language_func */
6894 +char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
6895 +{
6896 + zval **value;
6897 + HashPosition pos;
6898 + const char *dash_test;
6899 +
6900 + FOREACH_HASH_VAL(pos, supported, value) {
6901 +#if HTTP_DBG_NEG
6902 + fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
6903 +#endif
6904 + if (!strcasecmp(Z_STRVAL_PP(value), test)) {
6905 + return Z_STRVAL_PP(value);
6906 + }
6907 + }
6908 +
6909 + /* no distinct match found, so try primaries */
6910 + if ((dash_test = strchr(test, '-'))) {
6911 + FOREACH_HASH_VAL(pos, supported, value) {
6912 + int len = dash_test - test;
6913 +#if HTTP_DBG_NEG
6914 + fprintf(stderr, "strncasecmp('%s', '%s', %d)\n", Z_STRVAL_PP(value), test, len);
6915 +#endif
6916 + if ( (!strncasecmp(Z_STRVAL_PP(value), test, len)) &&
6917 + ( (Z_STRVAL_PP(value)[len] == '\0') ||
6918 + (Z_STRVAL_PP(value)[len] == '-'))) {
6919 + *quality *= .9;
6920 + return Z_STRVAL_PP(value);
6921 + }
6922 + }
6923 + }
6924 +
6925 + return NULL;
6926 +}
6927 +/* }}} */
6928 +
6929 +/* {{{ char *http_negotiate_default_func */
6930 +char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC)
6931 +{
6932 + zval **value;
6933 + HashPosition pos;
6934 +
6935 + FOREACH_HASH_VAL(pos, supported, value) {
6936 +#if HTTP_DBG_NEG
6937 + fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test);
6938 +#endif
6939 + if (!strcasecmp(Z_STRVAL_PP(value), test)) {
6940 + return Z_STRVAL_PP(value);
6941 + }
6942 + }
6943 +
6944 + return NULL;
6945 +}
6946 +/* }}} */
6947 +
6948 +/* {{{ HashTable *http_negotiate_z(zval *, HashTable *, negotiate_func_t) */
6949 +PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC)
6950 +{
6951 + zval *accept = http_zsep(IS_STRING, value);
6952 + HashTable *result = NULL;
6953 +
6954 + if (Z_STRLEN_P(accept)) {
6955 + zval ex_arr, ex_del;
6956 +
6957 + INIT_PZVAL(&ex_del);
6958 + INIT_PZVAL(&ex_arr);
6959 + ZVAL_STRINGL(&ex_del, ",", 1, 0);
6960 + array_init(&ex_arr);
6961 +
6962 + php_explode(&ex_del, accept, &ex_arr, INT_MAX);
6963 +
6964 + if (zend_hash_num_elements(Z_ARRVAL(ex_arr)) > 0) {
6965 + int i = 0;
6966 + HashPosition pos;
6967 + zval **entry, array;
6968 +
6969 + INIT_PZVAL(&array);
6970 + array_init(&array);
6971 +
6972 + FOREACH_HASH_VAL(pos, Z_ARRVAL(ex_arr), entry) {
6973 + int ident_len;
6974 + double quality;
6975 + char *selected, *identifier, *freeme;
6976 + const char *separator;
6977 +
6978 +#if HTTP_DBG_NEG
6979 + fprintf(stderr, "Checking %s\n", Z_STRVAL_PP(entry));
6980 +#endif
6981 +
6982 + if ((separator = strchr(Z_STRVAL_PP(entry), ';'))) {
6983 + const char *ptr = separator;
6984 +
6985 + while (*++ptr && !HTTP_IS_CTYPE(digit, *ptr) && '.' != *ptr);
6986 +
6987 + quality = zend_strtod(ptr, NULL);
6988 + identifier = estrndup(Z_STRVAL_PP(entry), ident_len = separator - Z_STRVAL_PP(entry));
6989 + } else {
6990 + quality = 1000.0 - i++;
6991 + identifier = estrndup(Z_STRVAL_PP(entry), ident_len = Z_STRLEN_PP(entry));
6992 + }
6993 + freeme = identifier;
6994 +
6995 + while (HTTP_IS_CTYPE(space, *identifier)) {
6996 + ++identifier;
6997 + --ident_len;
6998 + }
6999 + while (ident_len && HTTP_IS_CTYPE(space, identifier[ident_len - 1])) {
7000 + identifier[--ident_len] = '\0';
7001 + }
7002 +
7003 + if ((selected = neg(identifier, &quality, supported TSRMLS_CC))) {
7004 + /* don't overwrite previously set with higher quality */
7005 + if (!zend_hash_exists(Z_ARRVAL(array), selected, strlen(selected) + 1)) {
7006 + add_assoc_double(&array, selected, quality);
7007 + }
7008 + }
7009 +
7010 + efree(freeme);
7011 + }
7012 +
7013 + result = Z_ARRVAL(array);
7014 + zend_hash_sort(result, zend_qsort, http_sort_q, 0 TSRMLS_CC);
7015 + }
7016 +
7017 + zval_dtor(&ex_arr);
7018 + }
7019 +
7020 + zval_ptr_dtor(&accept);
7021 +
7022 + return result;
7023 +}
7024 +/* }}} */
7025 +
7026 +/* {{{ HashTable *http_negotiate_q(const char *, HashTable *, negotiate_func_t) */
7027 +PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC)
7028 +{
7029 + zval *accept;
7030 +
7031 +#if HTTP_DBG_NEG
7032 + fprintf(stderr, "Reading header %s: ", header);
7033 +#endif
7034 + if (!(accept = http_get_server_var(header, 1))) {
7035 + return NULL;
7036 + }
7037 +#if HTTP_DBG_NEG
7038 + fprintf(stderr, "%s\n", Z_STRVAL_P(accept));
7039 +#endif
7040 +
7041 + return http_negotiate_z(accept, supported, neg);
7042 +}
7043 +/* }}} */
7044 +
7045 +/* {{{ http_range_status http_get_request_ranges(HashTable *ranges, size_t) */
7046 +PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC)
7047 +{
7048 + zval *zrange;
7049 + char *range, c;
7050 + long begin = -1, end = -1, *ptr;
7051 +
7052 + if ( !(zrange = http_get_server_var("HTTP_RANGE", 1)) ||
7053 + (size_t) Z_STRLEN_P(zrange) < lenof("bytes=") || strncmp(Z_STRVAL_P(zrange), "bytes=", lenof("bytes="))) {
7054 + return RANGE_NO;
7055 + }
7056 + range = Z_STRVAL_P(zrange) + lenof("bytes=");
7057 + ptr = &begin;
7058 +
7059 + do {
7060 + switch (c = *(range++)) {
7061 + case '0':
7062 + /* allow 000... - shall we? */
7063 + if (*ptr != -10) {
7064 + *ptr *= 10;
7065 + }
7066 + break;
7067 +
7068 + case '1': case '2': case '3':
7069 + case '4': case '5': case '6':
7070 + case '7': case '8': case '9':
7071 + /*
7072 + * If the value of the pointer is already set (non-negative)
7073 + * then multiply its value by ten and add the current value,
7074 + * else initialise the pointers value with the current value
7075 + * --
7076 + * This let us recognize empty fields when validating the
7077 + * ranges, i.e. a "-10" for begin and "12345" for the end
7078 + * was the following range request: "Range: bytes=0-12345";
7079 + * While a "-1" for begin and "12345" for the end would
7080 + * have been: "Range: bytes=-12345".
7081 + */
7082 + if (*ptr > 0) {
7083 + *ptr *= 10;
7084 + *ptr += c - '0';
7085 + } else {
7086 + *ptr = c - '0';
7087 + }
7088 + break;
7089 +
7090 + case '-':
7091 + ptr = &end;
7092 + break;
7093 +
7094 + case ' ':
7095 + break;
7096 +
7097 + case 0:
7098 + case ',':
7099 +
7100 + if (length) {
7101 + /* validate ranges */
7102 + switch (begin) {
7103 + /* "0-12345" */
7104 + case -10:
7105 + switch (end) {
7106 + /* "0-" */
7107 + case -1:
7108 + return RANGE_NO;
7109 +
7110 + /* "0-0" */
7111 + case -10:
7112 + end = 0;
7113 + break;
7114 +
7115 + default:
7116 + if (length <= (size_t) end) {
7117 + return RANGE_ERR;
7118 + }
7119 + break;
7120 + }
7121 + begin = 0;
7122 + break;
7123 +
7124 + /* "-12345" */
7125 + case -1:
7126 + /* "-", "-0" or overflow */
7127 + if (end == -1 || end == -10 || length <= (size_t) end) {
7128 + return RANGE_ERR;
7129 + }
7130 + begin = length - end;
7131 + end = length - 1;
7132 + break;
7133 +
7134 + /* "12345-(xxx)" */
7135 + default:
7136 + switch (end) {
7137 + /* "12345-0" */
7138 + case -10:
7139 + return RANGE_ERR;
7140 +
7141 + /* "12345-" */
7142 + case -1:
7143 + if (length <= (size_t) begin) {
7144 + return RANGE_ERR;
7145 + }
7146 + end = length - 1;
7147 + break;
7148 +
7149 + /* "12345-67890" */
7150 + default:
7151 + if ( (length <= (size_t) begin) ||
7152 + (length <= (size_t) end) ||
7153 + (end < begin)) {
7154 + return RANGE_ERR;
7155 + }
7156 + break;
7157 + }
7158 + break;
7159 + }
7160 + }
7161 + {
7162 + zval *zentry;
7163 + MAKE_STD_ZVAL(zentry);
7164 + array_init(zentry);
7165 + add_index_long(zentry, 0, begin);
7166 + add_index_long(zentry, 1, end);
7167 + zend_hash_next_index_insert(ranges, &zentry, sizeof(zval *), NULL);
7168 +
7169 + begin = -1;
7170 + end = -1;
7171 + ptr = &begin;
7172 + }
7173 + break;
7174 +
7175 + default:
7176 + return RANGE_NO;
7177 + }
7178 + } while (c != 0);
7179 +
7180 + return RANGE_OK;
7181 +}
7182 +/* }}} */
7183 +
7184 +/* {{{ STATUS http_parse_headers(char *, HashTable *, zend_bool) */
7185 +PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *headers, zend_bool prettify,
7186 + http_info_callback callback_func, void **callback_data TSRMLS_DC)
7187 +{
7188 + const char *colon = NULL, *line = NULL;
7189 + zval array;
7190 +
7191 + INIT_ZARR(array, headers);
7192 +
7193 + /* skip leading ws */
7194 + while (HTTP_IS_CTYPE(space, *header)) ++header;
7195 + line = header;
7196 +
7197 +#define MORE_HEADERS (*(line-1) && !(*(line-1) == '\n' && (*line == '\n' || *line == '\r')))
7198 + do {
7199 + int value_len = 0;
7200 +
7201 + switch (*line++) {
7202 + case ':':
7203 + if (!colon) {
7204 + colon = line - 1;
7205 + }
7206 + break;
7207 +
7208 + case 0:
7209 + --value_len; /* we don't have CR so value length is one char less */
7210 + case '\n':
7211 + if ((!*(line - 1)) || ((*line != ' ') && (*line != '\t'))) {
7212 + http_info i;
7213 +
7214 + if (SUCCESS == http_info_parse(header, &i)) {
7215 + /* response/request line */
7216 + callback_func(callback_data, &headers, &i TSRMLS_CC);
7217 + http_info_dtor(&i);
7218 + Z_ARRVAL(array) = headers;
7219 + } else if (colon) {
7220 + /* "header: value" pair */
7221 + if (header != colon) {
7222 + int keylen = colon - header;
7223 + const char *key = header;
7224 +
7225 + /* skip leading ws */
7226 + while (keylen && HTTP_IS_CTYPE(space, *key)) --keylen, ++key;
7227 + /* skip trailing ws */
7228 + while (keylen && HTTP_IS_CTYPE(space, key[keylen - 1])) --keylen;
7229 +
7230 + if (keylen > 0) {
7231 + zval **previous = NULL;
7232 + char *value;
7233 + char *keydup = estrndup(key, keylen);
7234 +
7235 + if (prettify) {
7236 + keydup = pretty_key(keydup, keylen, 1, 1);
7237 + }
7238 +
7239 + value_len += line - colon - 1;
7240 +
7241 + /* skip leading ws */
7242 + while (HTTP_IS_CTYPE(space, *(++colon))) --value_len;
7243 + /* skip trailing ws */
7244 + while (HTTP_IS_CTYPE(space, colon[value_len - 1])) --value_len;
7245 +
7246 + if (value_len > 0) {
7247 + value = estrndup(colon, value_len);
7248 + } else {
7249 + value = estrdup("");
7250 + value_len = 0;
7251 + }
7252 +
7253 + /* if we already have got such a header make an array of those */
7254 + if (SUCCESS == zend_hash_find(headers, keydup, keylen + 1, (void *) &previous)) {
7255 + /* convert to array */
7256 + if (Z_TYPE_PP(previous) != IS_ARRAY) {
7257 + convert_to_array(*previous);
7258 + }
7259 + add_next_index_stringl(*previous, value, value_len, 0);
7260 + } else {
7261 + add_assoc_stringl(&array, keydup, value, value_len, 0);
7262 + }
7263 + efree(keydup);
7264 + } else {
7265 + /* empty key (" : ...") */
7266 + return FAILURE;
7267 + }
7268 + } else {
7269 + /* empty key (": ...") */
7270 + return FAILURE;
7271 + }
7272 + } else if (MORE_HEADERS) {
7273 + /* a line without a colon */
7274 + return FAILURE;
7275 + }
7276 + colon = NULL;
7277 + value_len = 0;
7278 + header += line - header;
7279 + }
7280 + break;
7281 + }
7282 + } while (MORE_HEADERS);
7283 +
7284 + return SUCCESS;
7285 +}
7286 +/* }}} */
7287 +
7288 +/* {{{ void http_get_request_headers(HashTable *) */
7289 +PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC)
7290 +{
7291 + HashKey key = initHashKey(0);
7292 + zval **hsv, **header;
7293 + HashPosition pos;
7294 +
7295 + if (!HTTP_G->request.headers) {
7296 + ALLOC_HASHTABLE(HTTP_G->request.headers);
7297 + zend_hash_init(HTTP_G->request.headers, 0, NULL, ZVAL_PTR_DTOR, 0);
7298 +
7299 +#ifdef ZEND_ENGINE_2
7300 + zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
7301 +#endif
7302 +
7303 + if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) {
7304 + FOREACH_KEY(pos, *hsv, key) {
7305 + if (key.type == HASH_KEY_IS_STRING && key.len > 6 && !strncmp(key.str, "HTTP_", 5)) {
7306 + key.len -= 5;
7307 + key.str = pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1);
7308 +
7309 + zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
7310 + ZVAL_ADDREF(*header);
7311 + zend_hash_add(HTTP_G->request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
7312 +
7313 + efree(key.str);
7314 + }
7315 + }
7316 + }
7317 + }
7318 +
7319 + if (headers) {
7320 + zend_hash_copy(headers, HTTP_G->request.headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
7321 + }
7322 +}
7323 +/* }}} */
7324 +
7325 +/* {{{ STATUS http_get_response_headers(HashTable *) */
7326 +PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC)
7327 +{
7328 + STATUS status;
7329 + phpstr headers;
7330 +
7331 + phpstr_init(&headers);
7332 + zend_llist_apply_with_argument(&SG(sapi_headers).headers, http_grab_response_headers, &headers TSRMLS_CC);
7333 + phpstr_fix(&headers);
7334 +
7335 + status = http_parse_headers_ex(PHPSTR_VAL(&headers), headers_ht, 1);
7336 + phpstr_dtor(&headers);
7337 +
7338 + return status;
7339 +}
7340 +/* }}} */
7341 +
7342 +/* {{{ zend_bool http_match_request_header(char *, char *) */
7343 +PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC)
7344 +{
7345 + char *name;
7346 + uint name_len = strlen(header);
7347 + zend_bool result = 0;
7348 + zval **data, *zvalue;
7349 +
7350 + http_get_request_headers(NULL);
7351 + name = pretty_key(estrndup(header, name_len), name_len, 1, 1);
7352 + if (SUCCESS == zend_hash_find(HTTP_G->request.headers, name, name_len+1, (void *) &data)) {
7353 + zvalue = http_zsep(IS_STRING, *data);
7354 + result = (match_case ? strcmp(Z_STRVAL_P(zvalue), value) : strcasecmp(Z_STRVAL_P(zvalue), value)) ? 0 : 1;
7355 + zval_ptr_dtor(&zvalue);
7356 + }
7357 + efree(name);
7358 +
7359 + return result;
7360 +}
7361 +/* }}} */
7362 +
7363 +
7364 +/*
7365 + * Local variables:
7366 + * tab-width: 4
7367 + * c-basic-offset: 4
7368 + * End:
7369 + * vim600: noet sw=4 ts=4 fdm=marker
7370 + * vim<600: noet sw=4 ts=4
7371 + */
7372 +
7373 --- /dev/null
7374 +++ b/ext/http/http_inflatestream_object.c
7375 @@ -0,0 +1,297 @@
7376 +/*
7377 + +--------------------------------------------------------------------+
7378 + | PECL :: http |
7379 + +--------------------------------------------------------------------+
7380 + | Redistribution and use in source and binary forms, with or without |
7381 + | modification, are permitted provided that the conditions mentioned |
7382 + | in the accompanying LICENSE file are met. |
7383 + +--------------------------------------------------------------------+
7384 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
7385 + +--------------------------------------------------------------------+
7386 +*/
7387 +
7388 +/* $Id: http_inflatestream_object.c 323304 2012-02-17 21:13:24Z mike $ */
7389 +
7390 +#define HTTP_WANT_ZLIB
7391 +#include "php_http.h"
7392 +
7393 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB)
7394 +
7395 +#include "php_http_api.h"
7396 +#include "php_http_encoding_api.h"
7397 +#include "php_http_exception_object.h"
7398 +#include "php_http_inflatestream_object.h"
7399 +
7400 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpInflateStream, method, 0, req_args)
7401 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpInflateStream, method, 0)
7402 +#define HTTP_INFLATE_ME(method, visibility) PHP_ME(HttpInflateStream, method, HTTP_ARGS(HttpInflateStream, method), visibility)
7403 +
7404 +HTTP_BEGIN_ARGS(__construct, 0)
7405 + HTTP_ARG_VAL(flags, 0)
7406 +HTTP_END_ARGS;
7407 +
7408 +HTTP_BEGIN_ARGS(factory, 0)
7409 + HTTP_ARG_VAL(flags, 0)
7410 + HTTP_ARG_VAL(class_name, 0)
7411 +HTTP_END_ARGS;
7412 +
7413 +HTTP_BEGIN_ARGS(update, 1)
7414 + HTTP_ARG_VAL(data, 0)
7415 +HTTP_END_ARGS;
7416 +
7417 +HTTP_BEGIN_ARGS(flush, 0)
7418 + HTTP_ARG_VAL(data, 0)
7419 +HTTP_END_ARGS;
7420 +
7421 +HTTP_BEGIN_ARGS(finish, 0)
7422 + HTTP_ARG_VAL(data, 0)
7423 +HTTP_END_ARGS;
7424 +
7425 +#define THIS_CE http_inflatestream_object_ce
7426 +zend_class_entry *http_inflatestream_object_ce;
7427 +zend_function_entry http_inflatestream_object_fe[] = {
7428 + HTTP_INFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
7429 + HTTP_INFLATE_ME(update, ZEND_ACC_PUBLIC)
7430 + HTTP_INFLATE_ME(flush, ZEND_ACC_PUBLIC)
7431 + HTTP_INFLATE_ME(finish, ZEND_ACC_PUBLIC)
7432 +
7433 + HTTP_INFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
7434 +
7435 + EMPTY_FUNCTION_ENTRY
7436 +};
7437 +static zend_object_handlers http_inflatestream_object_handlers;
7438 +
7439 +PHP_MINIT_FUNCTION(http_inflatestream_object)
7440 +{
7441 + HTTP_REGISTER_CLASS_EX(HttpInflateStream, http_inflatestream_object, NULL, 0);
7442 + http_inflatestream_object_handlers.clone_obj = _http_inflatestream_object_clone_obj;
7443 +
7444 +#ifndef WONKY
7445 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC);
7446 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC);
7447 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC);
7448 +#endif
7449 +
7450 + return SUCCESS;
7451 +}
7452 +
7453 +zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC)
7454 +{
7455 + return http_inflatestream_object_new_ex(ce, NULL, NULL);
7456 +}
7457 +
7458 +zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC)
7459 +{
7460 + zend_object_value ov;
7461 + http_inflatestream_object *o;
7462 +
7463 + o = ecalloc(1, sizeof(http_inflatestream_object));
7464 + o->zo.ce = ce;
7465 +
7466 + if (ptr) {
7467 + *ptr = o;
7468 + }
7469 +
7470 + if (s) {
7471 + o->stream = s;
7472 + }
7473 +
7474 +#ifdef ZEND_ENGINE_2_4
7475 + zend_object_std_init(o, ce TSRMLS_CC);
7476 + object_properties_init(o, ce);
7477 +#else
7478 + ALLOC_HASHTABLE(OBJ_PROP(o));
7479 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
7480 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
7481 +#endif
7482 +
7483 + ov.handle = putObject(http_inflatestream_object, o);
7484 + ov.handlers = &http_inflatestream_object_handlers;
7485 +
7486 + return ov;
7487 +}
7488 +
7489 +zend_object_value _http_inflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC)
7490 +{
7491 + http_encoding_stream *s;
7492 + zend_object_value new_ov;
7493 + http_inflatestream_object *new_obj = NULL;
7494 + getObject(http_inflatestream_object, old_obj);
7495 +
7496 + s = ecalloc(1, sizeof(http_encoding_stream));
7497 + s->flags = old_obj->stream->flags;
7498 + inflateCopy(&s->stream, &old_obj->stream->stream);
7499 + s->stream.opaque = phpstr_dup(s->stream.opaque);
7500 +
7501 + new_ov = http_inflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj);
7502 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
7503 +
7504 + return new_ov;
7505 +}
7506 +
7507 +void _http_inflatestream_object_free(zend_object *object TSRMLS_DC)
7508 +{
7509 + http_inflatestream_object *o = (http_inflatestream_object *) object;
7510 +
7511 + if (o->stream) {
7512 + http_encoding_inflate_stream_free(&o->stream);
7513 + }
7514 + freeObject(o);
7515 +}
7516 +
7517 +/* {{{ proto void HttpInflateStream::__construct([int flags = 0])
7518 + Creates a new HttpInflateStream object instance. */
7519 +PHP_METHOD(HttpInflateStream, __construct)
7520 +{
7521 + long flags = 0;
7522 +
7523 + SET_EH_THROW_HTTP();
7524 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) {
7525 + getObject(http_inflatestream_object, obj);
7526 +
7527 + if (!obj->stream) {
7528 + obj->stream = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
7529 + } else {
7530 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpInflateStream cannot be initialized twice");
7531 + }
7532 + }
7533 + SET_EH_NORMAL();
7534 +}
7535 +/* }}} */
7536 +
7537 +/* {{{ proto HttpInflateStream HttpInflateStream::factory([int flags[, string class = "HttpInflateStream"]])
7538 + Creates a new HttpInflateStream object instance. */
7539 +PHP_METHOD(HttpInflateStream, factory)
7540 +{
7541 + long flags = 0;
7542 + char *cn = NULL;
7543 + int cl = 0;
7544 +
7545 + SET_EH_THROW_HTTP();
7546 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) {
7547 + zend_object_value ov;
7548 + http_encoding_stream *s = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff);
7549 +
7550 + if (SUCCESS == http_object_new(&ov, cn, cl, _http_inflatestream_object_new_ex, http_inflatestream_object_ce, s, NULL)) {
7551 + RETVAL_OBJVAL(ov, 0);
7552 + }
7553 + }
7554 + SET_EH_NORMAL();
7555 +}
7556 +/* }}} */
7557 +
7558 +/* {{{ proto string HttpInflateStream::update(string data)
7559 + Passes more data through the inflate stream. */
7560 +PHP_METHOD(HttpInflateStream, update)
7561 +{
7562 + int data_len;
7563 + size_t decoded_len = 0;
7564 + char *data, *decoded = NULL;
7565 + getObject(http_inflatestream_object, obj);
7566 +
7567 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
7568 + RETURN_FALSE;
7569 + }
7570 +
7571 + if (!data_len) {
7572 + RETURN_STRING("", 1);
7573 + }
7574 +
7575 + if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
7576 + RETURN_FALSE;
7577 + }
7578 +
7579 + if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
7580 + RETURN_STRINGL(decoded, decoded_len, 0);
7581 + } else {
7582 + RETURN_FALSE;
7583 + }
7584 +}
7585 +/* }}} */
7586 +
7587 +/* {{{ proto string HttpInflateStream::flush([string data])
7588 + Flush the inflate stream. */
7589 +PHP_METHOD(HttpInflateStream, flush)
7590 +{
7591 + int data_len = 0;
7592 + size_t decoded_len = 0;
7593 + char *decoded = NULL, *data = NULL;
7594 + getObject(http_inflatestream_object, obj);
7595 +
7596 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
7597 + RETURN_FALSE;
7598 + }
7599 +
7600 + if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
7601 + RETURN_FALSE;
7602 + }
7603 +
7604 + /* flushing the inflate stream is a no-op */
7605 + if (!data_len) {
7606 + RETURN_STRINGL("", 0, 1);
7607 + } else if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) {
7608 + RETURN_STRINGL(decoded, decoded_len, 0);
7609 + } else {
7610 + RETURN_FALSE;
7611 + }
7612 +}
7613 +/* }}} */
7614 +
7615 +/* {{{ proto string HttpInflateStream::finish([string data])
7616 + Finalizes the inflate stream. The inflate stream can be reused after finalizing. */
7617 +PHP_METHOD(HttpInflateStream, finish)
7618 +{
7619 + int data_len = 0;
7620 + size_t updated_len = 0, decoded_len = 0;
7621 + char *updated = NULL, *decoded = NULL, *data = NULL;
7622 + getObject(http_inflatestream_object, obj);
7623 +
7624 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) {
7625 + RETURN_FALSE;
7626 + }
7627 +
7628 + if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) {
7629 + RETURN_FALSE;
7630 + }
7631 +
7632 + if (data_len) {
7633 + if (SUCCESS != http_encoding_inflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) {
7634 + RETURN_FALSE;
7635 + }
7636 + }
7637 +
7638 + if (SUCCESS == http_encoding_inflate_stream_finish(obj->stream, &decoded, &decoded_len)) {
7639 + if (updated_len) {
7640 + updated = erealloc(updated, updated_len + decoded_len + 1);
7641 + updated[updated_len + decoded_len] = '\0';
7642 + memcpy(updated + updated_len, decoded, decoded_len);
7643 + STR_FREE(decoded);
7644 + updated_len += decoded_len;
7645 + RETVAL_STRINGL(updated, updated_len, 0);
7646 + } else if (decoded) {
7647 + STR_FREE(updated);
7648 + RETVAL_STRINGL(decoded, decoded_len, 0);
7649 + } else {
7650 + RETVAL_NULL();
7651 + }
7652 + } else {
7653 + STR_FREE(updated);
7654 + RETVAL_FALSE;
7655 + }
7656 +
7657 + http_encoding_inflate_stream_dtor(obj->stream);
7658 + http_encoding_inflate_stream_init(obj->stream, obj->stream->flags);
7659 +}
7660 +/* }}} */
7661 +
7662 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/
7663 +
7664 +/*
7665 + * Local variables:
7666 + * tab-width: 4
7667 + * c-basic-offset: 4
7668 + * End:
7669 + * vim600: noet sw=4 ts=4 fdm=marker
7670 + * vim<600: noet sw=4 ts=4
7671 + */
7672 +
7673 --- /dev/null
7674 +++ b/ext/http/http_info_api.c
7675 @@ -0,0 +1,155 @@
7676 +/*
7677 + +--------------------------------------------------------------------+
7678 + | PECL :: http |
7679 + +--------------------------------------------------------------------+
7680 + | Redistribution and use in source and binary forms, with or without |
7681 + | modification, are permitted provided that the conditions mentioned |
7682 + | in the accompanying LICENSE file are met. |
7683 + +--------------------------------------------------------------------+
7684 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
7685 + +--------------------------------------------------------------------+
7686 +*/
7687 +
7688 +/* $Id: http_info_api.c 304921 2010-10-26 15:27:36Z iliaa $ */
7689 +
7690 +#include "php_http.h"
7691 +
7692 +#include "php_http_api.h"
7693 +#include "php_http_info_api.h"
7694 +
7695 +PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC)
7696 +{
7697 + zval array;
7698 +
7699 + INIT_ZARR(array, *headers);
7700 +
7701 + switch (info->type) {
7702 + case IS_HTTP_REQUEST:
7703 + add_assoc_string(&array, "Request Method", HTTP_INFO(info).request.method, 1);
7704 + add_assoc_string(&array, "Request Url", HTTP_INFO(info).request.url, 1);
7705 + break;
7706 +
7707 + case IS_HTTP_RESPONSE:
7708 + add_assoc_long(&array, "Response Code", (long) HTTP_INFO(info).response.code);
7709 + if (HTTP_INFO(info).response.status) {
7710 + add_assoc_string(&array, "Response Status", HTTP_INFO(info).response.status, 1);
7711 + }
7712 + break;
7713 + }
7714 +}
7715 +
7716 +PHP_HTTP_API void _http_info_dtor(http_info *i)
7717 +{
7718 + switch (i->type) {
7719 + case IS_HTTP_REQUEST:
7720 + STR_SET(HTTP_INFO(i).request.method, NULL);
7721 + STR_SET(HTTP_INFO(i).request.url, NULL);
7722 + break;
7723 +
7724 + case IS_HTTP_RESPONSE:
7725 + STR_SET(HTTP_INFO(i).response.status, NULL);
7726 + break;
7727 +
7728 + default:
7729 + break;
7730 + }
7731 +}
7732 +
7733 +PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info, zend_bool silent TSRMLS_DC)
7734 +{
7735 + const char *end, *http;
7736 +
7737 + /* sane parameter */
7738 + if ((!pre_header) || (!*pre_header)) {
7739 + return FAILURE;
7740 + }
7741 +
7742 + /* where's the end of the line */
7743 + if (!(end = http_locate_eol(pre_header, NULL))) {
7744 + end = pre_header + strlen(pre_header);
7745 + }
7746 +
7747 + /* there must be HTTP/1.x in the line */
7748 + if (!(http = http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) {
7749 + return FAILURE;
7750 + }
7751 +
7752 + /* and nothing than SPACE or NUL after HTTP/1.x */
7753 + if ( (!HTTP_IS_CTYPE(digit, http[lenof("HTTP/1.")])) ||
7754 + (http[lenof("HTTP/1.1")] && (!HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) {
7755 + if (!silent) {
7756 + http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid HTTP/1.x protocol identification");
7757 + }
7758 + return FAILURE;
7759 + }
7760 +
7761 +#if 0
7762 + {
7763 + char *line = estrndup(pre_header, end - pre_header);
7764 + fprintf(stderr, "http_parse_info('%s')\n", line);
7765 + efree(line);
7766 + }
7767 +#endif
7768 +
7769 + info->http.version = zend_strtod(http + lenof("HTTP/"), NULL);
7770 +
7771 + /* is response */
7772 + if (pre_header == http) {
7773 + char *status = NULL;
7774 + const char *code = http + sizeof("HTTP/1.1");
7775 +
7776 + info->type = IS_HTTP_RESPONSE;
7777 + while (' ' == *code) ++code;
7778 + if (code && end > code) {
7779 + HTTP_INFO(info).response.code = strtol(code, &status, 10);
7780 + } else {
7781 + HTTP_INFO(info).response.code = 0;
7782 + }
7783 + if (status && end > status) {
7784 + while (' ' == *status) ++status;
7785 + HTTP_INFO(info).response.status = estrndup(status, end - status);
7786 + } else {
7787 + HTTP_INFO(info).response.status = NULL;
7788 + }
7789 +
7790 + return SUCCESS;
7791 + }
7792 +
7793 + /* is request */
7794 + else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') {
7795 + const char *url = strchr(pre_header, ' ');
7796 +
7797 + info->type = IS_HTTP_REQUEST;
7798 + if (url && http > url) {
7799 + HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header);
7800 + while (' ' == *url) ++url;
7801 + while (' ' == *(http-1)) --http;
7802 + if (http > url) {
7803 + HTTP_INFO(info).request.url = estrndup(url, http - url);
7804 + } else {
7805 + efree(HTTP_INFO(info).request.method);
7806 + return FAILURE;
7807 + }
7808 + } else {
7809 + HTTP_INFO(info).request.method = NULL;
7810 + HTTP_INFO(info).request.url = NULL;
7811 + }
7812 +
7813 + return SUCCESS;
7814 + }
7815 +
7816 + /* some darn header containing HTTP/1.x */
7817 + else {
7818 + return FAILURE;
7819 + }
7820 +}
7821 +
7822 +/*
7823 + * Local variables:
7824 + * tab-width: 4
7825 + * c-basic-offset: 4
7826 + * End:
7827 + * vim600: noet sw=4 ts=4 fdm=marker
7828 + * vim<600: noet sw=4 ts=4
7829 + */
7830 +
7831 --- /dev/null
7832 +++ b/ext/http/http_message_api.c
7833 @@ -0,0 +1,739 @@
7834 +/*
7835 + +--------------------------------------------------------------------+
7836 + | PECL :: http |
7837 + +--------------------------------------------------------------------+
7838 + | Redistribution and use in source and binary forms, with or without |
7839 + | modification, are permitted provided that the conditions mentioned |
7840 + | in the accompanying LICENSE file are met. |
7841 + +--------------------------------------------------------------------+
7842 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
7843 + +--------------------------------------------------------------------+
7844 +*/
7845 +
7846 +/* $Id: http_message_api.c 323304 2012-02-17 21:13:24Z mike $ */
7847 +
7848 +#define HTTP_WANT_SAPI
7849 +#define HTTP_WANT_CURL
7850 +#define HTTP_WANT_ZLIB
7851 +#include "php_http.h"
7852 +
7853 +#include "php_http_api.h"
7854 +#include "php_http_encoding_api.h"
7855 +#include "php_http_headers_api.h"
7856 +#include "php_http_message_api.h"
7857 +#include "php_http_request_api.h"
7858 +#include "php_http_send_api.h"
7859 +#include "php_http_url_api.h"
7860 +
7861 +#define http_message_info_callback _http_message_info_callback
7862 +static void _http_message_info_callback(http_message **message, HashTable **headers, http_info *info TSRMLS_DC)
7863 +{
7864 + http_message *old = *message;
7865 +
7866 + /* advance message */
7867 + if (old->type || zend_hash_num_elements(&old->hdrs) || PHPSTR_LEN(old)) {
7868 + (*message) = http_message_new();
7869 + (*message)->parent = old;
7870 + (*headers) = &((*message)->hdrs);
7871 + }
7872 +
7873 + http_message_set_info(*message, info);
7874 +}
7875 +
7876 +#define http_message_init_type _http_message_init_type
7877 +static inline void _http_message_init_type(http_message *message, http_message_type type)
7878 +{
7879 + message->http.version = .0;
7880 +
7881 + switch (message->type = type) {
7882 + case HTTP_MSG_RESPONSE:
7883 + message->http.info.response.code = 0;
7884 + message->http.info.response.status = NULL;
7885 + break;
7886 +
7887 + case HTTP_MSG_REQUEST:
7888 + message->http.info.request.method = NULL;
7889 + message->http.info.request.url = NULL;
7890 + break;
7891 +
7892 + case HTTP_MSG_NONE:
7893 + default:
7894 + break;
7895 + }
7896 +}
7897 +
7898 +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)
7899 +{
7900 + if (!message) {
7901 + message = ecalloc_rel(1, sizeof(http_message));
7902 + }
7903 +
7904 + http_message_init_type(message, type);
7905 + message->parent = NULL;
7906 + phpstr_init(&message->body);
7907 + zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0);
7908 +
7909 + return message;
7910 +}
7911 +
7912 +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)
7913 +{
7914 + int free_msg;
7915 + http_info inf;
7916 + zval *sval, tval;
7917 + char *body_str;
7918 + size_t body_len;
7919 +
7920 + if ((free_msg = !message)) {
7921 + message = http_message_init_rel(NULL, HTTP_MSG_NONE);
7922 + }
7923 +
7924 + memset(&inf, 0, sizeof(http_info));
7925 + switch (inf.type = type) {
7926 + case HTTP_MSG_REQUEST:
7927 + if ((sval = http_get_server_var("SERVER_PROTOCOL", 1)) && !strncmp(Z_STRVAL_P(sval), "HTTP/", lenof("HTTP/"))) {
7928 + inf.http.version = zend_strtod(Z_STRVAL_P(sval) + lenof("HTTP/"), NULL);
7929 + } else {
7930 + inf.http.version = 1.1;
7931 + }
7932 + if ((sval = http_get_server_var("REQUEST_METHOD", 1))) {
7933 + inf.http.info.request.method = estrdup(Z_STRVAL_P(sval));
7934 + }
7935 + if ((sval = http_get_server_var("REQUEST_URI", 1))) {
7936 + inf.http.info.request.url = estrdup(Z_STRVAL_P(sval));
7937 + }
7938 +
7939 + http_message_set_info(message, &inf);
7940 + http_get_request_headers(&message->hdrs);
7941 + if (SUCCESS == http_get_request_body_ex(&body_str, &body_len, 0)) {
7942 + phpstr_from_string_ex(&message->body, body_str, body_len);
7943 + }
7944 + break;
7945 +
7946 + case HTTP_MSG_RESPONSE:
7947 + if (!SG(sapi_headers).http_status_line || SUCCESS != http_info_parse_ex(SG(sapi_headers).http_status_line, &inf, 0)) {
7948 + inf.http.version = 1.1;
7949 + inf.http.info.response.code = 200;
7950 + inf.http.info.response.status = estrdup("Ok");
7951 + }
7952 +
7953 + http_message_set_info(message, &inf);
7954 + http_get_response_headers(&message->hdrs);
7955 +#ifdef PHP_OUTPUT_NEWAPI
7956 + if (SUCCESS == php_output_get_contents(&tval TSRMLS_CC)) {
7957 +#else
7958 + if (SUCCESS == php_ob_get_buffer(&tval TSRMLS_CC)) {
7959 +#endif
7960 + message->body.data = Z_STRVAL(tval);
7961 + message->body.used = Z_STRLEN(tval);
7962 + message->body.free = 1; /* "\0" */
7963 + }
7964 + break;
7965 +
7966 + default:
7967 + if (free_msg) {
7968 + http_message_free(&message);
7969 + } else {
7970 + message = NULL;
7971 + }
7972 + break;
7973 + }
7974 + http_info_dtor(&inf);
7975 +
7976 + return message;
7977 +}
7978 +
7979 +PHP_HTTP_API void _http_message_set_type(http_message *message, http_message_type type)
7980 +{
7981 + /* just act if different */
7982 + if (type != message->type) {
7983 +
7984 + /* free request info */
7985 + switch (message->type) {
7986 + case HTTP_MSG_REQUEST:
7987 + STR_FREE(message->http.info.request.method);
7988 + STR_FREE(message->http.info.request.url);
7989 + break;
7990 +
7991 + case HTTP_MSG_RESPONSE:
7992 + STR_FREE(message->http.info.response.status);
7993 + break;
7994 +
7995 + default:
7996 + break;
7997 + }
7998 +
7999 + /* init */
8000 + http_message_init_type(message, type);
8001 + }
8002 +}
8003 +
8004 +PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info)
8005 +{
8006 + http_message_set_type(message, info->type);
8007 + message->http.version = info->http.version;
8008 + switch (message->type) {
8009 + case IS_HTTP_REQUEST:
8010 + STR_SET(HTTP_INFO(message).request.url, HTTP_INFO(info).request.url ? estrdup(HTTP_INFO(info).request.url) : NULL);
8011 + STR_SET(HTTP_INFO(message).request.method, HTTP_INFO(info).request.method ? estrdup(HTTP_INFO(info).request.method) : NULL);
8012 + break;
8013 +
8014 + case IS_HTTP_RESPONSE:
8015 + HTTP_INFO(message).response.code = HTTP_INFO(info).response.code;
8016 + STR_SET(HTTP_INFO(message).response.status, HTTP_INFO(info).response.status ? estrdup(HTTP_INFO(info).response.status) : NULL);
8017 + break;
8018 +
8019 + default:
8020 + break;
8021 + }
8022 +}
8023 +
8024 +#define http_message_body_parse(m, ms, ml, c) _http_message_body_parse((m), (ms), (ml), (c) TSRMLS_CC)
8025 +static inline void _http_message_body_parse(http_message *msg, const char *message, size_t message_length, const char **continue_at TSRMLS_DC)
8026 +{
8027 + zval *c;
8028 + size_t remaining;
8029 + const char *body;
8030 +
8031 + *continue_at = NULL;
8032 + if ((body = http_locate_body(message))) {
8033 + remaining = message + message_length - body;
8034 +
8035 + if ((c = http_message_header(msg, "Transfer-Encoding"))) {
8036 + if (strstr(Z_STRVAL_P(c), "chunked")) {
8037 + /* message has chunked transfer encoding */
8038 + char *decoded;
8039 + size_t decoded_len;
8040 +
8041 + /* decode and replace Transfer-Encoding with Content-Length header */
8042 + if ((*continue_at = http_encoding_dechunk(body, message + message_length - body, &decoded, &decoded_len))) {
8043 + zval *len;
8044 + char *tmp;
8045 + int tmp_len;
8046 +
8047 + tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
8048 + MAKE_STD_ZVAL(len);
8049 + ZVAL_STRINGL(len, tmp, tmp_len, 0);
8050 +
8051 + ZVAL_ADDREF(c);
8052 + zend_hash_update(&msg->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &c, sizeof(zval *), NULL);
8053 + zend_hash_del(&msg->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
8054 + zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length"));
8055 + zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
8056 +
8057 + phpstr_from_string_ex(PHPSTR(msg), decoded, decoded_len);
8058 + efree(decoded);
8059 + }
8060 + }
8061 + zval_ptr_dtor(&c);
8062 + }
8063 +
8064 + if (!*continue_at && (c = http_message_header(msg, "Content-Length"))) {
8065 + /* message has content-length header */
8066 + ulong len = strtoul(Z_STRVAL_P(c), NULL, 10);
8067 + if (len > remaining) {
8068 + 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);
8069 + len = remaining;
8070 + }
8071 + phpstr_from_string_ex(PHPSTR(msg), body, len);
8072 + *continue_at = body + len;
8073 + zval_ptr_dtor(&c);
8074 + }
8075 +
8076 + if (!*continue_at && (c = http_message_header(msg, "Content-Range"))) {
8077 + /* message has content-range header */
8078 + ulong total = 0, start = 0, end = 0, len = 0;
8079 +
8080 + if (!strncasecmp(Z_STRVAL_P(c), "bytes", lenof("bytes")) &&
8081 + ( Z_STRVAL_P(c)[lenof("bytes")] == ':' ||
8082 + Z_STRVAL_P(c)[lenof("bytes")] == ' ' ||
8083 + Z_STRVAL_P(c)[lenof("bytes")] == '=')) {
8084 + char *total_at = NULL, *end_at = NULL;
8085 + char *start_at = Z_STRVAL_P(c) + sizeof("bytes");
8086 +
8087 + start = strtoul(start_at, &end_at, 10);
8088 + if (end_at) {
8089 + end = strtoul(end_at + 1, &total_at, 10);
8090 + if (total_at && strncmp(total_at + 1, "*", 1)) {
8091 + total = strtoul(total_at + 1, NULL, 10);
8092 + }
8093 + if ((len = (end + 1 - start)) > remaining) {
8094 + 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);
8095 + len = remaining;
8096 + }
8097 + if (end >= start && (!total || end < total)) {
8098 + phpstr_from_string_ex(PHPSTR(msg), body, len);
8099 + *continue_at = body + len;
8100 + }
8101 + }
8102 + }
8103 +
8104 + if (!*continue_at) {
8105 + http_error_ex(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid Content-Range header: %s", Z_STRVAL_P(c));
8106 + }
8107 + zval_ptr_dtor(&c);
8108 + }
8109 +
8110 + if (!*continue_at) {
8111 + /* no headers that indicate content length */
8112 + if (HTTP_MSG_TYPE(RESPONSE, msg)) {
8113 + phpstr_from_string_ex(PHPSTR(msg), body, remaining);
8114 + } else {
8115 + *continue_at = body;
8116 + }
8117 + }
8118 +
8119 +#ifdef HTTP_HAVE_ZLIB
8120 + /* check for compressed data */
8121 + if ((c = http_message_header(msg, "Content-Encoding"))) {
8122 + char *decoded = NULL;
8123 + size_t decoded_len = 0;
8124 +
8125 + if ( !strcasecmp(Z_STRVAL_P(c), "gzip") ||
8126 + !strcasecmp(Z_STRVAL_P(c), "x-gzip") ||
8127 + !strcasecmp(Z_STRVAL_P(c), "deflate")) {
8128 + http_encoding_inflate(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len);
8129 + }
8130 +
8131 + if (decoded) {
8132 + zval *len, **original_len;
8133 + char *tmp;
8134 + int tmp_len;
8135 +
8136 + tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
8137 + MAKE_STD_ZVAL(len);
8138 + ZVAL_STRINGL(len, tmp, tmp_len, 0);
8139 +
8140 + ZVAL_ADDREF(c);
8141 + zend_hash_update(&msg->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), (void *) &c, sizeof(zval *), NULL);
8142 + zend_hash_del(&msg->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
8143 + if (SUCCESS == zend_hash_find(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &original_len)) {
8144 + ZVAL_ADDREF(*original_len);
8145 + zend_hash_update(&msg->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) original_len, sizeof(zval *), NULL);
8146 + zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
8147 + } else {
8148 + zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
8149 + }
8150 +
8151 + phpstr_dtor(PHPSTR(msg));
8152 + PHPSTR(msg)->data = decoded;
8153 + PHPSTR(msg)->used = decoded_len;
8154 + PHPSTR(msg)->free = 1;
8155 + }
8156 +
8157 + zval_ptr_dtor(&c);
8158 + }
8159 +#endif /* HTTP_HAVE_ZLIB */
8160 + }
8161 +}
8162 +
8163 +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)
8164 +{
8165 + const char *continue_at;
8166 + zend_bool free_msg = msg ? 0 : 1;
8167 +
8168 + if ((!message) || (message_length < HTTP_MSG_MIN_SIZE)) {
8169 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Empty or too short HTTP message: '%s'", message);
8170 + return NULL;
8171 + }
8172 +
8173 + msg = http_message_init_rel(msg, 0);
8174 +
8175 + if (SUCCESS != http_parse_headers_cb(message, &msg->hdrs, 1, (http_info_callback) http_message_info_callback, (void *) &msg)) {
8176 + if (free_msg) {
8177 + http_message_free(&msg);
8178 + }
8179 + http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse message headers");
8180 + return NULL;
8181 + }
8182 +
8183 + http_message_body_parse(msg, message, message_length, &continue_at);
8184 +
8185 + /* check for following messages */
8186 + if (continue_at && (continue_at < (message + message_length))) {
8187 + while (HTTP_IS_CTYPE(space, *continue_at)) ++continue_at;
8188 + if (continue_at < (message + message_length)) {
8189 + http_message *next = NULL, *most = NULL;
8190 +
8191 + /* set current message to parent of most parent following messages and return deepest */
8192 + if ((most = next = http_message_parse_rel(NULL, continue_at, message + message_length - continue_at))) {
8193 + while (most->parent) most = most->parent;
8194 + most->parent = msg;
8195 + msg = next;
8196 + }
8197 + }
8198 + }
8199 +
8200 + return msg;
8201 +}
8202 +
8203 +PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length)
8204 +{
8205 + phpstr str;
8206 + HashKey key = initHashKey(0);
8207 + zval **header;
8208 + char *data;
8209 + HashPosition pos1;
8210 +
8211 + phpstr_init_ex(&str, 4096, 0);
8212 +
8213 + switch (msg->type) {
8214 + case HTTP_MSG_REQUEST:
8215 + phpstr_appendf(&str, HTTP_INFO_REQUEST_FMT_ARGS(&msg->http, HTTP_CRLF));
8216 + break;
8217 +
8218 + case HTTP_MSG_RESPONSE:
8219 + phpstr_appendf(&str, HTTP_INFO_RESPONSE_FMT_ARGS(&msg->http, HTTP_CRLF));
8220 + break;
8221 +
8222 + case HTTP_MSG_NONE:
8223 + default:
8224 + break;
8225 + }
8226 +
8227 + FOREACH_HASH_KEYVAL(pos1, &msg->hdrs, key, header) {
8228 + if (key.type == HASH_KEY_IS_STRING) {
8229 + HashPosition pos2;
8230 + zval **single_header;
8231 +
8232 + switch (Z_TYPE_PP(header)) {
8233 + case IS_BOOL:
8234 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(header)?"true":"false");
8235 + break;
8236 +
8237 + case IS_LONG:
8238 + phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(header));
8239 + break;
8240 +
8241 + case IS_DOUBLE:
8242 + phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(header));
8243 + break;
8244 +
8245 + case IS_STRING:
8246 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(header));
8247 + break;
8248 +
8249 + case IS_ARRAY:
8250 + FOREACH_VAL(pos2, *header, single_header) {
8251 + switch (Z_TYPE_PP(single_header)) {
8252 + case IS_BOOL:
8253 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(single_header)?"true":"false");
8254 + break;
8255 +
8256 + case IS_LONG:
8257 + phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(single_header));
8258 + break;
8259 +
8260 + case IS_DOUBLE:
8261 + phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(single_header));
8262 + break;
8263 +
8264 + case IS_STRING:
8265 + phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(single_header));
8266 + break;
8267 + }
8268 + }
8269 + break;
8270 + }
8271 + }
8272 + }
8273 +
8274 + if (PHPSTR_LEN(msg)) {
8275 + phpstr_appends(&str, HTTP_CRLF);
8276 + phpstr_append(&str, PHPSTR_VAL(msg), PHPSTR_LEN(msg));
8277 + phpstr_appends(&str, HTTP_CRLF);
8278 + }
8279 +
8280 + data = phpstr_data(&str, string, length);
8281 + if (!string) {
8282 + efree(data);
8283 + }
8284 +
8285 + phpstr_dtor(&str);
8286 +}
8287 +
8288 +PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length)
8289 +{
8290 + char *buf;
8291 + size_t len;
8292 + phpstr str;
8293 +
8294 + phpstr_init(&str);
8295 +
8296 + do {
8297 + http_message_tostring(message, &buf, &len);
8298 + phpstr_prepend(&str, buf, len);
8299 + efree(buf);
8300 + } while ((message = message->parent));
8301 +
8302 + buf = phpstr_data(&str, string, length);
8303 + if (!string) {
8304 + efree(buf);
8305 + }
8306 +
8307 + phpstr_dtor(&str);
8308 +}
8309 +
8310 +PHP_HTTP_API http_message *_http_message_reverse(http_message *msg)
8311 +{
8312 + int i, c;
8313 +
8314 + http_message_count(c, msg);
8315 +
8316 + if (c > 1) {
8317 + http_message *tmp = msg, **arr = ecalloc(c, sizeof(http_message *));
8318 +
8319 + for (i = 0; i < c; ++i) {
8320 + arr[i] = tmp;
8321 + tmp = tmp->parent;
8322 + }
8323 + arr[0]->parent = NULL;
8324 + for (i = 0; i < c-1; ++i) {
8325 + arr[i+1]->parent = arr[i];
8326 + }
8327 +
8328 + msg = arr[c-1];
8329 + efree(arr);
8330 + }
8331 +
8332 + return msg;
8333 +}
8334 +
8335 +PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2)
8336 +{
8337 + if (m1 && m2) {
8338 + int i = 0, c1, c2;
8339 + http_message *t1 = m1, *t2 = m2, *p1, *p2;
8340 +
8341 + http_message_count(c1, m1);
8342 + http_message_count(c2, m2);
8343 +
8344 + while (i++ < (c1 - c2)) {
8345 + t1 = t1->parent;
8346 + }
8347 + while (i++ <= c1) {
8348 + p1 = t1->parent;
8349 + p2 = t2->parent;
8350 + t1->parent = t2;
8351 + t2->parent = p1;
8352 + t1 = p1;
8353 + t2 = p2;
8354 + }
8355 + } else if (!m1 && m2) {
8356 + m1 = m2;
8357 + }
8358 + return m1;
8359 +}
8360 +
8361 +PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *obj TSRMLS_DC)
8362 +{
8363 + zval strct;
8364 + zval *headers;
8365 +
8366 + INIT_ZARR(strct, HASH_OF(obj));
8367 +
8368 + add_assoc_long(&strct, "type", msg->type);
8369 + add_assoc_double(&strct, "httpVersion", msg->http.version);
8370 + switch (msg->type)
8371 + {
8372 + case HTTP_MSG_RESPONSE:
8373 + add_assoc_long(&strct, "responseCode", msg->http.info.response.code);
8374 + add_assoc_string(&strct, "responseStatus", STR_PTR(msg->http.info.response.status), 1);
8375 + break;
8376 +
8377 + case HTTP_MSG_REQUEST:
8378 + add_assoc_string(&strct, "requestMethod", STR_PTR(msg->http.info.request.method), 1);
8379 + add_assoc_string(&strct, "requestUrl", STR_PTR(msg->http.info.request.url), 1);
8380 + break;
8381 +
8382 + case HTTP_MSG_NONE:
8383 + /* avoid compiler warning */
8384 + break;
8385 + }
8386 +
8387 + MAKE_STD_ZVAL(headers);
8388 + array_init(headers);
8389 + zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8390 + add_assoc_zval(&strct, "headers", headers);
8391 +
8392 + add_assoc_stringl(&strct, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg), 1);
8393 +
8394 + if (msg->parent) {
8395 + zval *parent;
8396 +
8397 + MAKE_STD_ZVAL(parent);
8398 + if (Z_TYPE_P(obj) == IS_ARRAY) {
8399 + array_init(parent);
8400 + } else {
8401 + object_init(parent);
8402 + }
8403 + add_assoc_zval(&strct, "parentMessage", parent);
8404 + http_message_tostruct_recursive(msg->parent, parent);
8405 + } else {
8406 + add_assoc_null(&strct, "parentMessage");
8407 + }
8408 +}
8409 +
8410 +PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC)
8411 +{
8412 + STATUS rs = FAILURE;
8413 +
8414 + switch (message->type) {
8415 + case HTTP_MSG_RESPONSE:
8416 + {
8417 + HashKey key = initHashKey(0);
8418 + zval **val;
8419 + HashPosition pos;
8420 +
8421 + FOREACH_HASH_KEYVAL(pos, &message->hdrs, key, val) {
8422 + if (key.type == HASH_KEY_IS_STRING) {
8423 + http_send_header_zval_ex(key.str, key.len-1, val, 1);
8424 + }
8425 + }
8426 + rs = SUCCESS == http_send_status(message->http.info.response.code) &&
8427 + SUCCESS == http_send_data(PHPSTR_VAL(message), PHPSTR_LEN(message)) ?
8428 + SUCCESS : FAILURE;
8429 + break;
8430 + }
8431 +
8432 + case HTTP_MSG_REQUEST:
8433 + {
8434 +#ifdef HTTP_HAVE_CURL
8435 + char *uri = NULL;
8436 + http_request request;
8437 + zval **zhost, *options, *headers;
8438 +
8439 + MAKE_STD_ZVAL(options);
8440 + MAKE_STD_ZVAL(headers);
8441 + array_init(options);
8442 + array_init(headers);
8443 + zend_hash_copy(Z_ARRVAL_P(headers), &message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8444 + add_assoc_zval(options, "headers", headers);
8445 +
8446 + /* check host header */
8447 + if (SUCCESS == zend_hash_find(&message->hdrs, "Host", sizeof("Host"), (void *) &zhost) && Z_TYPE_PP(zhost) == IS_STRING) {
8448 + char *colon = NULL;
8449 + php_url parts, *url = php_url_parse(message->http.info.request.url);
8450 +
8451 + memset(&parts, 0, sizeof(php_url));
8452 +
8453 + /* check for port */
8454 + if ((colon = strchr(Z_STRVAL_PP(zhost), ':'))) {
8455 + parts.port = atoi(colon + 1);
8456 + parts.host = estrndup(Z_STRVAL_PP(zhost), (Z_STRVAL_PP(zhost) - colon - 1));
8457 + } else {
8458 + parts.host = estrndup(Z_STRVAL_PP(zhost), Z_STRLEN_PP(zhost));
8459 + }
8460 +
8461 + http_build_url(HTTP_URL_REPLACE, url, &parts, NULL, &uri, NULL);
8462 + php_url_free(url);
8463 + efree(parts.host);
8464 + } else {
8465 + uri = http_absolute_url(message->http.info.request.url);
8466 + }
8467 +
8468 + if ((request.meth = http_request_method_exists(1, 0, message->http.info.request.method))) {
8469 + http_request_body body;
8470 +
8471 + http_request_init_ex(&request, NULL, request.meth, uri);
8472 + request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, PHPSTR_VAL(message), PHPSTR_LEN(message), 0);
8473 + if (SUCCESS == (rs = http_request_prepare(&request, Z_ARRVAL_P(options)))) {
8474 + http_request_exec(&request);
8475 + }
8476 + http_request_dtor(&request);
8477 + } else {
8478 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD,
8479 + "Cannot send HttpMessage. Request method %s not supported",
8480 + message->http.info.request.method);
8481 + }
8482 + efree(uri);
8483 + zval_ptr_dtor(&options);
8484 +#else
8485 + http_error(HE_WARNING, HTTP_E_RUNTIME, "HTTP requests not supported - ext/http was not linked against libcurl.");
8486 +#endif
8487 + break;
8488 + }
8489 +
8490 + case HTTP_MSG_NONE:
8491 + default:
8492 + http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HTTP_MSG_REQUEST nor HTTP_MSG_RESPONSE");
8493 + break;
8494 + }
8495 +
8496 + return rs;
8497 +}
8498 +
8499 +PHP_HTTP_API http_message *_http_message_dup(http_message *orig TSRMLS_DC)
8500 +{
8501 + http_message *temp, *copy = NULL;
8502 + http_info info;
8503 +
8504 + if (orig) {
8505 + info.type = orig->type;
8506 + info.http = orig->http;
8507 +
8508 + copy = temp = http_message_new();
8509 + http_message_set_info(temp, &info);
8510 + zend_hash_copy(&temp->hdrs, &orig->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8511 + phpstr_append(&temp->body, orig->body.data, orig->body.used);
8512 +
8513 + while (orig->parent) {
8514 + info.type = orig->parent->type;
8515 + info.http = orig->parent->http;
8516 +
8517 + temp->parent = http_message_new();
8518 + http_message_set_info(temp->parent, &info);
8519 + zend_hash_copy(&temp->parent->hdrs, &orig->parent->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8520 + phpstr_append(&temp->parent->body, orig->parent->body.data, orig->parent->body.used);
8521 +
8522 + temp = temp->parent;
8523 + orig = orig->parent;
8524 + }
8525 + }
8526 +
8527 + return copy;
8528 +}
8529 +
8530 +PHP_HTTP_API void _http_message_dtor(http_message *message)
8531 +{
8532 + if (message) {
8533 + zend_hash_destroy(&message->hdrs);
8534 + phpstr_dtor(PHPSTR(message));
8535 +
8536 + switch (message->type) {
8537 + case HTTP_MSG_REQUEST:
8538 + STR_SET(message->http.info.request.method, NULL);
8539 + STR_SET(message->http.info.request.url, NULL);
8540 + break;
8541 +
8542 + case HTTP_MSG_RESPONSE:
8543 + STR_SET(message->http.info.response.status, NULL);
8544 + break;
8545 +
8546 + default:
8547 + break;
8548 + }
8549 + }
8550 +}
8551 +
8552 +PHP_HTTP_API void _http_message_free(http_message **message)
8553 +{
8554 + if (*message) {
8555 + if ((*message)->parent) {
8556 + http_message_free(&(*message)->parent);
8557 + }
8558 + http_message_dtor(*message);
8559 + efree(*message);
8560 + *message = NULL;
8561 + }
8562 +}
8563 +
8564 +/*
8565 + * Local variables:
8566 + * tab-width: 4
8567 + * c-basic-offset: 4
8568 + * End:
8569 + * vim600: noet sw=4 ts=4 fdm=marker
8570 + * vim<600: noet sw=4 ts=4
8571 + */
8572 +
8573 --- /dev/null
8574 +++ b/ext/http/http_message_object.c
8575 @@ -0,0 +1,1555 @@
8576 +/*
8577 + +--------------------------------------------------------------------+
8578 + | PECL :: http |
8579 + +--------------------------------------------------------------------+
8580 + | Redistribution and use in source and binary forms, with or without |
8581 + | modification, are permitted provided that the conditions mentioned |
8582 + | in the accompanying LICENSE file are met. |
8583 + +--------------------------------------------------------------------+
8584 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
8585 + +--------------------------------------------------------------------+
8586 +*/
8587 +
8588 +/* $Id: http_message_object.c 323304 2012-02-17 21:13:24Z mike $ */
8589 +
8590 +#define HTTP_WANT_SAPI
8591 +#define HTTP_WANT_CURL
8592 +#define HTTP_WANT_MAGIC
8593 +#include "php_http.h"
8594 +
8595 +#ifdef ZEND_ENGINE_2
8596 +
8597 +#include "zend_interfaces.h"
8598 +#include "ext/standard/url.h"
8599 +#include "php_variables.h"
8600 +
8601 +#include "php_http_api.h"
8602 +#include "php_http_send_api.h"
8603 +#include "php_http_url_api.h"
8604 +#include "php_http_message_api.h"
8605 +#include "php_http_message_object.h"
8606 +#include "php_http_exception_object.h"
8607 +#include "php_http_response_object.h"
8608 +#include "php_http_request_method_api.h"
8609 +#include "php_http_request_api.h"
8610 +#include "php_http_request_object.h"
8611 +#include "php_http_headers_api.h"
8612 +
8613 +#if defined(HTTP_HAVE_SPL) && !defined(WONKY)
8614 +/* SPL doesn't install its headers */
8615 +extern PHPAPI zend_class_entry *spl_ce_Countable;
8616 +#endif
8617 +
8618 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpMessage, method, 0, req_args)
8619 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpMessage, method, 0)
8620 +#define HTTP_MESSAGE_ME(method, visibility) PHP_ME(HttpMessage, method, HTTP_ARGS(HttpMessage, method), visibility)
8621 +
8622 +HTTP_BEGIN_ARGS(__construct, 0)
8623 + HTTP_ARG_VAL(message, 0)
8624 +HTTP_END_ARGS;
8625 +
8626 +HTTP_BEGIN_ARGS(factory, 0)
8627 + HTTP_ARG_VAL(message, 0)
8628 + HTTP_ARG_VAL(class_name, 0)
8629 +HTTP_END_ARGS;
8630 +
8631 +HTTP_BEGIN_ARGS(fromEnv, 1)
8632 + HTTP_ARG_VAL(type, 0)
8633 + HTTP_ARG_VAL(class_name, 0)
8634 +HTTP_END_ARGS;
8635 +
8636 +HTTP_EMPTY_ARGS(getBody);
8637 +HTTP_BEGIN_ARGS(setBody, 1)
8638 + HTTP_ARG_VAL(body, 0)
8639 +HTTP_END_ARGS;
8640 +
8641 +HTTP_BEGIN_ARGS(getHeader, 1)
8642 + HTTP_ARG_VAL(header, 0)
8643 +HTTP_END_ARGS;
8644 +
8645 +HTTP_EMPTY_ARGS(getHeaders);
8646 +HTTP_BEGIN_ARGS(setHeaders, 1)
8647 + HTTP_ARG_VAL(headers, 0)
8648 +HTTP_END_ARGS;
8649 +
8650 +HTTP_BEGIN_ARGS(addHeaders, 1)
8651 + HTTP_ARG_VAL(headers, 0)
8652 + HTTP_ARG_VAL(append, 0)
8653 +HTTP_END_ARGS;
8654 +
8655 +HTTP_EMPTY_ARGS(getType);
8656 +HTTP_BEGIN_ARGS(setType, 1)
8657 + HTTP_ARG_VAL(type, 0)
8658 +HTTP_END_ARGS;
8659 +
8660 +HTTP_EMPTY_ARGS(getInfo);
8661 +HTTP_BEGIN_ARGS(setInfo, 1)
8662 + HTTP_ARG_VAL(http_info, 0)
8663 +HTTP_END_ARGS;
8664 +
8665 +HTTP_EMPTY_ARGS(getResponseCode);
8666 +HTTP_BEGIN_ARGS(setResponseCode, 1)
8667 + HTTP_ARG_VAL(response_code, 0)
8668 +HTTP_END_ARGS;
8669 +
8670 +HTTP_EMPTY_ARGS(getResponseStatus);
8671 +HTTP_BEGIN_ARGS(setResponseStatus, 1)
8672 + HTTP_ARG_VAL(response_status, 0)
8673 +HTTP_END_ARGS;
8674 +
8675 +HTTP_EMPTY_ARGS(getRequestMethod);
8676 +HTTP_BEGIN_ARGS(setRequestMethod, 1)
8677 + HTTP_ARG_VAL(request_method, 0)
8678 +HTTP_END_ARGS;
8679 +
8680 +HTTP_EMPTY_ARGS(getRequestUrl);
8681 +HTTP_BEGIN_ARGS(setRequestUrl, 1)
8682 + HTTP_ARG_VAL(url, 0)
8683 +HTTP_END_ARGS;
8684 +
8685 +HTTP_EMPTY_ARGS(getHttpVersion);
8686 +HTTP_BEGIN_ARGS(setHttpVersion, 1)
8687 + HTTP_ARG_VAL(http_version, 0)
8688 +HTTP_END_ARGS;
8689 +
8690 +HTTP_BEGIN_ARGS(guessContentType, 1)
8691 + HTTP_ARG_VAL(magic_file, 0)
8692 + HTTP_ARG_VAL(magic_mode, 0)
8693 +HTTP_END_ARGS;
8694 +
8695 +HTTP_EMPTY_ARGS(getParentMessage);
8696 +HTTP_EMPTY_ARGS(send);
8697 +HTTP_EMPTY_ARGS(__toString);
8698 +HTTP_BEGIN_ARGS(toString, 0)
8699 + HTTP_ARG_VAL(include_parent, 0)
8700 +HTTP_END_ARGS;
8701 +
8702 +HTTP_EMPTY_ARGS(toMessageTypeObject);
8703 +
8704 +HTTP_EMPTY_ARGS(count);
8705 +
8706 +HTTP_EMPTY_ARGS(serialize);
8707 +HTTP_BEGIN_ARGS(unserialize, 1)
8708 + HTTP_ARG_VAL(serialized, 0)
8709 +HTTP_END_ARGS;
8710 +
8711 +HTTP_EMPTY_ARGS(rewind);
8712 +HTTP_EMPTY_ARGS(valid);
8713 +HTTP_EMPTY_ARGS(key);
8714 +HTTP_EMPTY_ARGS(current);
8715 +HTTP_EMPTY_ARGS(next);
8716 +
8717 +HTTP_EMPTY_ARGS(detach);
8718 +HTTP_BEGIN_ARGS(prepend, 1)
8719 + HTTP_ARG_OBJ(HttpMessage, message, 0)
8720 +HTTP_END_ARGS;
8721 +HTTP_EMPTY_ARGS(reverse);
8722 +
8723 +#define http_message_object_read_prop _http_message_object_read_prop
8724 +static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC);
8725 +#define http_message_object_write_prop _http_message_object_write_prop
8726 +static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC);
8727 +#define http_message_object_get_prop_ptr _http_message_object_get_prop_ptr
8728 +static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC);
8729 +#define http_message_object_get_props _http_message_object_get_props
8730 +static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC);
8731 +
8732 +#define THIS_CE http_message_object_ce
8733 +zend_class_entry *http_message_object_ce;
8734 +zend_function_entry http_message_object_fe[] = {
8735 + HTTP_MESSAGE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
8736 + HTTP_MESSAGE_ME(getBody, ZEND_ACC_PUBLIC)
8737 + HTTP_MESSAGE_ME(setBody, ZEND_ACC_PUBLIC)
8738 + HTTP_MESSAGE_ME(getHeader, ZEND_ACC_PUBLIC)
8739 + HTTP_MESSAGE_ME(getHeaders, ZEND_ACC_PUBLIC)
8740 + HTTP_MESSAGE_ME(setHeaders, ZEND_ACC_PUBLIC)
8741 + HTTP_MESSAGE_ME(addHeaders, ZEND_ACC_PUBLIC)
8742 + HTTP_MESSAGE_ME(getType, ZEND_ACC_PUBLIC)
8743 + HTTP_MESSAGE_ME(setType, ZEND_ACC_PUBLIC)
8744 + HTTP_MESSAGE_ME(getInfo, ZEND_ACC_PUBLIC)
8745 + HTTP_MESSAGE_ME(setInfo, ZEND_ACC_PUBLIC)
8746 + HTTP_MESSAGE_ME(getResponseCode, ZEND_ACC_PUBLIC)
8747 + HTTP_MESSAGE_ME(setResponseCode, ZEND_ACC_PUBLIC)
8748 + HTTP_MESSAGE_ME(getResponseStatus, ZEND_ACC_PUBLIC)
8749 + HTTP_MESSAGE_ME(setResponseStatus, ZEND_ACC_PUBLIC)
8750 + HTTP_MESSAGE_ME(getRequestMethod, ZEND_ACC_PUBLIC)
8751 + HTTP_MESSAGE_ME(setRequestMethod, ZEND_ACC_PUBLIC)
8752 + HTTP_MESSAGE_ME(getRequestUrl, ZEND_ACC_PUBLIC)
8753 + HTTP_MESSAGE_ME(setRequestUrl, ZEND_ACC_PUBLIC)
8754 + HTTP_MESSAGE_ME(getHttpVersion, ZEND_ACC_PUBLIC)
8755 + HTTP_MESSAGE_ME(setHttpVersion, ZEND_ACC_PUBLIC)
8756 + HTTP_MESSAGE_ME(guessContentType, ZEND_ACC_PUBLIC)
8757 + HTTP_MESSAGE_ME(getParentMessage, ZEND_ACC_PUBLIC)
8758 + HTTP_MESSAGE_ME(send, ZEND_ACC_PUBLIC)
8759 + HTTP_MESSAGE_ME(toString, ZEND_ACC_PUBLIC)
8760 + HTTP_MESSAGE_ME(toMessageTypeObject, ZEND_ACC_PUBLIC)
8761 +
8762 + /* implements Countable */
8763 + HTTP_MESSAGE_ME(count, ZEND_ACC_PUBLIC)
8764 +
8765 + /* implements Serializable */
8766 + HTTP_MESSAGE_ME(serialize, ZEND_ACC_PUBLIC)
8767 + HTTP_MESSAGE_ME(unserialize, ZEND_ACC_PUBLIC)
8768 +
8769 + /* implements Iterator */
8770 + HTTP_MESSAGE_ME(rewind, ZEND_ACC_PUBLIC)
8771 + HTTP_MESSAGE_ME(valid, ZEND_ACC_PUBLIC)
8772 + HTTP_MESSAGE_ME(current, ZEND_ACC_PUBLIC)
8773 + HTTP_MESSAGE_ME(key, ZEND_ACC_PUBLIC)
8774 + HTTP_MESSAGE_ME(next, ZEND_ACC_PUBLIC)
8775 +
8776 + ZEND_MALIAS(HttpMessage, __toString, toString, HTTP_ARGS(HttpMessage, __toString), ZEND_ACC_PUBLIC)
8777 +
8778 + HTTP_MESSAGE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
8779 + ZEND_MALIAS(HttpMessage, fromString, factory, HTTP_ARGS(HttpMessage, factory), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
8780 + HTTP_MESSAGE_ME(fromEnv, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
8781 +
8782 + HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC)
8783 + HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC)
8784 + HTTP_MESSAGE_ME(reverse, ZEND_ACC_PUBLIC)
8785 +
8786 + EMPTY_FUNCTION_ENTRY
8787 +};
8788 +static zend_object_handlers http_message_object_handlers;
8789 +
8790 +static HashTable http_message_object_prophandlers;
8791 +
8792 +typedef void (*http_message_object_prophandler_func)(http_message_object *o, zval *v TSRMLS_DC);
8793 +
8794 +typedef struct _http_message_object_prophandler {
8795 + http_message_object_prophandler_func read;
8796 + http_message_object_prophandler_func write;
8797 +} http_message_object_prophandler;
8798 +
8799 +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) {
8800 + http_message_object_prophandler h = { read, write };
8801 + return zend_hash_add(&http_message_object_prophandlers, prop_str, prop_len, (void *) &h, sizeof(h), NULL);
8802 +}
8803 +static STATUS http_message_object_get_prophandler(const char *prop_str, size_t prop_len, http_message_object_prophandler **handler) {
8804 + return zend_hash_find(&http_message_object_prophandlers, prop_str, prop_len, (void *) handler);
8805 +}
8806 +static void http_message_object_prophandler_get_type(http_message_object *obj, zval *return_value TSRMLS_DC) {
8807 + RETVAL_LONG(obj->message->type);
8808 +}
8809 +static void http_message_object_prophandler_set_type(http_message_object *obj, zval *value TSRMLS_DC) {
8810 + zval *cpy = http_zsep(IS_LONG, value);
8811 + http_message_set_type(obj->message, Z_LVAL_P(cpy));
8812 + zval_ptr_dtor(&cpy);
8813 +}
8814 +static void http_message_object_prophandler_get_body(http_message_object *obj, zval *return_value TSRMLS_DC) {
8815 + phpstr_fix(PHPSTR(obj->message));
8816 + RETVAL_PHPSTR(PHPSTR(obj->message), 0, 1);
8817 +}
8818 +static void http_message_object_prophandler_set_body(http_message_object *obj, zval *value TSRMLS_DC) {
8819 + zval *cpy = http_zsep(IS_STRING, value);
8820 + phpstr_dtor(PHPSTR(obj->message));
8821 + phpstr_from_string_ex(PHPSTR(obj->message), Z_STRVAL_P(cpy), Z_STRLEN_P(cpy));
8822 + zval_ptr_dtor(&cpy);
8823 +}
8824 +static void http_message_object_prophandler_get_request_method(http_message_object *obj, zval *return_value TSRMLS_DC) {
8825 + if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.method) {
8826 + RETVAL_STRING(obj->message->http.info.request.method, 1);
8827 + } else {
8828 + RETVAL_NULL();
8829 + }
8830 +}
8831 +static void http_message_object_prophandler_set_request_method(http_message_object *obj, zval *value TSRMLS_DC) {
8832 + if (HTTP_MSG_TYPE(REQUEST, obj->message)) {
8833 + zval *cpy = http_zsep(IS_STRING, value);
8834 + STR_SET(obj->message->http.info.request.method, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
8835 + zval_ptr_dtor(&cpy);
8836 + }
8837 +}
8838 +static void http_message_object_prophandler_get_request_url(http_message_object *obj, zval *return_value TSRMLS_DC) {
8839 + if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.url) {
8840 + RETVAL_STRING(obj->message->http.info.request.url, 1);
8841 + } else {
8842 + RETVAL_NULL();
8843 + }
8844 +}
8845 +static void http_message_object_prophandler_set_request_url(http_message_object *obj, zval *value TSRMLS_DC) {
8846 + if (HTTP_MSG_TYPE(REQUEST, obj->message)) {
8847 + zval *cpy = http_zsep(IS_STRING, value);
8848 + STR_SET(obj->message->http.info.request.url, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
8849 + zval_ptr_dtor(&cpy);
8850 + }
8851 +}
8852 +static void http_message_object_prophandler_get_response_status(http_message_object *obj, zval *return_value TSRMLS_DC) {
8853 + if (HTTP_MSG_TYPE(RESPONSE, obj->message) && obj->message->http.info.response.status) {
8854 + RETVAL_STRING(obj->message->http.info.response.status, 1);
8855 + } else {
8856 + RETVAL_NULL();
8857 + }
8858 +}
8859 +static void http_message_object_prophandler_set_response_status(http_message_object *obj, zval *value TSRMLS_DC) {
8860 + if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
8861 + zval *cpy = http_zsep(IS_STRING, value);
8862 + STR_SET(obj->message->http.info.response.status, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
8863 + zval_ptr_dtor(&cpy);
8864 + }
8865 +}
8866 +static void http_message_object_prophandler_get_response_code(http_message_object *obj, zval *return_value TSRMLS_DC) {
8867 + if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
8868 + RETVAL_LONG(obj->message->http.info.response.code);
8869 + } else {
8870 + RETVAL_NULL();
8871 + }
8872 +}
8873 +static void http_message_object_prophandler_set_response_code(http_message_object *obj, zval *value TSRMLS_DC) {
8874 + if (HTTP_MSG_TYPE(RESPONSE, obj->message)) {
8875 + zval *cpy = http_zsep(IS_LONG, value);
8876 + obj->message->http.info.response.code = Z_LVAL_P(cpy);
8877 + zval_ptr_dtor(&cpy);
8878 + }
8879 +}
8880 +static void http_message_object_prophandler_get_http_version(http_message_object *obj, zval *return_value TSRMLS_DC) {
8881 + RETVAL_DOUBLE(obj->message->http.version);
8882 +}
8883 +static void http_message_object_prophandler_set_http_version(http_message_object *obj, zval *value TSRMLS_DC) {
8884 + zval *cpy = http_zsep(IS_DOUBLE, value);
8885 + obj->message->http.version = Z_DVAL_P(cpy);
8886 + zval_ptr_dtor(&cpy);
8887 +}
8888 +static void http_message_object_prophandler_get_headers(http_message_object *obj, zval *return_value TSRMLS_DC) {
8889 + array_init(return_value);
8890 + zend_hash_copy(Z_ARRVAL_P(return_value), &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8891 +}
8892 +static void http_message_object_prophandler_set_headers(http_message_object *obj, zval *value TSRMLS_DC) {
8893 + zval *cpy = http_zsep(IS_ARRAY, value);
8894 + zend_hash_clean(&obj->message->hdrs);
8895 + zend_hash_copy(&obj->message->hdrs, Z_ARRVAL_P(cpy), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
8896 + zval_ptr_dtor(&cpy);
8897 +}
8898 +static void http_message_object_prophandler_get_parent_message(http_message_object *obj, zval *return_value TSRMLS_DC) {
8899 + if (obj->message->parent) {
8900 + RETVAL_OBJVAL(obj->parent, 1);
8901 + } else {
8902 + RETVAL_NULL();
8903 + }
8904 +}
8905 +static void http_message_object_prophandler_set_parent_message(http_message_object *obj, zval *value TSRMLS_DC) {
8906 + if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), http_message_object_ce TSRMLS_CC)) {
8907 + if (obj->message->parent) {
8908 + zval tmp;
8909 + tmp.value.obj = obj->parent;
8910 + Z_OBJ_DELREF(tmp);
8911 + }
8912 + Z_OBJ_ADDREF_P(value);
8913 + obj->parent = value->value.obj;
8914 + }
8915 +}
8916 +
8917 +PHP_MINIT_FUNCTION(http_message_object)
8918 +{
8919 + HTTP_REGISTER_CLASS_EX(HttpMessage, http_message_object, NULL, 0);
8920 +
8921 +#ifndef WONKY
8922 +# ifdef HTTP_HAVE_SPL
8923 + zend_class_implements(http_message_object_ce TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator);
8924 +# else
8925 + zend_class_implements(http_message_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_iterator);
8926 +# endif
8927 +#else
8928 + zend_class_implements(http_message_object_ce TSRMLS_CC, 1, zend_ce_iterator);
8929 +#endif
8930 +
8931 + http_message_object_handlers.clone_obj = _http_message_object_clone_obj;
8932 + http_message_object_handlers.read_property = http_message_object_read_prop;
8933 + http_message_object_handlers.write_property = http_message_object_write_prop;
8934 + http_message_object_handlers.get_properties = http_message_object_get_props;
8935 + http_message_object_handlers.get_property_ptr_ptr = http_message_object_get_prop_ptr;
8936 +
8937 + zend_hash_init(&http_message_object_prophandlers, 9, NULL, NULL, 1);
8938 + zend_declare_property_long(THIS_CE, ZEND_STRS("type")-1, HTTP_MSG_NONE, ZEND_ACC_PROTECTED TSRMLS_CC);
8939 + http_message_object_add_prophandler(ZEND_STRS("type")-1, http_message_object_prophandler_get_type, http_message_object_prophandler_set_type);
8940 + zend_declare_property_string(THIS_CE, ZEND_STRS("body")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8941 + http_message_object_add_prophandler(ZEND_STRS("body")-1, http_message_object_prophandler_get_body, http_message_object_prophandler_set_body);
8942 + zend_declare_property_string(THIS_CE, ZEND_STRS("requestMethod")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8943 + http_message_object_add_prophandler(ZEND_STRS("requestMethod")-1, http_message_object_prophandler_get_request_method, http_message_object_prophandler_set_request_method);
8944 + zend_declare_property_string(THIS_CE, ZEND_STRS("requestUrl")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8945 + http_message_object_add_prophandler(ZEND_STRS("requestUrl")-1, http_message_object_prophandler_get_request_url, http_message_object_prophandler_set_request_url);
8946 + zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
8947 + http_message_object_add_prophandler(ZEND_STRS("responseStatus")-1, http_message_object_prophandler_get_response_status, http_message_object_prophandler_set_response_status);
8948 + zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC);
8949 + http_message_object_add_prophandler(ZEND_STRS("responseCode")-1, http_message_object_prophandler_get_response_code, http_message_object_prophandler_set_response_code);
8950 + zend_declare_property_null(THIS_CE, ZEND_STRS("httpVersion")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
8951 + http_message_object_add_prophandler(ZEND_STRS("httpVersion")-1, http_message_object_prophandler_get_http_version, http_message_object_prophandler_set_http_version);
8952 + zend_declare_property_null(THIS_CE, ZEND_STRS("headers")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
8953 + http_message_object_add_prophandler(ZEND_STRS("headers")-1, http_message_object_prophandler_get_headers, http_message_object_prophandler_set_headers);
8954 + zend_declare_property_null(THIS_CE, ZEND_STRS("parentMessage")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
8955 + http_message_object_add_prophandler(ZEND_STRS("parentMessage")-1, http_message_object_prophandler_get_parent_message, http_message_object_prophandler_set_parent_message);
8956 +
8957 +#ifndef WONKY
8958 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_NONE")-1, HTTP_MSG_NONE TSRMLS_CC);
8959 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_REQUEST")-1, HTTP_MSG_REQUEST TSRMLS_CC);
8960 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RESPONSE")-1, HTTP_MSG_RESPONSE TSRMLS_CC);
8961 +#endif
8962 +
8963 + HTTP_LONG_CONSTANT("HTTP_MSG_NONE", HTTP_MSG_NONE);
8964 + HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST);
8965 + HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE);
8966 +
8967 + return SUCCESS;
8968 +}
8969 +
8970 +PHP_MSHUTDOWN_FUNCTION(http_message_object)
8971 +{
8972 + zend_hash_destroy(&http_message_object_prophandlers);
8973 +
8974 + return SUCCESS;
8975 +}
8976 +
8977 +void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC)
8978 +{
8979 + int i;
8980 + getObject(http_message_object, obj);
8981 +
8982 + /* count */
8983 + http_message_count(i, obj->message);
8984 +
8985 + if (i > 1) {
8986 + zval o;
8987 + zend_object_value *ovalues = NULL;
8988 + http_message_object **objects = NULL;
8989 + int last = i - 1;
8990 +
8991 + objects = ecalloc(i, sizeof(http_message_object *));
8992 + ovalues = ecalloc(i, sizeof(zend_object_value));
8993 +
8994 + /* we are the first message */
8995 + objects[0] = obj;
8996 + ovalues[0] = getThis()->value.obj;
8997 +
8998 + /* fetch parents */
8999 + INIT_PZVAL(&o);
9000 + o.type = IS_OBJECT;
9001 + for (i = 1; obj->parent.handle; ++i) {
9002 + o.value.obj = obj->parent;
9003 + ovalues[i] = o.value.obj;
9004 + objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC);
9005 + }
9006 +
9007 + /* reorder parents */
9008 + for (last = --i; i; --i) {
9009 + objects[i]->message->parent = objects[i-1]->message;
9010 + objects[i]->parent = ovalues[i-1];
9011 + }
9012 + objects[0]->message->parent = NULL;
9013 + objects[0]->parent.handle = 0;
9014 + objects[0]->parent.handlers = NULL;
9015 +
9016 + /* add ref (why?) */
9017 + Z_OBJ_ADDREF_P(getThis());
9018 + RETVAL_OBJVAL(ovalues[last], 1);
9019 +
9020 + efree(objects);
9021 + efree(ovalues);
9022 + } else {
9023 + RETURN_ZVAL(getThis(), 1, 0);
9024 + }
9025 +}
9026 +
9027 +void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC)
9028 +{
9029 + zval m;
9030 + http_message *save_parent_msg = NULL;
9031 + zend_object_value save_parent_obj = {0, NULL};
9032 + getObject(http_message_object, obj);
9033 + getObjectEx(http_message_object, prepend_obj, prepend);
9034 +
9035 + INIT_PZVAL(&m);
9036 + m.type = IS_OBJECT;
9037 +
9038 + if (!top) {
9039 + save_parent_obj = obj->parent;
9040 + save_parent_msg = obj->message->parent;
9041 + } else {
9042 + /* iterate to the most parent object */
9043 + while (obj->parent.handle) {
9044 + m.value.obj = obj->parent;
9045 + obj = zend_object_store_get_object(&m TSRMLS_CC);
9046 + }
9047 + }
9048 +
9049 + /* prepend */
9050 + obj->parent = prepend->value.obj;
9051 + obj->message->parent = prepend_obj->message;
9052 +
9053 + /* add ref */
9054 + zend_objects_store_add_ref(prepend TSRMLS_CC);
9055 + while (prepend_obj->parent.handle) {
9056 + m.value.obj = prepend_obj->parent;
9057 + zend_objects_store_add_ref(&m TSRMLS_CC);
9058 + prepend_obj = zend_object_store_get_object(&m TSRMLS_CC);
9059 + }
9060 +
9061 + if (!top) {
9062 + prepend_obj->parent = save_parent_obj;
9063 + prepend_obj->message->parent = save_parent_msg;
9064 + }
9065 +}
9066 +
9067 +zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC)
9068 +{
9069 + return http_message_object_new_ex(ce, NULL, NULL);
9070 +}
9071 +
9072 +zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC)
9073 +{
9074 + zend_object_value ov;
9075 + http_message_object *o;
9076 +
9077 + o = ecalloc(1, sizeof(http_message_object));
9078 + o->zo.ce = ce;
9079 +
9080 + if (ptr) {
9081 + *ptr = o;
9082 + }
9083 +
9084 + if (msg) {
9085 + o->message = msg;
9086 + if (msg->parent) {
9087 + o->parent = http_message_object_new_ex(ce, msg->parent, NULL);
9088 + }
9089 + }
9090 +
9091 +
9092 +#ifdef ZEND_ENGINE_2_4
9093 + zend_object_std_init(o, ce TSRMLS_CC);
9094 + object_properties_init(o, ce);
9095 +#else
9096 + ALLOC_HASHTABLE(OBJ_PROP(o));
9097 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
9098 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
9099 +#endif
9100 +
9101 + ov.handle = putObject(http_message_object, o);
9102 + ov.handlers = &http_message_object_handlers;
9103 +
9104 + return ov;
9105 +}
9106 +
9107 +zend_object_value _http_message_object_clone_obj(zval *this_ptr TSRMLS_DC)
9108 +{
9109 + zend_object_value new_ov;
9110 + http_message_object *new_obj = NULL;
9111 + getObject(http_message_object, old_obj);
9112 +
9113 + new_ov = http_message_object_new_ex(old_obj->zo.ce, http_message_dup(old_obj->message), &new_obj);
9114 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
9115 +
9116 + return new_ov;
9117 +}
9118 +
9119 +void _http_message_object_free(zend_object *object TSRMLS_DC)
9120 +{
9121 + http_message_object *o = (http_message_object *) object;
9122 +
9123 + if (o->iterator) {
9124 + zval_ptr_dtor(&o->iterator);
9125 + o->iterator = NULL;
9126 + }
9127 + if (o->message) {
9128 + http_message_dtor(o->message);
9129 + efree(o->message);
9130 + }
9131 + if (o->parent.handle) {
9132 + zval p;
9133 +
9134 + INIT_PZVAL(&p);
9135 + p.type = IS_OBJECT;
9136 + p.value.obj = o->parent;
9137 + zend_objects_store_del_ref(&p TSRMLS_CC);
9138 + }
9139 + freeObject(o);
9140 +}
9141 +
9142 +static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC) {
9143 + getObjectEx(http_message_object, obj, object);
9144 + http_message_object_prophandler *handler;
9145 +
9146 + if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
9147 + zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index");
9148 + return NULL;
9149 + }
9150 +
9151 + return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member ZEND_LITERAL_KEY_CC TSRMLS_CC);
9152 +}
9153 +
9154 +static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC)
9155 +{
9156 + getObjectEx(http_message_object, obj, object);
9157 + http_message_object_prophandler *handler;
9158 + zval *return_value;
9159 +
9160 + if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
9161 + if (type == BP_VAR_W) {
9162 + zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index");
9163 + return NULL;
9164 + }
9165 +
9166 + ALLOC_ZVAL(return_value);
9167 +#ifdef Z_SET_REFCOUNT
9168 + Z_SET_REFCOUNT_P(return_value, 0);
9169 + Z_UNSET_ISREF_P(return_value);
9170 +#else
9171 + return_value->refcount = 0;
9172 + return_value->is_ref = 0;
9173 +#endif
9174 +
9175 + handler->read(obj, return_value TSRMLS_CC);
9176 +
9177 + } else {
9178 + return_value = zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC);
9179 + }
9180 +
9181 + return return_value;
9182 +}
9183 +
9184 +static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC)
9185 +{
9186 + getObjectEx(http_message_object, obj, object);
9187 + http_message_object_prophandler *handler;
9188 +
9189 + if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) {
9190 + handler->write(obj, value TSRMLS_CC);
9191 + } else {
9192 + zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC);
9193 + }
9194 +}
9195 +
9196 +static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC)
9197 +{
9198 + zval *headers;
9199 + getObjectEx(http_message_object, obj, object);
9200 + http_message *msg = obj->message;
9201 + zval array, *parent;
9202 +#ifdef ZEND_ENGINE_2_4
9203 + HashTable *props = zend_get_std_object_handlers()->get_properties(object TSRMLS_CC);
9204 +#else
9205 + HashTable *props = OBJ_PROP(obj);
9206 +#endif
9207 + INIT_ZARR(array, props);
9208 +
9209 +#define ASSOC_PROP(array, ptype, name, val) \
9210 + { \
9211 + char *m_prop_name; \
9212 + int m_prop_len; \
9213 + zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
9214 + add_assoc_ ##ptype## _ex(&array, m_prop_name, sizeof(name)+3, val); \
9215 + efree(m_prop_name); \
9216 + }
9217 +#define ASSOC_STRING(array, name, val) ASSOC_STRINGL(array, name, val, strlen(val))
9218 +#define ASSOC_STRINGL(array, name, val, len) \
9219 + { \
9220 + char *m_prop_name; \
9221 + int m_prop_len; \
9222 + zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
9223 + add_assoc_stringl_ex(&array, m_prop_name, sizeof(name)+3, val, len, 1); \
9224 + efree(m_prop_name); \
9225 + }
9226 +
9227 + ASSOC_PROP(array, long, "type", msg->type);
9228 + ASSOC_PROP(array, double, "httpVersion", msg->http.version);
9229 +
9230 + switch (msg->type) {
9231 + case HTTP_MSG_REQUEST:
9232 + ASSOC_PROP(array, long, "responseCode", 0);
9233 + ASSOC_STRINGL(array, "responseStatus", "", 0);
9234 + ASSOC_STRING(array, "requestMethod", STR_PTR(msg->http.info.request.method));
9235 + ASSOC_STRING(array, "requestUrl", STR_PTR(msg->http.info.request.url));
9236 + break;
9237 +
9238 + case HTTP_MSG_RESPONSE:
9239 + ASSOC_PROP(array, long, "responseCode", msg->http.info.response.code);
9240 + ASSOC_STRING(array, "responseStatus", STR_PTR(msg->http.info.response.status));
9241 + ASSOC_STRINGL(array, "requestMethod", "", 0);
9242 + ASSOC_STRINGL(array, "requestUrl", "", 0);
9243 + break;
9244 +
9245 + case HTTP_MSG_NONE:
9246 + default:
9247 + ASSOC_PROP(array, long, "responseCode", 0);
9248 + ASSOC_STRINGL(array, "responseStatus", "", 0);
9249 + ASSOC_STRINGL(array, "requestMethod", "", 0);
9250 + ASSOC_STRINGL(array, "requestUrl", "", 0);
9251 + break;
9252 + }
9253 +
9254 + MAKE_STD_ZVAL(headers);
9255 + array_init(headers);
9256 + zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
9257 + ASSOC_PROP(array, zval, "headers", headers);
9258 + ASSOC_STRINGL(array, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg));
9259 +
9260 + MAKE_STD_ZVAL(parent);
9261 + if (msg->parent) {
9262 + ZVAL_OBJVAL(parent, obj->parent, 1);
9263 + } else {
9264 + ZVAL_NULL(parent);
9265 + }
9266 + ASSOC_PROP(array, zval, "parentMessage", parent);
9267 +
9268 + return props;
9269 +}
9270 +
9271 +/* ### USERLAND ### */
9272 +
9273 +/* {{{ proto void HttpMessage::__construct([string message])
9274 + Create a new HttpMessage object instance. */
9275 +PHP_METHOD(HttpMessage, __construct)
9276 +{
9277 + int length = 0;
9278 + char *message = NULL;
9279 +
9280 + getObject(http_message_object, obj);
9281 +
9282 + SET_EH_THROW_HTTP();
9283 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) {
9284 + http_message *msg = obj->message;
9285 +
9286 + http_message_dtor(msg);
9287 + if ((obj->message = http_message_parse_ex(msg, message, length))) {
9288 + if (obj->message->parent) {
9289 + obj->parent = http_message_object_new_ex(Z_OBJCE_P(getThis()), obj->message->parent, NULL);
9290 + }
9291 + } else {
9292 + obj->message = http_message_init(msg);
9293 + }
9294 + }
9295 + if (!obj->message) {
9296 + obj->message = http_message_new();
9297 + }
9298 + SET_EH_NORMAL();
9299 +}
9300 +/* }}} */
9301 +
9302 +/* {{{ proto static HttpMessage HttpMessage::factory([string raw_message[, string class_name = "HttpMessage"]])
9303 + Create a new HttpMessage object instance. */
9304 +PHP_METHOD(HttpMessage, factory)
9305 +{
9306 + char *string = NULL, *cn = NULL;
9307 + int length = 0, cl = 0;
9308 + http_message *msg = NULL;
9309 + zend_object_value ov;
9310 + http_message_object *obj = NULL;
9311 +
9312 + RETVAL_NULL();
9313 +
9314 + SET_EH_THROW_HTTP();
9315 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &string, &length, &cn, &cl)) {
9316 + if (length) {
9317 + msg = http_message_parse(string, length);
9318 + }
9319 + if ((msg || !length) && SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, msg, &obj)) {
9320 + RETVAL_OBJVAL(ov, 0);
9321 + }
9322 + if (obj && !obj->message) {
9323 + obj->message = http_message_new();
9324 + }
9325 + }
9326 + SET_EH_NORMAL();
9327 +}
9328 +/* }}} */
9329 +
9330 +/* {{{ proto static HttpMessage HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"])
9331 + Create a new HttpMessage object from environment representing either current request or response */
9332 +PHP_METHOD(HttpMessage, fromEnv)
9333 +{
9334 + char *cn = NULL;
9335 + int cl = 0;
9336 + long type;
9337 + http_message_object *obj = NULL;
9338 + zend_object_value ov;
9339 +
9340 + RETVAL_NULL();
9341 + SET_EH_THROW_HTTP();
9342 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &type, &cn, &cl)) {
9343 + if (SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, http_message_init_env(NULL, type), &obj)) {
9344 + RETVAL_OBJVAL(ov, 0);
9345 + }
9346 + if (obj && !obj->message) {
9347 + obj->message = http_message_new();
9348 + }
9349 + }
9350 + SET_EH_NORMAL();
9351 +}
9352 +/* }}} */
9353 +
9354 +/* {{{ proto string HttpMessage::getBody()
9355 + Get the body of the parsed HttpMessage. */
9356 +PHP_METHOD(HttpMessage, getBody)
9357 +{
9358 + NO_ARGS;
9359 +
9360 + if (return_value_used) {
9361 + getObject(http_message_object, obj);
9362 + RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
9363 + }
9364 +}
9365 +/* }}} */
9366 +
9367 +/* {{{ proto void HttpMessage::setBody(string body)
9368 + Set the body of the HttpMessage. NOTE: Don't forget to update any headers accordingly. */
9369 +PHP_METHOD(HttpMessage, setBody)
9370 +{
9371 + char *body;
9372 + int len;
9373 + getObject(http_message_object, obj);
9374 +
9375 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &body, &len)) {
9376 + phpstr_dtor(PHPSTR(obj->message));
9377 + phpstr_from_string_ex(PHPSTR(obj->message), body, len);
9378 + }
9379 +}
9380 +/* }}} */
9381 +
9382 +/* {{{ proto string HttpMessage::getHeader(string header)
9383 + Get message header. */
9384 +PHP_METHOD(HttpMessage, getHeader)
9385 +{
9386 + zval *header;
9387 + char *orig_header, *nice_header;
9388 + int header_len;
9389 + getObject(http_message_object, obj);
9390 +
9391 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &orig_header, &header_len)) {
9392 + RETURN_FALSE;
9393 + }
9394 +
9395 + nice_header = pretty_key(estrndup(orig_header, header_len), header_len, 1, 1);
9396 + if ((header = http_message_header_ex(obj->message, nice_header, header_len + 1, 0))) {
9397 + RETVAL_ZVAL(header, 1, 1);
9398 + }
9399 + efree(nice_header);
9400 +}
9401 +/* }}} */
9402 +
9403 +/* {{{ proto array HttpMessage::getHeaders()
9404 + Get Message Headers. */
9405 +PHP_METHOD(HttpMessage, getHeaders)
9406 +{
9407 + NO_ARGS;
9408 +
9409 + if (return_value_used) {
9410 + getObject(http_message_object, obj);
9411 +
9412 + array_init(return_value);
9413 + array_copy(&obj->message->hdrs, Z_ARRVAL_P(return_value));
9414 + }
9415 +}
9416 +/* }}} */
9417 +
9418 +/* {{{ proto void HttpMessage::setHeaders(array headers)
9419 + Sets new headers. */
9420 +PHP_METHOD(HttpMessage, setHeaders)
9421 +{
9422 + zval *new_headers = NULL;
9423 + getObject(http_message_object, obj);
9424 +
9425 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &new_headers)) {
9426 + return;
9427 + }
9428 +
9429 + zend_hash_clean(&obj->message->hdrs);
9430 + if (new_headers) {
9431 + array_copy(Z_ARRVAL_P(new_headers), &obj->message->hdrs);
9432 + }
9433 +}
9434 +/* }}} */
9435 +
9436 +/* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
9437 + Add headers. If append is true, headers with the same name will be separated, else overwritten. */
9438 +PHP_METHOD(HttpMessage, addHeaders)
9439 +{
9440 + zval *new_headers;
9441 + zend_bool append = 0;
9442 + getObject(http_message_object, obj);
9443 +
9444 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
9445 + return;
9446 + }
9447 +
9448 + array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY);
9449 +}
9450 +/* }}} */
9451 +
9452 +/* {{{ proto int HttpMessage::getType()
9453 + Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
9454 +PHP_METHOD(HttpMessage, getType)
9455 +{
9456 + NO_ARGS;
9457 +
9458 + if (return_value_used) {
9459 + getObject(http_message_object, obj);
9460 + RETURN_LONG(obj->message->type);
9461 + }
9462 +}
9463 +/* }}} */
9464 +
9465 +/* {{{ proto void HttpMessage::setType(int type)
9466 + Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
9467 +PHP_METHOD(HttpMessage, setType)
9468 +{
9469 + long type;
9470 + getObject(http_message_object, obj);
9471 +
9472 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
9473 + return;
9474 + }
9475 + http_message_set_type(obj->message, type);
9476 +}
9477 +/* }}} */
9478 +
9479 +/* {{{ proto string HttpMessage::getInfo(void)
9480 + Get the HTTP request/response line */
9481 +PHP_METHOD(HttpMessage, getInfo)
9482 +{
9483 + NO_ARGS;
9484 +
9485 + if (return_value_used) {
9486 + getObject(http_message_object, obj);
9487 +
9488 + switch (obj->message->type) {
9489 + case HTTP_MSG_REQUEST:
9490 + Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_REQUEST_FMT_ARGS(&obj->message->http, ""));
9491 + break;
9492 + case HTTP_MSG_RESPONSE:
9493 + Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_RESPONSE_FMT_ARGS(&obj->message->http, ""));
9494 + break;
9495 + default:
9496 + RETURN_NULL();
9497 + break;
9498 + }
9499 + Z_TYPE_P(return_value) = IS_STRING;
9500 + }
9501 +}
9502 +/* }}} */
9503 +
9504 +/* {{{ proto bool HttpMessage::setInfo(string http_info)
9505 + Set type and request or response info with a standard HTTP request or response line */
9506 +PHP_METHOD(HttpMessage, setInfo)
9507 +{
9508 + char *str;
9509 + int len;
9510 + http_info inf;
9511 +
9512 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) && SUCCESS == http_info_parse_ex(str, &inf, 0)) {
9513 + getObject(http_message_object, obj);
9514 +
9515 + http_message_set_info(obj->message, &inf);
9516 + http_info_dtor(&inf);
9517 + RETURN_TRUE;
9518 + }
9519 + RETURN_FALSE;
9520 +}
9521 +/* }}} */
9522 +
9523 +/* {{{ proto int HttpMessage::getResponseCode()
9524 + Get the Response Code of the Message. */
9525 +PHP_METHOD(HttpMessage, getResponseCode)
9526 +{
9527 + NO_ARGS;
9528 +
9529 + if (return_value_used) {
9530 + getObject(http_message_object, obj);
9531 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9532 + RETURN_LONG(obj->message->http.info.response.code);
9533 + }
9534 +}
9535 +/* }}} */
9536 +
9537 +/* {{{ proto bool HttpMessage::setResponseCode(int code)
9538 + Set the response code of an HTTP Response Message. */
9539 +PHP_METHOD(HttpMessage, setResponseCode)
9540 +{
9541 + long code;
9542 + getObject(http_message_object, obj);
9543 +
9544 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9545 +
9546 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
9547 + RETURN_FALSE;
9548 + }
9549 + if (code < 100 || code > 599) {
9550 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid response code (100-599): %ld", code);
9551 + RETURN_FALSE;
9552 + }
9553 +
9554 + obj->message->http.info.response.code = code;
9555 + RETURN_TRUE;
9556 +}
9557 +/* }}} */
9558 +
9559 +/* {{{ proto string HttpMessage::getResponseStatus()
9560 + Get the Response Status of the message (i.e. the string following the response code). */
9561 +PHP_METHOD(HttpMessage, getResponseStatus)
9562 +{
9563 + NO_ARGS;
9564 +
9565 + if (return_value_used) {
9566 + getObject(http_message_object, obj);
9567 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9568 + if (obj->message->http.info.response.status) {
9569 + RETURN_STRING(obj->message->http.info.response.status, 1);
9570 + } else {
9571 + RETURN_EMPTY_STRING();
9572 + }
9573 + }
9574 +}
9575 +/* }}} */
9576 +
9577 +/* {{{ proto bool HttpMessage::setResponseStatus(string status)
9578 + Set the Response Status of the HTTP message (i.e. the string following the response code). */
9579 +PHP_METHOD(HttpMessage, setResponseStatus)
9580 +{
9581 + char *status;
9582 + int status_len;
9583 + getObject(http_message_object, obj);
9584 +
9585 + HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
9586 +
9587 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &status, &status_len)) {
9588 + RETURN_FALSE;
9589 + }
9590 + STR_SET(obj->message->http.info.response.status, estrndup(status, status_len));
9591 + RETURN_TRUE;
9592 +}
9593 +/* }}} */
9594 +
9595 +/* {{{ proto string HttpMessage::getRequestMethod()
9596 + Get the Request Method of the Message. */
9597 +PHP_METHOD(HttpMessage, getRequestMethod)
9598 +{
9599 + NO_ARGS;
9600 +
9601 + if (return_value_used) {
9602 + getObject(http_message_object, obj);
9603 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9604 + if (obj->message->http.info.request.method) {
9605 + RETURN_STRING(obj->message->http.info.request.method, 1);
9606 + } else {
9607 + RETURN_EMPTY_STRING();
9608 + }
9609 + }
9610 +}
9611 +/* }}} */
9612 +
9613 +/* {{{ proto bool HttpMessage::setRequestMethod(string method)
9614 + Set the Request Method of the HTTP Message. */
9615 +PHP_METHOD(HttpMessage, setRequestMethod)
9616 +{
9617 + char *method;
9618 + int method_len;
9619 + getObject(http_message_object, obj);
9620 +
9621 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9622 +
9623 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
9624 + RETURN_FALSE;
9625 + }
9626 + if (method_len < 1) {
9627 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
9628 + RETURN_FALSE;
9629 + }
9630 + if (!http_request_method_exists(1, 0, method)) {
9631 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unknown request method: %s", method);
9632 + RETURN_FALSE;
9633 + }
9634 +
9635 + STR_SET(obj->message->http.info.request.method, estrndup(method, method_len));
9636 + RETURN_TRUE;
9637 +}
9638 +/* }}} */
9639 +
9640 +/* {{{ proto string HttpMessage::getRequestUrl()
9641 + Get the Request URL of the Message. */
9642 +PHP_METHOD(HttpMessage, getRequestUrl)
9643 +{
9644 + NO_ARGS;
9645 +
9646 + if (return_value_used) {
9647 + getObject(http_message_object, obj);
9648 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9649 + if (obj->message->http.info.request.url) {
9650 + RETURN_STRING(obj->message->http.info.request.url, 1);
9651 + } else {
9652 + RETURN_EMPTY_STRING();
9653 + }
9654 + }
9655 +}
9656 +/* }}} */
9657 +
9658 +/* {{{ proto bool HttpMessage::setRequestUrl(string url)
9659 + Set the Request URL of the HTTP Message. */
9660 +PHP_METHOD(HttpMessage, setRequestUrl)
9661 +{
9662 + char *URI;
9663 + int URIlen;
9664 + getObject(http_message_object, obj);
9665 +
9666 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) {
9667 + RETURN_FALSE;
9668 + }
9669 + HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
9670 + if (URIlen < 1) {
9671 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestUrl to an empty string");
9672 + RETURN_FALSE;
9673 + }
9674 +
9675 + STR_SET(obj->message->http.info.request.url, estrndup(URI, URIlen));
9676 + RETURN_TRUE;
9677 +}
9678 +/* }}} */
9679 +
9680 +/* {{{ proto string HttpMessage::getHttpVersion()
9681 + Get the HTTP Protocol Version of the Message. */
9682 +PHP_METHOD(HttpMessage, getHttpVersion)
9683 +{
9684 + NO_ARGS;
9685 +
9686 + if (return_value_used) {
9687 + char *version;
9688 + getObject(http_message_object, obj);
9689 +
9690 + spprintf(&version, 0, "%1.1F", obj->message->http.version);
9691 + RETURN_STRING(version, 0);
9692 + }
9693 +}
9694 +/* }}} */
9695 +
9696 +/* {{{ proto bool HttpMessage::setHttpVersion(string version)
9697 + Set the HTTP Protocol version of the Message. */
9698 +PHP_METHOD(HttpMessage, setHttpVersion)
9699 +{
9700 + zval *zv;
9701 + char *version;
9702 + getObject(http_message_object, obj);
9703 +
9704 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) {
9705 + return;
9706 + }
9707 +
9708 + convert_to_double(zv);
9709 + spprintf(&version, 0, "%1.1F", Z_DVAL_P(zv));
9710 + if (strcmp(version, "1.0") && strcmp(version, "1.1")) {
9711 + efree(version);
9712 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %g", Z_DVAL_P(zv));
9713 + RETURN_FALSE;
9714 + }
9715 + efree(version);
9716 + obj->message->http.version = Z_DVAL_P(zv);
9717 + RETURN_TRUE;
9718 +}
9719 +/* }}} */
9720 +
9721 +/* {{{ proto string HttpMessage::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
9722 + Attempts to guess the content type of supplied payload through libmagic. */
9723 +PHP_METHOD(HttpMessage, guessContentType)
9724 +{
9725 +#ifdef HTTP_HAVE_MAGIC
9726 + char *magic_file, *ct = NULL;
9727 + int magic_file_len;
9728 + long magic_mode = MAGIC_MIME;
9729 +
9730 + RETVAL_FALSE;
9731 + SET_EH_THROW_HTTP();
9732 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
9733 + getObject(http_message_object, obj);
9734 + if ((ct = http_guess_content_type(magic_file, magic_mode, PHPSTR_VAL(&obj->message->body), PHPSTR_LEN(&obj->message->body), SEND_DATA))) {
9735 + RETVAL_STRING(ct, 0);
9736 + }
9737 + }
9738 + SET_EH_NORMAL();
9739 +#else
9740 + http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
9741 + RETURN_FALSE;
9742 +#endif
9743 +}
9744 +/* }}} */
9745 +
9746 +/* {{{ proto HttpMessage HttpMessage::getParentMessage()
9747 + Get parent Message. */
9748 +PHP_METHOD(HttpMessage, getParentMessage)
9749 +{
9750 + SET_EH_THROW_HTTP();
9751 + NO_ARGS {
9752 + getObject(http_message_object, obj);
9753 +
9754 + if (obj->message->parent) {
9755 + RETVAL_OBJVAL(obj->parent, 1);
9756 + } else {
9757 + http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpMessage does not have a parent message");
9758 + }
9759 + }
9760 + SET_EH_NORMAL();
9761 +}
9762 +/* }}} */
9763 +
9764 +/* {{{ proto bool HttpMessage::send()
9765 + Send the Message according to its type as Response or Request. */
9766 +PHP_METHOD(HttpMessage, send)
9767 +{
9768 + getObject(http_message_object, obj);
9769 +
9770 + NO_ARGS;
9771 +
9772 + RETURN_SUCCESS(http_message_send(obj->message));
9773 +}
9774 +/* }}} */
9775 +
9776 +/* {{{ proto string HttpMessage::toString([bool include_parent = false])
9777 + Get the string representation of the Message. */
9778 +PHP_METHOD(HttpMessage, toString)
9779 +{
9780 + if (return_value_used) {
9781 + char *string;
9782 + size_t length;
9783 + zend_bool include_parent = 0;
9784 + getObject(http_message_object, obj);
9785 +
9786 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
9787 + RETURN_FALSE;
9788 + }
9789 +
9790 + if (include_parent) {
9791 + http_message_serialize(obj->message, &string, &length);
9792 + } else {
9793 + http_message_tostring(obj->message, &string, &length);
9794 + }
9795 + RETURN_STRINGL(string, length, 0);
9796 + }
9797 +}
9798 +/* }}} */
9799 +
9800 +/* {{{ proto HttpRequest|HttpResponse HttpMessage::toMessageTypeObject(void)
9801 + Creates an object regarding to the type of the message. Returns either an HttpRequest or HttpResponse object on success, or NULL on failure. */
9802 +PHP_METHOD(HttpMessage, toMessageTypeObject)
9803 +{
9804 + SET_EH_THROW_HTTP();
9805 +
9806 + NO_ARGS;
9807 +
9808 + if (return_value_used) {
9809 + getObject(http_message_object, obj);
9810 +
9811 + switch (obj->message->type) {
9812 + case HTTP_MSG_REQUEST:
9813 + {
9814 +#ifdef HTTP_HAVE_CURL
9815 + int method;
9816 + char *url;
9817 + zval post, body, *array, *headers, *host = http_message_header(obj->message, "Host");
9818 + php_url hurl, *purl = php_url_parse(STR_PTR(obj->message->http.info.request.url));
9819 +
9820 + MAKE_STD_ZVAL(array);
9821 + array_init(array);
9822 +
9823 + memset(&hurl, 0, sizeof(php_url));
9824 + if (host) {
9825 + hurl.host = Z_STRVAL_P(host);
9826 + zval_ptr_dtor(&host);
9827 + }
9828 + http_build_url(HTTP_URL_REPLACE, purl, &hurl, NULL, &url, NULL);
9829 + php_url_free(purl);
9830 + add_assoc_string(array, "url", url, 0);
9831 +
9832 + if ( obj->message->http.info.request.method &&
9833 + ((method = http_request_method_exists(1, 0, obj->message->http.info.request.method)) ||
9834 + (method = http_request_method_register(obj->message->http.info.request.method, strlen(obj->message->http.info.request.method))))) {
9835 + add_assoc_long(array, "method", method);
9836 + }
9837 +
9838 + if (10 == (int) (obj->message->http.version * 10)) {
9839 + add_assoc_long(array, "protocol", CURL_HTTP_VERSION_1_0);
9840 + }
9841 +
9842 + MAKE_STD_ZVAL(headers);
9843 + array_init(headers);
9844 + array_copy(&obj->message->hdrs, Z_ARRVAL_P(headers));
9845 + add_assoc_zval(array, "headers", headers);
9846 +
9847 + object_init_ex(return_value, http_request_object_ce);
9848 + zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setoptions", NULL, array);
9849 + zval_ptr_dtor(&array);
9850 +
9851 + if (PHPSTR_VAL(obj->message) && PHPSTR_LEN(obj->message)) {
9852 + phpstr_fix(PHPSTR(obj->message));
9853 + INIT_PZVAL(&body);
9854 + ZVAL_STRINGL(&body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 0);
9855 + if (method != HTTP_POST) {
9856 + zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setbody", NULL, &body);
9857 + } else {
9858 + INIT_PZVAL(&post);
9859 + array_init(&post);
9860 +
9861 + zval_copy_ctor(&body);
9862 + sapi_module.treat_data(PARSE_STRING, Z_STRVAL(body), &post TSRMLS_CC);
9863 + zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setpostfields", NULL, &post);
9864 + zval_dtor(&post);
9865 + }
9866 + }
9867 +#else
9868 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpRequest (missing curl support)");
9869 +#endif
9870 + break;
9871 + }
9872 +
9873 + case HTTP_MSG_RESPONSE:
9874 + {
9875 +#ifndef WONKY
9876 + HashPosition pos1, pos2;
9877 + HashKey key = initHashKey(0);
9878 + zval **header, **h, *body;
9879 +
9880 + if (obj->message->http.info.response.code) {
9881 + http_send_status(obj->message->http.info.response.code);
9882 + }
9883 +
9884 + object_init_ex(return_value, http_response_object_ce);
9885 +
9886 + FOREACH_HASH_KEYVAL(pos1, &obj->message->hdrs, key, header) {
9887 + if (key.type == HASH_KEY_IS_STRING) {
9888 + zval *zkey;
9889 +
9890 + MAKE_STD_ZVAL(zkey);
9891 + ZVAL_STRINGL(zkey, key.str, key.len - 1, 1);
9892 +
9893 + switch (Z_TYPE_PP(header)) {
9894 + case IS_ARRAY:
9895 + case IS_OBJECT:
9896 + FOREACH_HASH_VAL(pos2, HASH_OF(*header), h) {
9897 + ZVAL_ADDREF(*h);
9898 + zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *h);
9899 + zval_ptr_dtor(h);
9900 + }
9901 + break;
9902 +
9903 + default:
9904 + ZVAL_ADDREF(*header);
9905 + zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *header);
9906 + zval_ptr_dtor(header);
9907 + break;
9908 + }
9909 + zval_ptr_dtor(&zkey);
9910 + }
9911 + }
9912 +
9913 + MAKE_STD_ZVAL(body);
9914 + ZVAL_STRINGL(body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 1);
9915 + zend_call_method_with_1_params(&return_value, http_response_object_ce, NULL, "setdata", NULL, body);
9916 + zval_ptr_dtor(&body);
9917 +#else
9918 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpResponse (need PHP 5.1+)");
9919 +#endif
9920 + break;
9921 + }
9922 +
9923 + default:
9924 + http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HttpMessage::TYPE_REQUEST nor HttpMessage::TYPE_RESPONSE");
9925 + break;
9926 + }
9927 + }
9928 + SET_EH_NORMAL();
9929 +}
9930 +/* }}} */
9931 +
9932 +/* {{{ proto int HttpMessage::count()
9933 + Implements Countable::count(). Returns the number of parent messages + 1. */
9934 +PHP_METHOD(HttpMessage, count)
9935 +{
9936 + NO_ARGS {
9937 + long i;
9938 + getObject(http_message_object, obj);
9939 +
9940 + http_message_count(i, obj->message);
9941 + RETURN_LONG(i);
9942 + }
9943 +}
9944 +/* }}} */
9945 +
9946 +/* {{{ proto string HttpMessage::serialize()
9947 + Implements Serializable::serialize(). Returns the serialized representation of the HttpMessage. */
9948 +PHP_METHOD(HttpMessage, serialize)
9949 +{
9950 + NO_ARGS {
9951 + char *string;
9952 + size_t length;
9953 + getObject(http_message_object, obj);
9954 +
9955 + http_message_serialize(obj->message, &string, &length);
9956 + RETURN_STRINGL(string, length, 0);
9957 + }
9958 +}
9959 +/* }}} */
9960 +
9961 +/* {{{ proto void HttpMessage::unserialize(string serialized)
9962 + Implements Serializable::unserialize(). Re-constructs the HttpMessage based upon the serialized string. */
9963 +PHP_METHOD(HttpMessage, unserialize)
9964 +{
9965 + int length;
9966 + char *serialized;
9967 + getObject(http_message_object, obj);
9968 +
9969 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &length)) {
9970 + http_message *msg;
9971 +
9972 + http_message_dtor(obj->message);
9973 + if ((msg = http_message_parse_ex(obj->message, serialized, (size_t) length))) {
9974 + obj->message = msg;
9975 + } else {
9976 + http_message_init(obj->message);
9977 + http_error(HE_ERROR, HTTP_E_RUNTIME, "Could not unserialize HttpMessage");
9978 + }
9979 + }
9980 +}
9981 +/* }}} */
9982 +
9983 +/* {{{ proto HttpMessage HttpMessage::detach(void)
9984 + Returns a clone of an HttpMessage object detached from any parent messages. */
9985 +PHP_METHOD(HttpMessage, detach)
9986 +{
9987 + http_info info;
9988 + http_message *msg;
9989 + getObject(http_message_object, obj);
9990 +
9991 + NO_ARGS;
9992 +
9993 + info.type = obj->message->type;
9994 + memcpy(&HTTP_INFO(&info), &HTTP_INFO(obj->message), sizeof(struct http_info));
9995 +
9996 + msg = http_message_new();
9997 + http_message_set_info(msg, &info);
9998 +
9999 + zend_hash_copy(&msg->hdrs, &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
10000 + phpstr_append(&msg->body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message));
10001 +
10002 + RETVAL_OBJVAL(http_message_object_new_ex(Z_OBJCE_P(getThis()), msg, NULL), 0);
10003 +}
10004 +/* }}} */
10005 +
10006 +/* {{{ proto void HttpMessage::prepend(HttpMessage message[, bool top = true])
10007 + Prepends message(s) to the HTTP message. Throws HttpInvalidParamException if the message is located within the same message chain. */
10008 +PHP_METHOD(HttpMessage, prepend)
10009 +{
10010 + zval *prepend;
10011 + zend_bool top = 1;
10012 +
10013 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, http_message_object_ce, &top)) {
10014 + http_message *msg[2];
10015 + getObject(http_message_object, obj);
10016 + getObjectEx(http_message_object, prepend_obj, prepend);
10017 +
10018 + /* safety check */
10019 + for (msg[0] = obj->message; msg[0]; msg[0] = msg[0]->parent) {
10020 + for (msg[1] = prepend_obj->message; msg[1]; msg[1] = msg[1]->parent) {
10021 + if (msg[0] == msg[1]) {
10022 + http_error(HE_THROW, HTTP_E_INVALID_PARAM, "Cannot prepend a message located within the same message chain");
10023 + return;
10024 + }
10025 + }
10026 + }
10027 +
10028 + http_message_object_prepend_ex(getThis(), prepend, top);
10029 + }
10030 +}
10031 +/* }}} */
10032 +
10033 +/* {{{ proto HttpMessage HttpMessage::reverse()
10034 + Reorders the message chain in reverse order. Returns the most parent HttpMessage object. */
10035 +PHP_METHOD(HttpMessage, reverse)
10036 +{
10037 + NO_ARGS {
10038 + http_message_object_reverse(getThis(), return_value);
10039 + }
10040 +}
10041 +/* }}} */
10042 +
10043 +/* {{{ proto void HttpMessage::rewind(void)
10044 + Implements Iterator::rewind(). */
10045 +PHP_METHOD(HttpMessage, rewind)
10046 +{
10047 + NO_ARGS {
10048 + getObject(http_message_object, obj);
10049 +
10050 + if (obj->iterator) {
10051 + zval_ptr_dtor(&obj->iterator);
10052 + }
10053 + ZVAL_ADDREF(getThis());
10054 + obj->iterator = getThis();
10055 + }
10056 +}
10057 +/* }}} */
10058 +
10059 +/* {{{ proto bool HttpMessage::valid(void)
10060 + Implements Iterator::valid(). */
10061 +PHP_METHOD(HttpMessage, valid)
10062 +{
10063 + NO_ARGS {
10064 + getObject(http_message_object, obj);
10065 +
10066 + RETURN_BOOL(obj->iterator != NULL);
10067 + }
10068 +}
10069 +/* }}} */
10070 +
10071 +/* {{{ proto void HttpMessage::next(void)
10072 + Implements Iterator::next(). */
10073 +PHP_METHOD(HttpMessage, next)
10074 +{
10075 + NO_ARGS {
10076 + getObject(http_message_object, obj);
10077 + if (obj->iterator) {
10078 + getObjectEx(http_message_object, itr, obj->iterator);
10079 +
10080 + if (itr && itr->parent.handle) {
10081 + zval *old = obj->iterator;
10082 + MAKE_STD_ZVAL(obj->iterator);
10083 + ZVAL_OBJVAL(obj->iterator, itr->parent, 1);
10084 + zval_ptr_dtor(&old);
10085 + } else {
10086 + zval_ptr_dtor(&obj->iterator);
10087 + obj->iterator = NULL;
10088 + }
10089 + }
10090 + }
10091 +}
10092 +/* }}} */
10093 +
10094 +/* {{{ proto int HttpMessage::key(void)
10095 + Implements Iterator::key(). */
10096 +PHP_METHOD(HttpMessage, key)
10097 +{
10098 + NO_ARGS {
10099 + getObject(http_message_object, obj);
10100 +
10101 + RETURN_LONG(obj->iterator ? obj->iterator->value.obj.handle:0);
10102 + }
10103 +}
10104 +/* }}} */
10105 +
10106 +/* {{{ proto HttpMessage HttpMessage::current(void)
10107 + Implements Iterator::current(). */
10108 +PHP_METHOD(HttpMessage, current)
10109 +{
10110 + NO_ARGS {
10111 + getObject(http_message_object, obj);
10112 +
10113 + if (obj->iterator) {
10114 + RETURN_ZVAL(obj->iterator, 1, 0);
10115 + }
10116 + }
10117 +}
10118 +/* }}} */
10119 +
10120 +#endif /* ZEND_ENGINE_2 */
10121 +
10122 +/*
10123 + * Local variables:
10124 + * tab-width: 4
10125 + * c-basic-offset: 4
10126 + * End:
10127 + * vim600: noet sw=4 ts=4 fdm=marker
10128 + * vim<600: noet sw=4 ts=4
10129 + */
10130 +
10131 --- /dev/null
10132 +++ b/ext/http/http_persistent_handle_api.c
10133 @@ -0,0 +1,388 @@
10134 +/*
10135 + +--------------------------------------------------------------------+
10136 + | PECL :: http |
10137 + +--------------------------------------------------------------------+
10138 + | Redistribution and use in source and binary forms, with or without |
10139 + | modification, are permitted provided that the conditions mentioned |
10140 + | in the accompanying LICENSE file are met. |
10141 + +--------------------------------------------------------------------+
10142 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10143 + +--------------------------------------------------------------------+
10144 +*/
10145 +
10146 +/* $Id: http_persistent_handle_api.c 292841 2009-12-31 08:48:57Z mike $ */
10147 +
10148 +#include "php_http.h"
10149 +#include "php_http_api.h"
10150 +
10151 +#include "php_http_persistent_handle_api.h"
10152 +
10153 +#ifndef HTTP_DEBUG_PHANDLES
10154 +# define HTTP_DEBUG_PHANDLES 0
10155 +#endif
10156 +#if HTTP_DEBUG_PHANDLES
10157 +# undef inline
10158 +# define inline
10159 +#endif
10160 +
10161 +static HashTable http_persistent_handles_hash;
10162 +#ifdef ZTS
10163 +# define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
10164 +# define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
10165 +static MUTEX_T http_persistent_handles_lock;
10166 +#else
10167 +# define LOCK()
10168 +# define UNLOCK()
10169 +#endif
10170 +
10171 +typedef struct _http_persistent_handle_list_t {
10172 + HashTable free;
10173 + ulong used;
10174 +} http_persistent_handle_list;
10175 +
10176 +typedef struct _http_persistent_handle_provider_t {
10177 + http_persistent_handle_list list; /* "ident" => array(handles) entries */
10178 + http_persistent_handle_ctor ctor;
10179 + http_persistent_handle_dtor dtor;
10180 + http_persistent_handle_copy copy;
10181 +} http_persistent_handle_provider;
10182 +
10183 +static inline http_persistent_handle_list *http_persistent_handle_list_init(http_persistent_handle_list *list)
10184 +{
10185 + int free_list;
10186 +
10187 + if ((free_list = !list)) {
10188 + list = pemalloc(sizeof(http_persistent_handle_list), 1);
10189 + }
10190 +
10191 + list->used = 0;
10192 +
10193 + if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) {
10194 + if (free_list) {
10195 + pefree(list, 1);
10196 + }
10197 + list = NULL;
10198 + }
10199 +
10200 + return list;
10201 +}
10202 +
10203 +static inline void http_persistent_handle_list_dtor(http_persistent_handle_list *list, http_persistent_handle_dtor dtor)
10204 +{
10205 + HashPosition pos;
10206 + void **handle;
10207 +
10208 +#if HTTP_DEBUG_PHANDLES
10209 + fprintf(stderr, "LSTDTOR: %p\n", list);
10210 +#endif
10211 + FOREACH_HASH_VAL(pos, &list->free, handle) {
10212 +#if HTTP_DEBUG_PHANDLES
10213 + fprintf(stderr, "DESTROY: %p\n", *handle);
10214 +#endif
10215 +
10216 + dtor(*handle);
10217 + }
10218 + zend_hash_destroy(&list->free);
10219 +}
10220 +
10221 +static inline void http_persistent_handle_list_free(http_persistent_handle_list **list, http_persistent_handle_dtor dtor)
10222 +{
10223 + http_persistent_handle_list_dtor(*list, dtor);
10224 +#if HTTP_DEBUG_PHANDLES
10225 + fprintf(stderr, "LSTFREE: %p\n", *list);
10226 +#endif
10227 + pefree(*list, 1);
10228 + *list = NULL;
10229 +}
10230 +
10231 +static inline http_persistent_handle_list *http_persistent_handle_list_find(http_persistent_handle_provider *provider TSRMLS_DC)
10232 +{
10233 + http_persistent_handle_list **list, *new_list;
10234 +
10235 + 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)) {
10236 +#if HTTP_DEBUG_PHANDLES
10237 + fprintf(stderr, "LSTFIND: %p\n", *list);
10238 +#endif
10239 + return *list;
10240 + }
10241 +
10242 + if ((new_list = http_persistent_handle_list_init(NULL))) {
10243 + 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)) {
10244 +#if HTTP_DEBUG_PHANDLES
10245 + fprintf(stderr, "LSTFIND: %p (new)\n", *list);
10246 +#endif
10247 + return *list;
10248 + }
10249 + http_persistent_handle_list_free(&new_list, provider->dtor);
10250 + }
10251 +
10252 + return NULL;
10253 +}
10254 +
10255 +static inline STATUS http_persistent_handle_do_acquire(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)
10256 +{
10257 + ulong index;
10258 + void **handle_ptr;
10259 + http_persistent_handle_list *list;
10260 +
10261 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10262 + zend_hash_internal_pointer_end(&list->free);
10263 + 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)) {
10264 + *handle = *handle_ptr;
10265 + zend_hash_index_del(&list->free, index);
10266 + } else {
10267 + *handle = provider->ctor();
10268 + }
10269 +
10270 + if (*handle) {
10271 + ++provider->list.used;
10272 + ++list->used;
10273 + return SUCCESS;
10274 + }
10275 + } else {
10276 + *handle = NULL;
10277 + }
10278 +
10279 + return FAILURE;
10280 +}
10281 +
10282 +static inline STATUS http_persistent_handle_do_release(http_persistent_handle_provider *provider, void **handle TSRMLS_DC)
10283 +{
10284 + http_persistent_handle_list *list;
10285 +
10286 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10287 + if (provider->list.used >= HTTP_G->persistent.handles.limit) {
10288 + provider->dtor(*handle);
10289 + } else {
10290 + if (SUCCESS != zend_hash_next_index_insert(&list->free, (void *) handle, sizeof(void *), NULL)) {
10291 + return FAILURE;
10292 + }
10293 + }
10294 +
10295 + *handle = NULL;
10296 + --provider->list.used;
10297 + --list->used;
10298 + return SUCCESS;
10299 + }
10300 +
10301 + return FAILURE;
10302 +}
10303 +
10304 +static inline STATUS http_persistent_handle_do_accrete(http_persistent_handle_provider *provider, void *old_handle, void **new_handle TSRMLS_DC)
10305 +{
10306 + http_persistent_handle_list *list;
10307 +
10308 + if (provider->copy && (*new_handle = provider->copy(old_handle))) {
10309 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10310 + ++list->used;
10311 + }
10312 + ++provider->list.used;
10313 + return SUCCESS;
10314 + }
10315 + return FAILURE;
10316 +}
10317 +
10318 +static void http_persistent_handles_hash_dtor(void *p)
10319 +{
10320 + http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p;
10321 + http_persistent_handle_list **list, *list_tmp;
10322 + HashPosition pos;
10323 +
10324 + FOREACH_HASH_VAL(pos, &provider->list.free, list) {
10325 + /* fix shutdown crash in PHP4 */
10326 + list_tmp = *list;
10327 + http_persistent_handle_list_free(&list_tmp, provider->dtor);
10328 + }
10329 +
10330 + zend_hash_destroy(&provider->list.free);
10331 +}
10332 +
10333 +PHP_MINIT_FUNCTION(http_persistent_handle)
10334 +{
10335 + zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1);
10336 +#ifdef ZTS
10337 + http_persistent_handles_lock = tsrm_mutex_alloc();
10338 +#endif
10339 + return SUCCESS;
10340 +}
10341 +
10342 +PHP_MSHUTDOWN_FUNCTION(http_persistent_handle)
10343 +{
10344 + zend_hash_destroy(&http_persistent_handles_hash);
10345 +#ifdef ZTS
10346 + tsrm_mutex_free(http_persistent_handles_lock);
10347 +#endif
10348 + return SUCCESS;
10349 +}
10350 +
10351 +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)
10352 +{
10353 + STATUS status = FAILURE;
10354 + http_persistent_handle_provider provider;
10355 +
10356 + LOCK();
10357 + if (http_persistent_handle_list_init(&provider.list)) {
10358 + provider.ctor = ctor;
10359 + provider.dtor = dtor;
10360 + provider.copy = copy;
10361 +
10362 +#if HTTP_DEBUG_PHANDLES
10363 + fprintf(stderr, "PROVIDE: %s\n", name_str);
10364 +#endif
10365 +
10366 + 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)) {
10367 + status = SUCCESS;
10368 + }
10369 + }
10370 + UNLOCK();
10371 +
10372 + return status;
10373 +}
10374 +
10375 +PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC)
10376 +{
10377 + STATUS status = FAILURE;
10378 + http_persistent_handle_provider *provider;
10379 +
10380 + *handle = NULL;
10381 + LOCK();
10382 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10383 + status = http_persistent_handle_do_acquire(provider, handle TSRMLS_CC);
10384 + }
10385 + UNLOCK();
10386 +
10387 +#if HTTP_DEBUG_PHANDLES
10388 + fprintf(stderr, "ACQUIRE: %p (%s)\n", *handle, name_str);
10389 +#endif
10390 +
10391 + return status;
10392 +}
10393 +
10394 +PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC)
10395 +{
10396 + STATUS status = FAILURE;
10397 + http_persistent_handle_provider *provider;
10398 +#if HTTP_DEBUG_PHANDLES
10399 + void *handle_tmp = *handle;
10400 +#endif
10401 +
10402 + LOCK();
10403 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10404 + status = http_persistent_handle_do_release(provider, handle TSRMLS_CC);
10405 + }
10406 + UNLOCK();
10407 +
10408 +#if HTTP_DEBUG_PHANDLES
10409 + fprintf(stderr, "RELEASE: %p (%s)\n", handle_tmp, name_str);
10410 +#endif
10411 +
10412 + return status;
10413 +}
10414 +
10415 +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)
10416 +{
10417 + STATUS status = FAILURE;
10418 + http_persistent_handle_provider *provider;
10419 +
10420 + *new_handle = NULL;
10421 + LOCK();
10422 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10423 + status = http_persistent_handle_do_accrete(provider, old_handle, new_handle TSRMLS_CC);
10424 + }
10425 + UNLOCK();
10426 +
10427 +#if HTTP_DEBUG_PHANDLES
10428 + fprintf(stderr, "ACCRETE: %p > %p (%s)\n", old_handle, *new_handle, name_str);
10429 +#endif
10430 +
10431 + return status;
10432 +}
10433 +
10434 +PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC)
10435 +{
10436 + http_persistent_handle_provider *provider;
10437 + http_persistent_handle_list *list, **listp;
10438 + HashPosition pos1, pos2;
10439 +
10440 + LOCK();
10441 + if (name_str && name_len) {
10442 + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) {
10443 + if (current_ident_only) {
10444 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10445 + http_persistent_handle_list_dtor(list, provider->dtor);
10446 + http_persistent_handle_list_init(list);
10447 + }
10448 + } else {
10449 + FOREACH_HASH_VAL(pos1, &provider->list.free, listp) {
10450 + http_persistent_handle_list_dtor(*listp, provider->dtor);
10451 + http_persistent_handle_list_init(*listp);
10452 + }
10453 + }
10454 + }
10455 + } else {
10456 + FOREACH_HASH_VAL(pos1, &http_persistent_handles_hash, provider) {
10457 + if (current_ident_only) {
10458 + if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) {
10459 + http_persistent_handle_list_dtor(list, provider->dtor);
10460 + http_persistent_handle_list_init(list);
10461 + }
10462 + } else {
10463 + FOREACH_HASH_VAL(pos2, &provider->list.free, listp) {
10464 + http_persistent_handle_list_dtor(*listp, provider->dtor);
10465 + http_persistent_handle_list_init(*listp);
10466 + }
10467 + }
10468 + }
10469 + }
10470 + UNLOCK();
10471 +}
10472 +
10473 +PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC)
10474 +{
10475 + zval *zentry[2];
10476 + HashPosition pos1, pos2;
10477 + HashKey key1 = initHashKey(0), key2 = initHashKey(0);
10478 + http_persistent_handle_provider *provider;
10479 + http_persistent_handle_list **list;
10480 +
10481 + LOCK();
10482 + if (zend_hash_num_elements(&http_persistent_handles_hash)) {
10483 + if (!ht) {
10484 + ALLOC_HASHTABLE(ht);
10485 + zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
10486 + }
10487 +
10488 + FOREACH_HASH_KEYVAL(pos1, &http_persistent_handles_hash, key1, provider) {
10489 + MAKE_STD_ZVAL(zentry[0]);
10490 + array_init(zentry[0]);
10491 +
10492 + FOREACH_HASH_KEYVAL(pos2, &provider->list.free, key2, list) {
10493 + MAKE_STD_ZVAL(zentry[1]);
10494 + array_init(zentry[1]);
10495 + add_assoc_long_ex(zentry[1], ZEND_STRS("used"), (*list)->used);
10496 + add_assoc_long_ex(zentry[1], ZEND_STRS("free"), zend_hash_num_elements(&(*list)->free));
10497 +
10498 + /* use zend_hash_* not add_assoc_* (which is zend_symtable_*) as we want a string even for numbers */
10499 + zend_hash_add(Z_ARRVAL_P(zentry[0]), key2.str, key2.len, &zentry[1], sizeof(zval *), NULL);
10500 + }
10501 +
10502 + zend_hash_add(ht, key1.str, key1.len, &zentry[0], sizeof(zval *), NULL);
10503 + }
10504 + } else if (ht) {
10505 + ht = NULL;
10506 + }
10507 + UNLOCK();
10508 +
10509 + return ht;
10510 +}
10511 +
10512 +
10513 +/*
10514 + * Local variables:
10515 + * tab-width: 4
10516 + * c-basic-offset: 4
10517 + * End:
10518 + * vim600: noet sw=4 ts=4 fdm=marker
10519 + * vim<600: noet sw=4 ts=4
10520 + */
10521 +
10522 --- /dev/null
10523 +++ b/ext/http/http_querystring_api.c
10524 @@ -0,0 +1,220 @@
10525 +/*
10526 + +--------------------------------------------------------------------+
10527 + | PECL :: http |
10528 + +--------------------------------------------------------------------+
10529 + | Redistribution and use in source and binary forms, with or without |
10530 + | modification, are permitted provided that the conditions mentioned |
10531 + | in the accompanying LICENSE file are met. |
10532 + +--------------------------------------------------------------------+
10533 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10534 + +--------------------------------------------------------------------+
10535 +*/
10536 +
10537 +/* $Id: http_querystring_api.c 292841 2009-12-31 08:48:57Z mike $ */
10538 +
10539 +#define HTTP_WANT_SAPI
10540 +#include "php_http.h"
10541 +
10542 +#include "php_variables.h"
10543 +#ifdef HTTP_HAVE_ICONV
10544 +# undef PHP_ATOM_INC
10545 +# include "ext/iconv/php_iconv.h"
10546 +# include "ext/standard/url.h"
10547 +#endif
10548 +
10549 +#include "php_http_api.h"
10550 +#include "php_http_url_api.h"
10551 +#include "php_http_querystring_api.h"
10552 +
10553 +#ifdef ZEND_ENGINE_2
10554 +#define THIS_CE http_querystring_object_ce
10555 +extern zend_class_entry *http_querystring_object_ce;
10556 +#endif
10557 +
10558 +
10559 +#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)
10560 +static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC);
10561 +#define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC)
10562 +static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC);
10563 +
10564 +
10565 +#ifdef HTTP_HAVE_ICONV
10566 +PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC)
10567 +{
10568 + HashPosition pos;
10569 + zval **entry = NULL;
10570 + char *xlate_str = NULL, *xkey;
10571 + size_t xlate_len = 0, xlen;
10572 + HashKey key = initHashKey(0);
10573 +
10574 + FOREACH_KEYVAL(pos, param, key, entry) {
10575 + if (key.type == HASH_KEY_IS_STRING) {
10576 + if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.str, key.len-1, &xkey, &xlen, oe, ie)) {
10577 + http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe);
10578 + return FAILURE;
10579 + }
10580 + }
10581 +
10582 + if (Z_TYPE_PP(entry) == IS_STRING) {
10583 + if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) {
10584 + if (key.type == HASH_KEY_IS_STRING) {
10585 + efree(xkey);
10586 + }
10587 + 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);
10588 + return FAILURE;
10589 + }
10590 + if (key.type == HASH_KEY_IS_STRING) {
10591 + add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0);
10592 + } else {
10593 + add_index_stringl(array, key.num, xlate_str, xlate_len, 0);
10594 + }
10595 + } else if (Z_TYPE_PP(entry) == IS_ARRAY) {
10596 + zval *subarray;
10597 +
10598 + MAKE_STD_ZVAL(subarray);
10599 + array_init(subarray);
10600 + if (key.type == HASH_KEY_IS_STRING) {
10601 + add_assoc_zval_ex(array, xkey, xlen+1, subarray);
10602 + } else {
10603 + add_index_zval(array, key.num, subarray);
10604 + }
10605 + if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) {
10606 + if (key.type == HASH_KEY_IS_STRING) {
10607 + efree(xkey);
10608 + }
10609 + return FAILURE;
10610 + }
10611 + }
10612 +
10613 + if (key.type == HASH_KEY_IS_STRING) {
10614 + efree(xkey);
10615 + }
10616 + }
10617 + return SUCCESS;
10618 +}
10619 +#endif /* HAVE_ICONV */
10620 +
10621 +PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC)
10622 +{
10623 + char *s = NULL;
10624 + size_t l = 0;
10625 +
10626 + if (Z_TYPE_P(qarray) != IS_ARRAY) {
10627 + convert_to_array(qarray);
10628 + }
10629 + if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) {
10630 + zval_dtor(qstring);
10631 + ZVAL_STRINGL(qstring, s, l, 0);
10632 + } else {
10633 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string");
10634 + }
10635 +}
10636 +
10637 +PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC)
10638 +{
10639 + if (Z_TYPE_P(params) == IS_ARRAY) {
10640 + return http_querystring_modify_array(qarray, params);
10641 + } else if (Z_TYPE_P(params) == IS_OBJECT) {
10642 +#ifdef ZEND_ENGINE_2
10643 + if (instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) {
10644 + return http_querystring_modify_array(qarray, zend_read_property(THIS_CE, params, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC));
10645 + } else {
10646 +#endif
10647 + return http_querystring_modify_array(qarray, params);
10648 +#ifdef ZEND_ENGINE_2
10649 + }
10650 +#endif
10651 + } else {
10652 + int rv;
10653 + zval array;
10654 + zval *qstring = http_zsep(IS_STRING, params);
10655 +
10656 + INIT_PZVAL(&array);
10657 + array_init(&array);
10658 +
10659 + sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(qstring)), &array TSRMLS_CC);
10660 + zval_ptr_dtor(&qstring);
10661 +
10662 + rv = http_querystring_modify_array(qarray, &array);
10663 + zval_dtor(&array);
10664 + return rv;
10665 + }
10666 +}
10667 +
10668 +static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC)
10669 +{
10670 + int rv = 0;
10671 + HashKey key = initHashKey(0);
10672 + HashPosition pos;
10673 + zval **params_entry = NULL;
10674 +
10675 + FOREACH_HASH_KEYVAL(pos, HASH_OF(params), key, params_entry) {
10676 + /* only public properties */
10677 + 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)) {
10678 + rv = 1;
10679 + }
10680 + }
10681 +
10682 + return rv;
10683 +}
10684 +
10685 +static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC)
10686 +{
10687 + zval **qarray_entry;
10688 +
10689 + /* ensure array type */
10690 + if (Z_TYPE_P(qarray) != IS_ARRAY) {
10691 + convert_to_array(qarray);
10692 + }
10693 +
10694 + /* delete */
10695 + if (Z_TYPE_P(params_entry) == IS_NULL) {
10696 + if (key_type == HASH_KEY_IS_STRING) {
10697 + return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen));
10698 + } else {
10699 + return (SUCCESS == zend_hash_index_del(Z_ARRVAL_P(qarray), idx));
10700 + }
10701 + }
10702 +
10703 + /* update */
10704 + if ( ((key_type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry))) ||
10705 + ((key_type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), idx, (void *) &qarray_entry)))) {
10706 + zval equal;
10707 +
10708 + /* recursive */
10709 + if (Z_TYPE_P(params_entry) == IS_ARRAY || Z_TYPE_P(params_entry) == IS_OBJECT) {
10710 + return http_querystring_modify(*qarray_entry, params_entry);
10711 + }
10712 + /* equal */
10713 + if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) {
10714 + return 0;
10715 + }
10716 + }
10717 +
10718 + /* add */
10719 + if (Z_TYPE_P(params_entry) == IS_OBJECT) {
10720 + zval *new_array;
10721 +
10722 + MAKE_STD_ZVAL(new_array);
10723 + array_init(new_array);
10724 + http_querystring_modify_array(new_array, params_entry);
10725 + params_entry = new_array;
10726 + } else {
10727 + ZVAL_ADDREF(params_entry);
10728 + }
10729 + if (key_type == HASH_KEY_IS_STRING) {
10730 + add_assoc_zval_ex(qarray, key, keylen, params_entry);
10731 + } else {
10732 + add_index_zval(qarray, idx, params_entry);
10733 + }
10734 + return 1;
10735 +}
10736 +
10737 +/*
10738 + * Local variables:
10739 + * tab-width: 4
10740 + * c-basic-offset: 4
10741 + * End:
10742 + * vim600: noet sw=4 ts=4 fdm=marker
10743 + * vim<600: noet sw=4 ts=4
10744 + */
10745 --- /dev/null
10746 +++ b/ext/http/http_querystring_object.c
10747 @@ -0,0 +1,633 @@
10748 +/*
10749 + +--------------------------------------------------------------------+
10750 + | PECL :: http |
10751 + +--------------------------------------------------------------------+
10752 + | Redistribution and use in source and binary forms, with or without |
10753 + | modification, are permitted provided that the conditions mentioned |
10754 + | in the accompanying LICENSE file are met. |
10755 + +--------------------------------------------------------------------+
10756 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10757 + +--------------------------------------------------------------------+
10758 +*/
10759 +
10760 +/* $Id: http_querystring_object.c 323304 2012-02-17 21:13:24Z mike $ */
10761 +
10762 +#define HTTP_WANT_SAPI
10763 +#include "php_http.h"
10764 +
10765 +#ifdef ZEND_ENGINE_2
10766 +
10767 +#include "php_variables.h"
10768 +#include "zend_interfaces.h"
10769 +
10770 +#include "php_http_api.h"
10771 +#include "php_http_querystring_api.h"
10772 +#include "php_http_querystring_object.h"
10773 +#include "php_http_exception_object.h"
10774 +
10775 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpQueryString, method, 0, req_args)
10776 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpQueryString, method, 0)
10777 +#define HTTP_QUERYSTRING_ME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, method), visibility)
10778 +#define HTTP_QUERYSTRING_GME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, __getter), visibility)
10779 +
10780 +HTTP_BEGIN_ARGS(__construct, 0)
10781 + HTTP_ARG_VAL(global, 0)
10782 + HTTP_ARG_VAL(params, 0)
10783 +HTTP_END_ARGS;
10784 +
10785 +#ifndef WONKY
10786 +HTTP_BEGIN_ARGS(singleton, 0)
10787 + HTTP_ARG_VAL(global, 0)
10788 +HTTP_END_ARGS;
10789 +#endif
10790 +
10791 +HTTP_BEGIN_ARGS(factory, 0)
10792 + HTTP_ARG_VAL(global, 0)
10793 + HTTP_ARG_VAL(params, 0)
10794 + HTTP_ARG_VAL(class_name, 0)
10795 +HTTP_END_ARGS;
10796 +
10797 +HTTP_EMPTY_ARGS(toArray);
10798 +HTTP_EMPTY_ARGS(toString);
10799 +
10800 +HTTP_BEGIN_ARGS(get, 0)
10801 + HTTP_ARG_VAL(name, 0)
10802 + HTTP_ARG_VAL(type, 0)
10803 + HTTP_ARG_VAL(defval, 0)
10804 + HTTP_ARG_VAL(delete, 0)
10805 +HTTP_END_ARGS;
10806 +
10807 +HTTP_BEGIN_ARGS(set, 1)
10808 + HTTP_ARG_VAL(params, 0)
10809 +HTTP_END_ARGS;
10810 +
10811 +HTTP_BEGIN_ARGS(mod, 0)
10812 + HTTP_ARG_VAL(params, 0)
10813 +HTTP_END_ARGS;
10814 +
10815 +HTTP_BEGIN_ARGS(__getter, 1)
10816 + HTTP_ARG_VAL(name, 0)
10817 + HTTP_ARG_VAL(defval, 0)
10818 + HTTP_ARG_VAL(delete, 0)
10819 +HTTP_END_ARGS;
10820 +
10821 +#ifdef HTTP_HAVE_ICONV
10822 +HTTP_BEGIN_ARGS(xlate, 2)
10823 + HTTP_ARG_VAL(from_encoding, 0)
10824 + HTTP_ARG_VAL(to_encoding, 0)
10825 +HTTP_END_ARGS;
10826 +#endif
10827 +
10828 +HTTP_EMPTY_ARGS(serialize);
10829 +HTTP_BEGIN_ARGS(unserialize, 1)
10830 + HTTP_ARG_VAL(serialized, 0)
10831 +HTTP_END_ARGS;
10832 +
10833 +HTTP_BEGIN_ARGS(offsetGet, 1)
10834 + HTTP_ARG_VAL(offset, 0)
10835 +HTTP_END_ARGS;
10836 +
10837 +HTTP_BEGIN_ARGS(offsetSet, 2)
10838 + HTTP_ARG_VAL(offset, 0)
10839 + HTTP_ARG_VAL(value, 0)
10840 +HTTP_END_ARGS;
10841 +
10842 +HTTP_BEGIN_ARGS(offsetExists, 1)
10843 + HTTP_ARG_VAL(offset, 0)
10844 +HTTP_END_ARGS;
10845 +
10846 +HTTP_BEGIN_ARGS(offsetUnset, 1)
10847 + HTTP_ARG_VAL(offset, 0)
10848 +HTTP_END_ARGS;
10849 +
10850 +
10851 +#define THIS_CE http_querystring_object_ce
10852 +zend_class_entry *http_querystring_object_ce;
10853 +zend_function_entry http_querystring_object_fe[] = {
10854 + HTTP_QUERYSTRING_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL)
10855 +
10856 + HTTP_QUERYSTRING_ME(toArray, ZEND_ACC_PUBLIC)
10857 + HTTP_QUERYSTRING_ME(toString, ZEND_ACC_PUBLIC)
10858 + ZEND_MALIAS(HttpQueryString, __toString, toString, HTTP_ARGS(HttpQueryString, toString), ZEND_ACC_PUBLIC)
10859 +
10860 + HTTP_QUERYSTRING_ME(get, ZEND_ACC_PUBLIC)
10861 + HTTP_QUERYSTRING_ME(set, ZEND_ACC_PUBLIC)
10862 + HTTP_QUERYSTRING_ME(mod, ZEND_ACC_PUBLIC)
10863 +
10864 + HTTP_QUERYSTRING_GME(getBool, ZEND_ACC_PUBLIC)
10865 + HTTP_QUERYSTRING_GME(getInt, ZEND_ACC_PUBLIC)
10866 + HTTP_QUERYSTRING_GME(getFloat, ZEND_ACC_PUBLIC)
10867 + HTTP_QUERYSTRING_GME(getString, ZEND_ACC_PUBLIC)
10868 + HTTP_QUERYSTRING_GME(getArray, ZEND_ACC_PUBLIC)
10869 + HTTP_QUERYSTRING_GME(getObject, ZEND_ACC_PUBLIC)
10870 +
10871 + HTTP_QUERYSTRING_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
10872 +#ifndef WONKY
10873 + HTTP_QUERYSTRING_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
10874 +#endif
10875 +#ifdef HTTP_HAVE_ICONV
10876 + HTTP_QUERYSTRING_ME(xlate, ZEND_ACC_PUBLIC)
10877 +#endif
10878 +
10879 + /* Implements Serializable */
10880 + HTTP_QUERYSTRING_ME(serialize, ZEND_ACC_PUBLIC)
10881 + HTTP_QUERYSTRING_ME(unserialize, ZEND_ACC_PUBLIC)
10882 +
10883 + /* Implements ArrayAccess */
10884 + HTTP_QUERYSTRING_ME(offsetGet, ZEND_ACC_PUBLIC)
10885 + HTTP_QUERYSTRING_ME(offsetSet, ZEND_ACC_PUBLIC)
10886 + HTTP_QUERYSTRING_ME(offsetExists, ZEND_ACC_PUBLIC)
10887 + HTTP_QUERYSTRING_ME(offsetUnset, ZEND_ACC_PUBLIC)
10888 +
10889 + EMPTY_FUNCTION_ENTRY
10890 +};
10891 +static zend_object_handlers http_querystring_object_handlers;
10892 +
10893 +PHP_MINIT_FUNCTION(http_querystring_object)
10894 +{
10895 + HTTP_REGISTER_CLASS_EX(HttpQueryString, http_querystring_object, NULL, 0);
10896 +
10897 +#ifndef WONKY
10898 + zend_class_implements(http_querystring_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_arrayaccess);
10899 +#endif
10900 +
10901 + zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
10902 + zend_declare_property_null(THIS_CE, ZEND_STRS("queryArray")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
10903 + zend_declare_property_string(THIS_CE, ZEND_STRS("queryString")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
10904 +
10905 +#ifndef WONKY
10906 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_BOOL")-1, HTTP_QUERYSTRING_TYPE_BOOL TSRMLS_CC);
10907 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_INT")-1, HTTP_QUERYSTRING_TYPE_INT TSRMLS_CC);
10908 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_FLOAT")-1, HTTP_QUERYSTRING_TYPE_FLOAT TSRMLS_CC);
10909 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_STRING")-1, HTTP_QUERYSTRING_TYPE_STRING TSRMLS_CC);
10910 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ARRAY")-1, HTTP_QUERYSTRING_TYPE_ARRAY TSRMLS_CC);
10911 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_OBJECT")-1, HTTP_QUERYSTRING_TYPE_OBJECT TSRMLS_CC);
10912 +#endif
10913 +
10914 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_BOOL", HTTP_QUERYSTRING_TYPE_BOOL);
10915 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_INT", HTTP_QUERYSTRING_TYPE_INT);
10916 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_FLOAT", HTTP_QUERYSTRING_TYPE_FLOAT);
10917 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_STRING", HTTP_QUERYSTRING_TYPE_STRING);
10918 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_ARRAY", HTTP_QUERYSTRING_TYPE_ARRAY);
10919 + HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_OBJECT", HTTP_QUERYSTRING_TYPE_OBJECT);
10920 +
10921 + return SUCCESS;
10922 +}
10923 +
10924 +zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC)
10925 +{
10926 + return http_querystring_object_new_ex(ce, NULL, NULL);
10927 +}
10928 +
10929 +zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC)
10930 +{
10931 + zend_object_value ov;
10932 + http_querystring_object *o;
10933 +
10934 + o = ecalloc(1, sizeof(http_querystring_object));
10935 + o->zo.ce = ce;
10936 +
10937 + if (ptr) {
10938 + *ptr = o;
10939 + }
10940 +
10941 +#ifdef ZEND_ENGINE_2_4
10942 + zend_object_std_init(o, ce TSRMLS_CC);
10943 + object_properties_init(o, ce);
10944 +#else
10945 + ALLOC_HASHTABLE(OBJ_PROP(o));
10946 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
10947 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
10948 +#endif
10949 +
10950 + ov.handle = putObject(http_querystring_object, o);
10951 + ov.handlers = &http_querystring_object_handlers;
10952 +
10953 + return ov;
10954 +}
10955 +
10956 +void _http_querystring_object_free(zend_object *object TSRMLS_DC)
10957 +{
10958 + http_querystring_object *o = (http_querystring_object *) object;
10959 +
10960 + freeObject(o);
10961 +}
10962 +
10963 +/* {{{ querystring helpers */
10964 +#define http_querystring_instantiate(t, g, p, u) _http_querystring_instantiate((t), (g), (p), (u) TSRMLS_CC)
10965 +static inline zval *_http_querystring_instantiate(zval *this_ptr, zend_bool global, zval *params, zend_bool defer_update TSRMLS_DC)
10966 +{
10967 + zval *qarray = NULL, *qstring = NULL, **_SERVER = NULL, **_GET = NULL, **QUERY_STRING = NULL;;
10968 +
10969 + if (!this_ptr) {
10970 + MAKE_STD_ZVAL(this_ptr);
10971 + Z_TYPE_P(this_ptr) = IS_OBJECT;
10972 + this_ptr->value.obj = http_querystring_object_new(http_querystring_object_ce);
10973 + }
10974 + if (global) {
10975 +#ifdef ZEND_ENGINE_2
10976 + zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
10977 +#endif
10978 + if ( (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &_SERVER)) &&
10979 + (Z_TYPE_PP(_SERVER) == IS_ARRAY) &&
10980 + (SUCCESS == zend_hash_find(Z_ARRVAL_PP(_SERVER), "QUERY_STRING", sizeof("QUERY_STRING"), (void *) &QUERY_STRING))) {
10981 +
10982 + qstring = *QUERY_STRING;
10983 +#ifdef ZEND_ENGINE_2
10984 + zend_is_auto_global("_GET", lenof("_GET") TSRMLS_CC);
10985 +#endif
10986 + if ((SUCCESS == zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void *) &_GET)) && (Z_TYPE_PP(_GET) == IS_ARRAY)) {
10987 + qarray = *_GET;
10988 + } else {
10989 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to superglobal GET array");
10990 + }
10991 + } else {
10992 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to QUERY_STRING");
10993 + }
10994 +
10995 + if (qarray && qstring) {
10996 + if (Z_TYPE_P(qstring) != IS_STRING) {
10997 + convert_to_string(qstring);
10998 + }
10999 +
11000 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC);
11001 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, qstring TSRMLS_CC);
11002 +#ifdef Z_SET_ISREF
11003 + Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC));
11004 + Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
11005 +#else
11006 + zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)->is_ref = 1;
11007 + zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)->is_ref = 1;
11008 +#endif
11009 +
11010 + if (params) {
11011 + http_querystring_modify(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), params);
11012 + }
11013 + if (!defer_update) {
11014 + 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));
11015 + }
11016 + }
11017 + } else {
11018 + MAKE_STD_ZVAL(qarray);
11019 + array_init(qarray);
11020 +
11021 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC);
11022 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryString")-1, "", 0 TSRMLS_CC);
11023 +
11024 + if (params && http_querystring_modify(qarray, params) && !defer_update) {
11025 + http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
11026 + }
11027 +
11028 + zval_ptr_dtor(&qarray);
11029 + }
11030 +
11031 + return this_ptr;
11032 +}
11033 +
11034 +#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC)
11035 +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)
11036 +{
11037 + zval **arrval, *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11038 +
11039 + if ((Z_TYPE_P(qarray) == IS_ARRAY) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), name, name_len + 1, (void *) &arrval))) {
11040 + if (type) {
11041 + zval *value = http_zsep(type, *arrval);
11042 + RETVAL_ZVAL(value, 1, 1);
11043 + } else {
11044 + RETVAL_ZVAL(*arrval, 1, 0);
11045 + }
11046 +
11047 + if (del && (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), name, name_len + 1))) {
11048 + http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
11049 + }
11050 + } else if(defval) {
11051 + RETURN_ZVAL(defval, 1, 0);
11052 + }
11053 +}
11054 +/* }}} */
11055 +
11056 +/* {{{ proto final void HttpQueryString::__construct([bool global = true[, mixed add])
11057 + Creates a new HttpQueryString object instance. Operates on and modifies $_GET and $_SERVER['QUERY_STRING'] if global is TRUE. */
11058 +PHP_METHOD(HttpQueryString, __construct)
11059 +{
11060 + zend_bool global = 1;
11061 + zval *params = NULL;
11062 +
11063 + SET_EH_THROW_HTTP();
11064 + if (!sapi_module.treat_data) {
11065 + http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered");
11066 + } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bz", &global, &params)) {
11067 + http_querystring_instantiate(getThis(), global, params, 0);
11068 + }
11069 + SET_EH_NORMAL();
11070 +}
11071 +/* }}} */
11072 +
11073 +/* {{{ proto HttpQueryString HttpQueryString::factory([bool global = TRUE[, mixed params[, string class_name = "HttpQueryString"])
11074 + Creates a new HttpQueryString object instance. */
11075 +PHP_METHOD(HttpQueryString, factory)
11076 +{
11077 + zend_bool global = 1;
11078 + zval *params = NULL;
11079 + char *cn = NULL;
11080 + int cl = 0;
11081 + zend_object_value ov;
11082 +
11083 + SET_EH_THROW_HTTP();
11084 + if (!sapi_module.treat_data) {
11085 + http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered");
11086 + } else if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bzs", &global, &params, &cn, &cl) &&
11087 + SUCCESS == http_object_new(&ov, cn, cl, _http_querystring_object_new_ex, http_querystring_object_ce, NULL, NULL)) {
11088 + RETVAL_OBJVAL(ov, 0);
11089 + http_querystring_instantiate(return_value, global, params, 0);
11090 + }
11091 + SET_EH_NORMAL();
11092 +}
11093 +/* }}} */
11094 +
11095 +/* {{{ proto string HttpQueryString::toString()
11096 + Returns the string representation. */
11097 +PHP_METHOD(HttpQueryString, toString)
11098 +{
11099 + NO_ARGS;
11100 + RETURN_PROP(queryString);
11101 +}
11102 +/* }}} */
11103 +
11104 +/* {{{ proto array HttpQueryString::toArray()
11105 + Returns the array representation. */
11106 +PHP_METHOD(HttpQueryString, toArray)
11107 +{
11108 + NO_ARGS;
11109 + RETURN_PROP(queryArray);
11110 +}
11111 +/* }}} */
11112 +
11113 +/* {{{ proto mixed HttpQueryString::get([string key[, mixed type = 0[, mixed defval = NULL[, bool delete = false]]]])
11114 + 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. */
11115 +PHP_METHOD(HttpQueryString, get)
11116 +{
11117 + char *name = NULL;
11118 + int name_len = 0;
11119 + long type = 0;
11120 + zend_bool del = 0;
11121 + zval *ztype = NULL, *defval = NULL;
11122 +
11123 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szzb", &name, &name_len, &ztype, &defval, &del)) {
11124 + if (name && name_len) {
11125 + if (ztype) {
11126 + if (Z_TYPE_P(ztype) == IS_LONG) {
11127 + type = Z_LVAL_P(ztype);
11128 + } else if(Z_TYPE_P(ztype) == IS_STRING) {
11129 + switch (Z_STRVAL_P(ztype)[0]) {
11130 + case 'B':
11131 + case 'b': type = HTTP_QUERYSTRING_TYPE_BOOL; break;
11132 + case 'I':
11133 + case 'i': type = HTTP_QUERYSTRING_TYPE_INT; break;
11134 + case 'F':
11135 + case 'f': type = HTTP_QUERYSTRING_TYPE_FLOAT; break;
11136 + case 'S':
11137 + case 's': type = HTTP_QUERYSTRING_TYPE_STRING; break;
11138 + case 'A':
11139 + case 'a': type = HTTP_QUERYSTRING_TYPE_ARRAY; break;
11140 + case 'O':
11141 + case 'o': type = HTTP_QUERYSTRING_TYPE_OBJECT; break;
11142 + }
11143 + }
11144 + }
11145 + http_querystring_get(getThis(), type, name, name_len, defval, del, return_value);
11146 + } else {
11147 + RETURN_PROP(queryString);
11148 + }
11149 + }
11150 +}
11151 +/* }}} */
11152 +
11153 +/* {{{ proto string HttpQueryString::set(mixed params)
11154 + Set query string entry/entries. NULL values will unset the variable. */
11155 +PHP_METHOD(HttpQueryString, set)
11156 +{
11157 + zval *params;
11158 +
11159 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &params)) {
11160 + zval *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11161 + if (http_querystring_modify(qarray, params)) {
11162 + http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
11163 + }
11164 + }
11165 +
11166 + if (return_value_used) {
11167 + RETURN_PROP(queryString);
11168 + }
11169 +}
11170 +/* }}} */
11171 +
11172 +/* {{{ proto HttpQueryString HttpQueryString::mod(mixed params)
11173 + Copies the query string object and sets provided params at the clone. */
11174 +PHP_METHOD(HttpQueryString, mod)
11175 +{
11176 + zval *zobj, *qarr, *qstr, *params;
11177 +
11178 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &params)) {
11179 + zobj = http_querystring_instantiate(NULL, 0, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), 1);
11180 + qarr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11181 + qstr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryString")-1, 0 TSRMLS_CC);
11182 +
11183 + http_querystring_modify(qarr, params);
11184 + http_querystring_update(qarr, qstr);
11185 +
11186 + RETURN_ZVAL(zobj, 1, 1);
11187 + }
11188 +}
11189 +/* }}} */
11190 +
11191 +#ifndef WONKY
11192 +/* {{{ proto static HttpQueryString HttpQueryString::singleton([bool global = true])
11193 + Get a single instance (differentiates between the global setting). */
11194 +PHP_METHOD(HttpQueryString, singleton)
11195 +{
11196 + zend_bool global = 1;
11197 + zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
11198 +
11199 + SET_EH_THROW_HTTP();
11200 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) {
11201 + zval **zobj_ptr = NULL, *zobj = NULL;
11202 +
11203 + if (Z_TYPE_P(instance) == IS_ARRAY) {
11204 + if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) {
11205 + RETVAL_ZVAL(*zobj_ptr, 1, 0);
11206 + } else {
11207 + zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global);
11208 + add_index_zval(instance, global, zobj);
11209 + RETVAL_OBJECT(zobj, 1);
11210 + }
11211 + } else {
11212 + MAKE_STD_ZVAL(instance);
11213 + array_init(instance);
11214 +
11215 + zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global);
11216 + add_index_zval(instance, global, zobj);
11217 + RETVAL_OBJECT(zobj, 1);
11218 +
11219 + zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC);
11220 + zval_ptr_dtor(&instance);
11221 + }
11222 + }
11223 + SET_EH_NORMAL();
11224 +}
11225 +/* }}} */
11226 +#endif
11227 +
11228 +/* {{{ Getters by type */
11229 +#define HTTP_QUERYSTRING_GETTER(method, TYPE) \
11230 +PHP_METHOD(HttpQueryString, method) \
11231 +{ \
11232 + char *name; \
11233 + int name_len; \
11234 + zval *defval = NULL; \
11235 + zend_bool del = 0; \
11236 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &name, &name_len, &defval, &del)) { \
11237 + http_querystring_get(getThis(), TYPE, name, name_len, defval, del, return_value); \
11238 + } \
11239 +}
11240 +HTTP_QUERYSTRING_GETTER(getBool, IS_BOOL);
11241 +HTTP_QUERYSTRING_GETTER(getInt, IS_LONG);
11242 +HTTP_QUERYSTRING_GETTER(getFloat, IS_DOUBLE);
11243 +HTTP_QUERYSTRING_GETTER(getString, IS_STRING);
11244 +HTTP_QUERYSTRING_GETTER(getArray, IS_ARRAY);
11245 +HTTP_QUERYSTRING_GETTER(getObject, IS_OBJECT);
11246 +/* }}} */
11247 +
11248 +#ifdef HTTP_HAVE_ICONV
11249 +/* {{{ proto bool HttpQueryString::xlate(string ie, string oe)
11250 + 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. */
11251 +PHP_METHOD(HttpQueryString, xlate)
11252 +{
11253 + char *ie, *oe;
11254 + int ie_len, oe_len;
11255 + zval xa, *qa, *qs;
11256 + STATUS rs;
11257 +
11258 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ie, &ie_len, &oe, &oe_len)) {
11259 + RETURN_FALSE;
11260 + }
11261 +
11262 + qa = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11263 + qs = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC);
11264 + INIT_PZVAL(&xa);
11265 + array_init(&xa);
11266 +
11267 + if (SUCCESS == (rs = http_querystring_xlate(&xa, qa, ie, oe))) {
11268 + zend_hash_clean(Z_ARRVAL_P(qa));
11269 + zend_hash_copy(Z_ARRVAL_P(qa), Z_ARRVAL(xa), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
11270 + http_querystring_update(qa, qs);
11271 + }
11272 + zval_dtor(&xa);
11273 +
11274 + RETURN_SUCCESS(rs);
11275 +}
11276 +/* }}} */
11277 +#endif /* HAVE_ICONV */
11278 +
11279 +/* {{{ proto string HttpQueryString::serialize()
11280 + Implements Serializable::serialize(). */
11281 +PHP_METHOD(HttpQueryString, serialize)
11282 +{
11283 + NO_ARGS;
11284 + RETURN_PROP(queryString);
11285 +}
11286 +/* }}} */
11287 +
11288 +/* {{{ proto void HttpQueryString::unserialize(string serialized)
11289 + Implements Serializable::unserialize(). */
11290 +PHP_METHOD(HttpQueryString, unserialize)
11291 +{
11292 + zval *serialized;
11293 +
11294 + SET_EH_THROW_HTTP();
11295 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &serialized)) {
11296 + if (Z_TYPE_P(serialized) == IS_STRING) {
11297 + http_querystring_instantiate(getThis(), 0, serialized, 0);
11298 + } else {
11299 + http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Expected a string as parameter");
11300 + }
11301 + }
11302 + SET_EH_NORMAL();
11303 +}
11304 +/* }}} */
11305 +
11306 +/* {{{ proto mixed HttpQueryString::offsetGet(string offset)
11307 + Implements ArrayAccess::offsetGet(). */
11308 +PHP_METHOD(HttpQueryString, offsetGet)
11309 +{
11310 + char *offset_str;
11311 + int offset_len;
11312 + zval **value;
11313 +
11314 + if ( (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) &&
11315 + (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))) {
11316 + RETVAL_ZVAL(*value, 1, 0);
11317 + }
11318 +}
11319 +/* }}} */
11320 +
11321 +/* {{{ proto void HttpQueryString::offsetSet(string offset, mixed value)
11322 + Implements ArrayAccess::offsetGet(). */
11323 +PHP_METHOD(HttpQueryString, offsetSet)
11324 +{
11325 + char *offset_str;
11326 + int offset_len;
11327 + zval *value;
11328 +
11329 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset_str, &offset_len, &value)) {
11330 + 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);
11331 +
11332 + ZVAL_ADDREF(value);
11333 + add_assoc_zval_ex(qarr, offset_str, offset_len + 1, value);
11334 + http_querystring_update(qarr, qstr);
11335 + }
11336 +}
11337 +/* }}} */
11338 +
11339 +/* {{{ proto bool HttpQueryString::offsetExists(string offset)
11340 + Implements ArrayAccess::offsetExists(). */
11341 +PHP_METHOD(HttpQueryString, offsetExists)
11342 +{
11343 + char *offset_str;
11344 + int offset_len;
11345 + zval **value;
11346 +
11347 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
11348 + 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));
11349 + }
11350 +}
11351 +/* }}} */
11352 +
11353 +/* {{{ proto void HttpQueryString::offsetUnset(string offset)
11354 + Implements ArrayAccess::offsetUnset(). */
11355 +PHP_METHOD(HttpQueryString, offsetUnset)
11356 +{
11357 + char *offset_str;
11358 + int offset_len;
11359 +
11360 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) {
11361 + zval *qarr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC);
11362 +
11363 + if (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarr), offset_str, offset_len + 1)) {
11364 + http_querystring_update(qarr, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC));
11365 + }
11366 + }
11367 +}
11368 +/* }}} */
11369 +
11370 +#endif /* ZEND_ENGINE_2 */
11371 +
11372 +/*
11373 + * Local variables:
11374 + * tab-width: 4
11375 + * c-basic-offset: 4
11376 + * End:
11377 + * vim600: noet sw=4 ts=4 fdm=marker
11378 + * vim<600: noet sw=4 ts=4
11379 + */
11380 +
11381 --- /dev/null
11382 +++ b/ext/http/http_request_api.c
11383 @@ -0,0 +1,1326 @@
11384 +/*
11385 + +--------------------------------------------------------------------+
11386 + | PECL :: http |
11387 + +--------------------------------------------------------------------+
11388 + | Redistribution and use in source and binary forms, with or without |
11389 + | modification, are permitted provided that the conditions mentioned |
11390 + | in the accompanying LICENSE file are met. |
11391 + +--------------------------------------------------------------------+
11392 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
11393 + +--------------------------------------------------------------------+
11394 +*/
11395 +
11396 +/* $Id: http_request_api.c 310775 2011-05-05 06:02:50Z mike $ */
11397 +
11398 +#define HTTP_WANT_SAPI
11399 +#define HTTP_WANT_CURL
11400 +#include "php_http.h"
11401 +
11402 +#ifdef HTTP_HAVE_CURL
11403 +
11404 +#include "php_http_api.h"
11405 +#include "php_http_persistent_handle_api.h"
11406 +#include "php_http_request_api.h"
11407 +#include "php_http_url_api.h"
11408 +
11409 +#ifdef ZEND_ENGINE_2
11410 +# include "php_http_request_object.h"
11411 +#endif
11412 +
11413 +#include "php_http_request_int.h"
11414 +
11415 +/* {{{ cruft for thread safe SSL crypto locks */
11416 +#ifdef HTTP_NEED_OPENSSL_TSL
11417 +static MUTEX_T *http_openssl_tsl = NULL;
11418 +
11419 +static void http_openssl_thread_lock(int mode, int n, const char * file, int line)
11420 +{
11421 + if (mode & CRYPTO_LOCK) {
11422 + tsrm_mutex_lock(http_openssl_tsl[n]);
11423 + } else {
11424 + tsrm_mutex_unlock(http_openssl_tsl[n]);
11425 + }
11426 +}
11427 +
11428 +static ulong http_openssl_thread_id(void)
11429 +{
11430 + return (ulong) tsrm_thread_id();
11431 +}
11432 +#endif
11433 +#ifdef HTTP_NEED_GNUTLS_TSL
11434 +static int http_gnutls_mutex_create(void **m)
11435 +{
11436 + if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
11437 + return SUCCESS;
11438 + } else {
11439 + return FAILURE;
11440 + }
11441 +}
11442 +
11443 +static int http_gnutls_mutex_destroy(void **m)
11444 +{
11445 + tsrm_mutex_free(*((MUTEX_T *) m));
11446 + return SUCCESS;
11447 +}
11448 +
11449 +static int http_gnutls_mutex_lock(void **m)
11450 +{
11451 + return tsrm_mutex_lock(*((MUTEX_T *) m));
11452 +}
11453 +
11454 +static int http_gnutls_mutex_unlock(void **m)
11455 +{
11456 + return tsrm_mutex_unlock(*((MUTEX_T *) m));
11457 +}
11458 +
11459 +static struct gcry_thread_cbs http_gnutls_tsl = {
11460 + GCRY_THREAD_OPTION_USER,
11461 + NULL,
11462 + http_gnutls_mutex_create,
11463 + http_gnutls_mutex_destroy,
11464 + http_gnutls_mutex_lock,
11465 + http_gnutls_mutex_unlock
11466 +};
11467 +#endif
11468 +/* }}} */
11469 +
11470 +/* safe curl wrappers */
11471 +#define init_curl_storage(ch) \
11472 + {\
11473 + http_request_storage *st = pecalloc(1, sizeof(http_request_storage), 1); \
11474 + curl_easy_setopt(ch, CURLOPT_PRIVATE, st); \
11475 + curl_easy_setopt(ch, CURLOPT_ERRORBUFFER, st->errorbuffer); \
11476 + }
11477 +
11478 +static void *safe_curl_init(void)
11479 +{
11480 + CURL *ch;
11481 +
11482 + if ((ch = curl_easy_init())) {
11483 + init_curl_storage(ch);
11484 + return ch;
11485 + }
11486 + return NULL;
11487 +}
11488 +static void *safe_curl_copy(void *p)
11489 +{
11490 + CURL *ch;
11491 +
11492 + if ((ch = curl_easy_duphandle(p))) {
11493 + init_curl_storage(ch);
11494 + return ch;
11495 + }
11496 + return NULL;
11497 +}
11498 +static void safe_curl_dtor(void *p) {
11499 + http_request_storage *st = http_request_storage_get(p);
11500 +
11501 + curl_easy_cleanup(p);
11502 +
11503 + if (st) {
11504 + if (st->url) {
11505 + pefree(st->url, 1);
11506 + }
11507 + if (st->cookiestore) {
11508 + pefree(st->cookiestore, 1);
11509 + }
11510 + pefree(st, 1);
11511 + }
11512 +}
11513 +/* }}} */
11514 +
11515 +/* {{{ MINIT */
11516 +PHP_MINIT_FUNCTION(http_request)
11517 +{
11518 +#ifdef HTTP_NEED_OPENSSL_TSL
11519 + /* mod_ssl, libpq or ext/curl might already have set thread lock callbacks */
11520 + if (!CRYPTO_get_id_callback()) {
11521 + int i, c = CRYPTO_num_locks();
11522 +
11523 + http_openssl_tsl = malloc(c * sizeof(MUTEX_T));
11524 +
11525 + for (i = 0; i < c; ++i) {
11526 + http_openssl_tsl[i] = tsrm_mutex_alloc();
11527 + }
11528 +
11529 + CRYPTO_set_id_callback(http_openssl_thread_id);
11530 + CRYPTO_set_locking_callback(http_openssl_thread_lock);
11531 + }
11532 +#endif
11533 +#ifdef HTTP_NEED_GNUTLS_TSL
11534 + gcry_control(GCRYCTL_SET_THREAD_CBS, &http_gnutls_tsl);
11535 +#endif
11536 +
11537 + if (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL)) {
11538 + return FAILURE;
11539 + }
11540 +
11541 + if (SUCCESS != http_persistent_handle_provide("http_request", safe_curl_init, safe_curl_dtor, safe_curl_copy)) {
11542 + return FAILURE;
11543 + }
11544 +
11545 + HTTP_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC);
11546 + HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST);
11547 +#if HTTP_CURL_VERSION(7,19,3)
11548 + HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST_IE", CURLAUTH_DIGEST_IE);
11549 +#endif
11550 + HTTP_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM);
11551 + HTTP_LONG_CONSTANT("HTTP_AUTH_GSSNEG", CURLAUTH_GSSNEGOTIATE);
11552 + HTTP_LONG_CONSTANT("HTTP_AUTH_ANY", CURLAUTH_ANY);
11553 +
11554 + HTTP_LONG_CONSTANT("HTTP_VERSION_NONE", CURL_HTTP_VERSION_NONE); /* to be removed */
11555 + HTTP_LONG_CONSTANT("HTTP_VERSION_1_0", CURL_HTTP_VERSION_1_0);
11556 + HTTP_LONG_CONSTANT("HTTP_VERSION_1_1", CURL_HTTP_VERSION_1_1);
11557 + HTTP_LONG_CONSTANT("HTTP_VERSION_ANY", CURL_HTTP_VERSION_NONE);
11558 +
11559 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_TLSv1", CURL_SSLVERSION_TLSv1);
11560 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv2", CURL_SSLVERSION_SSLv2);
11561 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv3", CURL_SSLVERSION_SSLv3);
11562 + HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_ANY", CURL_SSLVERSION_DEFAULT);
11563 +
11564 + HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V4", CURL_IPRESOLVE_V4);
11565 + HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V6", CURL_IPRESOLVE_V6);
11566 + HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_ANY", CURL_IPRESOLVE_WHATEVER);
11567 +
11568 +#if HTTP_CURL_VERSION(7,15,2)
11569 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4", CURLPROXY_SOCKS4);
11570 +#endif
11571 +#if HTTP_CURL_VERSION(7,18,0)
11572 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4A", CURLPROXY_SOCKS4A);
11573 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5_HOSTNAME);
11574 +#endif
11575 + HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5", CURLPROXY_SOCKS5);
11576 + HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP", CURLPROXY_HTTP);
11577 +#if HTTP_CURL_VERSION(7,19,4)
11578 + HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP_1_0", CURLPROXY_HTTP_1_0);
11579 +#endif
11580 +
11581 +#if HTTP_CURL_VERSION(7,19,1)
11582 + HTTP_LONG_CONSTANT("HTTP_POSTREDIR_301", CURL_REDIR_POST_301);
11583 + HTTP_LONG_CONSTANT("HTTP_POSTREDIR_302", CURL_REDIR_POST_302);
11584 + HTTP_LONG_CONSTANT("HTTP_POSTREDIR_ALL", CURL_REDIR_POST_ALL);
11585 +#endif
11586 + return SUCCESS;
11587 +}
11588 +/* }}} */
11589 +
11590 +/* {{{ MSHUTDOWN */
11591 +PHP_MSHUTDOWN_FUNCTION(http_request)
11592 +{
11593 + curl_global_cleanup();
11594 +#ifdef HTTP_NEED_OPENSSL_TSL
11595 + if (http_openssl_tsl) {
11596 + int i, c = CRYPTO_num_locks();
11597 +
11598 + CRYPTO_set_id_callback(NULL);
11599 + CRYPTO_set_locking_callback(NULL);
11600 +
11601 + for (i = 0; i < c; ++i) {
11602 + tsrm_mutex_free(http_openssl_tsl[i]);
11603 + }
11604 +
11605 + free(http_openssl_tsl);
11606 + http_openssl_tsl = NULL;
11607 + }
11608 +#endif
11609 + return SUCCESS;
11610 +}
11611 +/* }}} */
11612 +
11613 +/* {{{ forward declarations */
11614 +#define http_request_option(r, o, k, t) _http_request_option_ex((r), (o), (k), sizeof(k), (t) TSRMLS_CC)
11615 +#define http_request_option_ex(r, o, k, l, t) _http_request_option_ex((r), (o), (k), (l), (t) TSRMLS_CC)
11616 +static inline zval *_http_request_option_ex(http_request *request, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC);
11617 +#define http_request_option_cache(r, k, z) _http_request_option_cache_ex((r), (k), sizeof(k), 0, (z) TSRMLS_CC)
11618 +#define http_request_option_cache_ex(r, k, kl, h, z) _http_request_option_cache_ex((r), (k), (kl), (h), (z) TSRMLS_CC)
11619 +static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC);
11620 +
11621 +#define http_request_cookies_enabled(r) _http_request_cookies_enabled((r))
11622 +static inline int _http_request_cookies_enabled(http_request *r);
11623 +
11624 +static size_t http_curl_read_callback(void *, size_t, size_t, void *);
11625 +static int http_curl_progress_callback(void *, double, double, double, double);
11626 +static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *);
11627 +static int http_curl_dummy_callback(char *data, size_t n, size_t l, void *s) { return n*l; }
11628 +static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *);
11629 +/* }}} */
11630 +
11631 +/* {{{ CURL *http_curl_init(http_request *) */
11632 +PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC)
11633 +{
11634 + if (ch || (SUCCESS == http_persistent_handle_acquire("http_request", &ch))) {
11635 +#if defined(ZTS)
11636 + curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
11637 +#endif
11638 + curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
11639 + curl_easy_setopt(ch, CURLOPT_FILETIME, 1L);
11640 + curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1L);
11641 + curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
11642 + curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, NULL);
11643 + curl_easy_setopt(ch, CURLOPT_DEBUGFUNCTION, http_curl_raw_callback);
11644 + curl_easy_setopt(ch, CURLOPT_READFUNCTION, http_curl_read_callback);
11645 + curl_easy_setopt(ch, CURLOPT_IOCTLFUNCTION, http_curl_ioctl_callback);
11646 + curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, http_curl_dummy_callback);
11647 +
11648 + /* set context */
11649 + if (request) {
11650 + curl_easy_setopt(ch, CURLOPT_DEBUGDATA, request);
11651 +
11652 + /* attach curl handle */
11653 + request->ch = ch;
11654 + /* set defaults (also in http_request_reset()) */
11655 + http_request_defaults(request);
11656 + }
11657 + }
11658 +
11659 + return ch;
11660 +}
11661 +/* }}} */
11662 +
11663 +/* {{{ CURL *http_curl_copy(CURL *) */
11664 +PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC)
11665 +{
11666 + CURL *copy;
11667 +
11668 + if (SUCCESS == http_persistent_handle_accrete("http_request", ch, &copy)) {
11669 + return copy;
11670 + }
11671 + return NULL;
11672 +}
11673 +/* }}} */
11674 +
11675 +/* {{{ void http_curl_free(CURL **) */
11676 +PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC)
11677 +{
11678 + if (*ch) {
11679 + curl_easy_setopt(*ch, CURLOPT_NOPROGRESS, 1L);
11680 + curl_easy_setopt(*ch, CURLOPT_PROGRESSFUNCTION, NULL);
11681 + curl_easy_setopt(*ch, CURLOPT_VERBOSE, 0L);
11682 + curl_easy_setopt(*ch, CURLOPT_DEBUGFUNCTION, NULL);
11683 +
11684 + http_persistent_handle_release("http_request", ch);
11685 + }
11686 +}
11687 +/* }}} */
11688 +
11689 +/* {{{ http_request *http_request_init(http_request *) */
11690 +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)
11691 +{
11692 + http_request *r;
11693 +
11694 + if (request) {
11695 + r = request;
11696 + } else {
11697 + r = emalloc_rel(sizeof(http_request));
11698 + }
11699 + memset(r, 0, sizeof(http_request));
11700 +
11701 + r->ch = ch;
11702 + r->url = (url) ? http_absolute_url(url) : NULL;
11703 + r->meth = (meth > 0) ? meth : HTTP_GET;
11704 +
11705 + phpstr_init(&r->conv.request);
11706 + phpstr_init_ex(&r->conv.response, HTTP_CURLBUF_SIZE, 0);
11707 + phpstr_init(&r->_cache.cookies);
11708 + zend_hash_init(&r->_cache.options, 0, NULL, ZVAL_PTR_DTOR, 0);
11709 +
11710 + TSRMLS_SET_CTX(r->tsrm_ls);
11711 +
11712 + return r;
11713 +}
11714 +/* }}} */
11715 +
11716 +/* {{{ void http_request_dtor(http_request *) */
11717 +PHP_HTTP_API void _http_request_dtor(http_request *request)
11718 +{
11719 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11720 +
11721 + http_request_reset(request);
11722 + http_curl_free(&request->ch);
11723 +
11724 + phpstr_dtor(&request->_cache.cookies);
11725 + zend_hash_destroy(&request->_cache.options);
11726 + if (request->_cache.headers) {
11727 + curl_slist_free_all(request->_cache.headers);
11728 + request->_cache.headers = NULL;
11729 + }
11730 + if (request->_progress_callback) {
11731 + zval_ptr_dtor(&request->_progress_callback);
11732 + request->_progress_callback = NULL;
11733 + }
11734 +}
11735 +/* }}} */
11736 +
11737 +/* {{{ void http_request_free(http_request **) */
11738 +PHP_HTTP_API void _http_request_free(http_request **request)
11739 +{
11740 + if (*request) {
11741 + TSRMLS_FETCH_FROM_CTX((*request)->tsrm_ls);
11742 + http_request_body_free(&(*request)->body);
11743 + http_request_dtor(*request);
11744 + efree(*request);
11745 + *request = NULL;
11746 + }
11747 +}
11748 +/* }}} */
11749 +
11750 +/* {{{ void http_request_reset(http_request *) */
11751 +PHP_HTTP_API void _http_request_reset(http_request *request)
11752 +{
11753 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11754 + STR_SET(request->url, NULL);
11755 + request->conv.last_type = 0;
11756 + phpstr_dtor(&request->conv.request);
11757 + phpstr_dtor(&request->conv.response);
11758 + http_request_body_dtor(request->body);
11759 + http_request_defaults(request);
11760 +
11761 + if (request->ch) {
11762 + http_request_storage *st = http_request_storage_get(request->ch);
11763 +
11764 + if (st) {
11765 + if (st->url) {
11766 + pefree(st->url, 1);
11767 + st->url = NULL;
11768 + }
11769 + if (st->cookiestore) {
11770 + pefree(st->cookiestore, 1);
11771 + st->cookiestore = NULL;
11772 + }
11773 + st->errorbuffer[0] = '\0';
11774 + }
11775 + }
11776 +}
11777 +/* }}} */
11778 +
11779 +/* {{{ STATUS http_request_enable_cookies(http_request *) */
11780 +PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request)
11781 +{
11782 + int initialized = 1;
11783 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11784 +
11785 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
11786 + if (initialized && (http_request_cookies_enabled(request) || (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIEFILE, "")))) {
11787 + return SUCCESS;
11788 + }
11789 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not enable cookies for this session");
11790 + return FAILURE;
11791 +}
11792 +/* }}} */
11793 +
11794 +/* {{{ STATUS http_request_reset_cookies(http_request *, int) */
11795 +PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only)
11796 +{
11797 + int initialized = 1;
11798 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11799 +
11800 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
11801 + if (initialized) {
11802 + if (!http_request_cookies_enabled(request)) {
11803 + if (SUCCESS != http_request_enable_cookies(request)) {
11804 + return FAILURE;
11805 + }
11806 + }
11807 + if (session_only) {
11808 +#if HTTP_CURL_VERSION(7,15,4)
11809 + if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "SESS")) {
11810 + return SUCCESS;
11811 + }
11812 +#else
11813 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset session cookies (need libcurl >= v7.15.4)");
11814 +#endif
11815 + } else {
11816 +#if HTTP_CURL_VERSION(7,14,1)
11817 + if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "ALL")) {
11818 + return SUCCESS;
11819 + }
11820 +#else
11821 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset cookies (need libcurl >= v7.14.1)");
11822 +#endif
11823 + }
11824 + }
11825 + return FAILURE;
11826 +}
11827 +/* }}} */
11828 +
11829 +PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request)
11830 +{
11831 + int initialized = 1;
11832 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11833 +
11834 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0);
11835 + if (initialized) {
11836 + if (!http_request_cookies_enabled(request)) {
11837 + return FAILURE;
11838 + }
11839 +#if HTTP_CURL_VERSION(7,17,1)
11840 + if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "FLUSH")) {
11841 + return SUCCESS;
11842 + }
11843 +#else
11844 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not flush cookies (need libcurl >= v7.17.1)");
11845 +#endif
11846 + }
11847 + return FAILURE;
11848 +}
11849 +
11850 +/* {{{ void http_request_defaults(http_request *) */
11851 +PHP_HTTP_API void _http_request_defaults(http_request *request)
11852 +{
11853 + if (request->ch) {
11854 + HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL);
11855 + HTTP_CURL_OPT(CURLOPT_URL, NULL);
11856 + HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1L);
11857 +#if HTTP_CURL_VERSION(7,19,4)
11858 + HTTP_CURL_OPT(CURLOPT_NOPROXY, NULL);
11859 +#endif
11860 + HTTP_CURL_OPT(CURLOPT_PROXY, NULL);
11861 + HTTP_CURL_OPT(CURLOPT_PROXYPORT, 0L);
11862 + HTTP_CURL_OPT(CURLOPT_PROXYTYPE, 0L);
11863 + /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
11864 +#if HTTP_CURL_VERSION(7,19,1)
11865 + HTTP_CURL_OPT(CURLOPT_PROXYUSERNAME, NULL);
11866 + HTTP_CURL_OPT(CURLOPT_PROXYPASSWORD, NULL);
11867 +#endif
11868 + HTTP_CURL_OPT(CURLOPT_PROXYAUTH, 0L);
11869 + HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 0L);
11870 + HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, 60L);
11871 + HTTP_CURL_OPT(CURLOPT_IPRESOLVE, 0);
11872 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, 0L);
11873 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, 0L);
11874 +#if HTTP_CURL_VERSION(7,15,5)
11875 + /* LFS weirdance
11876 + HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) 0);
11877 + HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) 0);
11878 + */
11879 +#endif
11880 + /* crashes
11881 + HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, 5L); */
11882 + HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 0L);
11883 + HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 0L);
11884 + HTTP_CURL_OPT(CURLOPT_INTERFACE, NULL);
11885 + HTTP_CURL_OPT(CURLOPT_PORT, 0L);
11886 +#if HTTP_CURL_VERSION(7,19,0)
11887 + HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, 0L);
11888 +#endif
11889 +#if HTTP_CURL_VERSION(7,15,2)
11890 + HTTP_CURL_OPT(CURLOPT_LOCALPORT, 0L);
11891 + HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, 0L);
11892 +#endif
11893 + /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
11894 +#if HTTP_CURL_VERSION(7,19,1)
11895 + HTTP_CURL_OPT(CURLOPT_USERNAME, NULL);
11896 + HTTP_CURL_OPT(CURLOPT_PASSWORD, NULL);
11897 +#endif
11898 + HTTP_CURL_OPT(CURLOPT_HTTPAUTH, 0L);
11899 + HTTP_CURL_OPT(CURLOPT_ENCODING, NULL);
11900 +#if HTTP_CURL_VERSION(7,16,2)
11901 + /* we do this ourself anyway */
11902 + HTTP_CURL_OPT(CURLOPT_HTTP_CONTENT_DECODING, 0L);
11903 + HTTP_CURL_OPT(CURLOPT_HTTP_TRANSFER_DECODING, 0L);
11904 +#endif
11905 + HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, 0L);
11906 +#if HTTP_CURL_VERSION(7,19,1)
11907 + HTTP_CURL_OPT(CURLOPT_POSTREDIR, 0L);
11908 +#elif HTTP_CURL_VERSION(7,17,1)
11909 + HTTP_CURL_OPT(CURLOPT_POST301, 0L);
11910 +#endif
11911 + HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, 0L);
11912 + HTTP_CURL_OPT(CURLOPT_REFERER, NULL);
11913 + HTTP_CURL_OPT(CURLOPT_USERAGENT, "PECL::HTTP/" PHP_HTTP_VERSION " (PHP/" PHP_VERSION ")");
11914 + HTTP_CURL_OPT(CURLOPT_HTTPHEADER, NULL);
11915 + HTTP_CURL_OPT(CURLOPT_COOKIE, NULL);
11916 + HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 0L);
11917 + /* these options would enable curl's cookie engine by default which we don't want
11918 + HTTP_CURL_OPT(CURLOPT_COOKIEFILE, NULL);
11919 + HTTP_CURL_OPT(CURLOPT_COOKIEJAR, NULL); */
11920 +#if HTTP_CURL_VERSION(7,14,1)
11921 + HTTP_CURL_OPT(CURLOPT_COOKIELIST, NULL);
11922 +#endif
11923 + HTTP_CURL_OPT(CURLOPT_RANGE, NULL);
11924 + HTTP_CURL_OPT(CURLOPT_RESUME_FROM, 0L);
11925 + HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, 0L);
11926 + HTTP_CURL_OPT(CURLOPT_TIMECONDITION, 0L);
11927 + HTTP_CURL_OPT(CURLOPT_TIMEVALUE, 0L);
11928 + HTTP_CURL_OPT(CURLOPT_TIMEOUT, 0L);
11929 + HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, 3);
11930 + HTTP_CURL_OPT(CURLOPT_SSLCERT, NULL);
11931 + HTTP_CURL_OPT(CURLOPT_SSLCERTTYPE, NULL);
11932 + HTTP_CURL_OPT(CURLOPT_SSLCERTPASSWD, NULL);
11933 + HTTP_CURL_OPT(CURLOPT_SSLKEY, NULL);
11934 + HTTP_CURL_OPT(CURLOPT_SSLKEYTYPE, NULL);
11935 + HTTP_CURL_OPT(CURLOPT_SSLKEYPASSWD, NULL);
11936 + HTTP_CURL_OPT(CURLOPT_SSLENGINE, NULL);
11937 + HTTP_CURL_OPT(CURLOPT_SSLVERSION, 0L);
11938 + HTTP_CURL_OPT(CURLOPT_SSL_VERIFYPEER, 0L);
11939 + HTTP_CURL_OPT(CURLOPT_SSL_VERIFYHOST, 0L);
11940 + HTTP_CURL_OPT(CURLOPT_SSL_CIPHER_LIST, NULL);
11941 +#if HTTP_CURL_VERSION(7,19,0)
11942 + HTTP_CURL_OPT(CURLOPT_ISSUERCERT, NULL);
11943 + #if defined(HTTP_HAVE_OPENSSL)
11944 + HTTP_CURL_OPT(CURLOPT_CRLFILE, NULL);
11945 + #endif
11946 +#endif
11947 +#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
11948 + HTTP_CURL_OPT(CURLOPT_CERTINFO, NULL);
11949 +#endif
11950 +#ifdef HTTP_CURL_CAINFO
11951 + HTTP_CURL_OPT(CURLOPT_CAINFO, HTTP_CURL_CAINFO);
11952 +#else
11953 + HTTP_CURL_OPT(CURLOPT_CAINFO, NULL);
11954 +#endif
11955 + HTTP_CURL_OPT(CURLOPT_CAPATH, NULL);
11956 + HTTP_CURL_OPT(CURLOPT_RANDOM_FILE, NULL);
11957 + HTTP_CURL_OPT(CURLOPT_EGDSOCKET, NULL);
11958 + HTTP_CURL_OPT(CURLOPT_POSTFIELDS, NULL);
11959 + HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, 0L);
11960 + HTTP_CURL_OPT(CURLOPT_HTTPPOST, NULL);
11961 + HTTP_CURL_OPT(CURLOPT_IOCTLDATA, NULL);
11962 + HTTP_CURL_OPT(CURLOPT_READDATA, NULL);
11963 + HTTP_CURL_OPT(CURLOPT_INFILESIZE, 0L);
11964 + HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE);
11965 + HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, NULL);
11966 + HTTP_CURL_OPT(CURLOPT_NOBODY, 0L);
11967 + HTTP_CURL_OPT(CURLOPT_POST, 0L);
11968 + HTTP_CURL_OPT(CURLOPT_UPLOAD, 0L);
11969 + HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L);
11970 + }
11971 +}
11972 +/* }}} */
11973 +
11974 +PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb)
11975 +{
11976 + if (request->_progress_callback) {
11977 + zval_ptr_dtor(&request->_progress_callback);
11978 + }
11979 + if ((request->_progress_callback = cb)) {
11980 + ZVAL_ADDREF(cb);
11981 + HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 0);
11982 + HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, request);
11983 + HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, http_curl_progress_callback);
11984 + } else {
11985 + HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1);
11986 + HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, NULL);
11987 + HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL);
11988 + }
11989 +}
11990 +
11991 +/* {{{ STATUS http_request_prepare(http_request *, HashTable *) */
11992 +PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options)
11993 +{
11994 + zval *zoption;
11995 + zend_bool range_req = 0;
11996 + http_request_storage *storage;
11997 +
11998 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
11999 +
12000 + HTTP_CHECK_CURL_INIT(request->ch, http_curl_init(request), return FAILURE);
12001 +
12002 + if (!request->url) {
12003 + return FAILURE;
12004 + }
12005 + if (!(storage = http_request_storage_get(request->ch))) {
12006 + return FAILURE;
12007 + }
12008 + storage->errorbuffer[0] = '\0';
12009 + /* set options */
12010 + if (storage->url) {
12011 + pefree(storage->url, 1);
12012 + }
12013 + storage->url = pestrdup(request->url, 1);
12014 + HTTP_CURL_OPT(CURLOPT_URL, storage->url);
12015 +
12016 + /* progress callback */
12017 + if ((zoption = http_request_option(request, options, "onprogress", -1))) {
12018 + http_request_set_progress_callback(request, zoption);
12019 + }
12020 +
12021 + /* proxy */
12022 + if ((zoption = http_request_option(request, options, "proxyhost", IS_STRING))) {
12023 + HTTP_CURL_OPT(CURLOPT_PROXY, Z_STRVAL_P(zoption));
12024 + /* type */
12025 + if ((zoption = http_request_option(request, options, "proxytype", IS_LONG))) {
12026 + HTTP_CURL_OPT(CURLOPT_PROXYTYPE, Z_LVAL_P(zoption));
12027 + }
12028 + /* port */
12029 + if ((zoption = http_request_option(request, options, "proxyport", IS_LONG))) {
12030 + HTTP_CURL_OPT(CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
12031 + }
12032 + /* user:pass */
12033 + if ((zoption = http_request_option(request, options, "proxyauth", IS_STRING)) && Z_STRLEN_P(zoption)) {
12034 + HTTP_CURL_OPT(CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
12035 + }
12036 + /* auth method */
12037 + if ((zoption = http_request_option(request, options, "proxyauthtype", IS_LONG))) {
12038 + HTTP_CURL_OPT(CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
12039 + }
12040 + /* tunnel */
12041 + if ((zoption = http_request_option(request, options, "proxytunnel", IS_BOOL)) && Z_BVAL_P(zoption)) {
12042 + HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 1L);
12043 + }
12044 + }
12045 +#if HTTP_CURL_VERSION(7,19,4)
12046 + if ((zoption = http_request_option(request, options, "noproxy", IS_STRING))) {
12047 + HTTP_CURL_OPT(CURLOPT_NOPROXY, Z_STRVAL_P(zoption));
12048 + }
12049 +#endif
12050 +
12051 + /* dns */
12052 + if ((zoption = http_request_option(request, options, "dns_cache_timeout", IS_LONG))) {
12053 + HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, Z_LVAL_P(zoption));
12054 + }
12055 + if ((zoption = http_request_option(request, options, "ipresolve", IS_LONG)) && Z_LVAL_P(zoption)) {
12056 + HTTP_CURL_OPT(CURLOPT_IPRESOLVE, Z_LVAL_P(zoption));
12057 + }
12058 +
12059 + /* limits */
12060 + if ((zoption = http_request_option(request, options, "low_speed_limit", IS_LONG))) {
12061 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, Z_LVAL_P(zoption));
12062 + }
12063 + if ((zoption = http_request_option(request, options, "low_speed_time", IS_LONG))) {
12064 + HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, Z_LVAL_P(zoption));
12065 + }
12066 +#if HTTP_CURL_VERSION(7,15,5)
12067 + /* LSF weirdance
12068 + if ((zoption = http_request_option(request, options, "max_send_speed", IS_LONG))) {
12069 + HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
12070 + }
12071 + if ((zoption = http_request_option(request, options, "max_recv_speed", IS_LONG))) {
12072 + HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
12073 + }
12074 + */
12075 +#endif
12076 + /* crashes
12077 + if ((zoption = http_request_option(request, options, "maxconnects", IS_LONG))) {
12078 + HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, Z_LVAL_P(zoption));
12079 + } */
12080 + if ((zoption = http_request_option(request, options, "fresh_connect", IS_BOOL)) && Z_BVAL_P(zoption)) {
12081 + HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 1L);
12082 + }
12083 + if ((zoption = http_request_option(request, options, "forbid_reuse", IS_BOOL)) && Z_BVAL_P(zoption)) {
12084 + HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 1L);
12085 + }
12086 +
12087 + /* outgoing interface */
12088 + if ((zoption = http_request_option(request, options, "interface", IS_STRING))) {
12089 + HTTP_CURL_OPT(CURLOPT_INTERFACE, Z_STRVAL_P(zoption));
12090 +
12091 +#if HTTP_CURL_VERSION(7,15,2)
12092 + if ((zoption = http_request_option(request, options, "portrange", IS_ARRAY))) {
12093 + zval **prs, **pre;
12094 +
12095 + zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
12096 + if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &prs)) {
12097 + zend_hash_move_forward(Z_ARRVAL_P(zoption));
12098 + if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &pre)) {
12099 + zval *prs_cpy = http_zsep(IS_LONG, *prs);
12100 + zval *pre_cpy = http_zsep(IS_LONG, *pre);
12101 +
12102 + if (Z_LVAL_P(prs_cpy) && Z_LVAL_P(pre_cpy)) {
12103 + HTTP_CURL_OPT(CURLOPT_LOCALPORT, MIN(Z_LVAL_P(prs_cpy), Z_LVAL_P(pre_cpy)));
12104 + HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, labs(Z_LVAL_P(prs_cpy)-Z_LVAL_P(pre_cpy))+1L);
12105 + }
12106 + zval_ptr_dtor(&prs_cpy);
12107 + zval_ptr_dtor(&pre_cpy);
12108 + }
12109 + }
12110 + }
12111 +#endif
12112 + }
12113 +
12114 + /* another port */
12115 + if ((zoption = http_request_option(request, options, "port", IS_LONG))) {
12116 + HTTP_CURL_OPT(CURLOPT_PORT, Z_LVAL_P(zoption));
12117 + }
12118 +
12119 + /* RFC4007 zone_id */
12120 +#if HTTP_CURL_VERSION(7,19,0)
12121 + if ((zoption = http_request_option(request, options, "address_scope", IS_LONG))) {
12122 + HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, Z_LVAL_P(zoption));
12123 + }
12124 +#endif
12125 +
12126 + /* auth */
12127 + if ((zoption = http_request_option(request, options, "httpauth", IS_STRING)) && Z_STRLEN_P(zoption)) {
12128 + HTTP_CURL_OPT(CURLOPT_USERPWD, Z_STRVAL_P(zoption));
12129 + }
12130 + if ((zoption = http_request_option(request, options, "httpauthtype", IS_LONG))) {
12131 + HTTP_CURL_OPT(CURLOPT_HTTPAUTH, Z_LVAL_P(zoption));
12132 + }
12133 +
12134 + /* redirects, defaults to 0 */
12135 + if ((zoption = http_request_option(request, options, "redirect", IS_LONG))) {
12136 + HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1L : 0L);
12137 + HTTP_CURL_OPT(CURLOPT_MAXREDIRS, Z_LVAL_P(zoption));
12138 + if ((zoption = http_request_option(request, options, "unrestrictedauth", IS_BOOL))) {
12139 + HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, Z_LVAL_P(zoption));
12140 + }
12141 +#if HTTP_CURL_VERSION(7,17,1)
12142 + if ((zoption = http_request_option(request, options, "postredir", IS_BOOL))) {
12143 +# if HTTP_CURL_VERSION(7,19,1)
12144 + HTTP_CURL_OPT(CURLOPT_POSTREDIR, Z_BVAL_P(zoption) ? 1L : 0L);
12145 +# else
12146 + HTTP_CURL_OPT(CURLOPT_POST301, Z_BVAL_P(zoption) ? 1L : 0L);
12147 +# endif
12148 + }
12149 +#endif
12150 + }
12151 +
12152 + /* retries, defaults to 0 */
12153 + if ((zoption = http_request_option(request, options, "retrycount", IS_LONG))) {
12154 + request->_retry.count = Z_LVAL_P(zoption);
12155 + if ((zoption = http_request_option(request, options, "retrydelay", IS_DOUBLE))) {
12156 + request->_retry.delay = Z_DVAL_P(zoption);
12157 + } else {
12158 + request->_retry.delay = 0;
12159 + }
12160 + } else {
12161 + request->_retry.count = 0;
12162 + }
12163 +
12164 + /* referer */
12165 + if ((zoption = http_request_option(request, options, "referer", IS_STRING)) && Z_STRLEN_P(zoption)) {
12166 + HTTP_CURL_OPT(CURLOPT_REFERER, Z_STRVAL_P(zoption));
12167 + }
12168 +
12169 + /* useragent, default "PECL::HTTP/version (PHP/version)" */
12170 + if ((zoption = http_request_option(request, options, "useragent", IS_STRING))) {
12171 + /* allow to send no user agent, not even default one */
12172 + if (Z_STRLEN_P(zoption)) {
12173 + HTTP_CURL_OPT(CURLOPT_USERAGENT, Z_STRVAL_P(zoption));
12174 + } else {
12175 + HTTP_CURL_OPT(CURLOPT_USERAGENT, NULL);
12176 + }
12177 + }
12178 +
12179 + /* resume */
12180 + if ((zoption = http_request_option(request, options, "resume", IS_LONG)) && (Z_LVAL_P(zoption) > 0)) {
12181 + range_req = 1;
12182 + HTTP_CURL_OPT(CURLOPT_RESUME_FROM, Z_LVAL_P(zoption));
12183 + }
12184 + /* or range of kind array(array(0,499), array(100,1499)) */
12185 + else if ((zoption = http_request_option(request, options, "range", IS_ARRAY)) && zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
12186 + HashPosition pos1, pos2;
12187 + zval **rr, **rb, **re;
12188 + phpstr rs;
12189 +
12190 + phpstr_init(&rs);
12191 + FOREACH_VAL(pos1, zoption, rr) {
12192 + if (Z_TYPE_PP(rr) == IS_ARRAY) {
12193 + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(rr), &pos2);
12194 + if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &rb, &pos2)) {
12195 + zend_hash_move_forward_ex(Z_ARRVAL_PP(rr), &pos2);
12196 + if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &re, &pos2)) {
12197 + 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))) &&
12198 + ((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)))) {
12199 + zval *rbl = http_zsep(IS_LONG, *rb);
12200 + zval *rel = http_zsep(IS_LONG, *re);
12201 +
12202 + if ((Z_LVAL_P(rbl) >= 0) && (Z_LVAL_P(rel) >= 0)) {
12203 + phpstr_appendf(&rs, "%ld-%ld,", Z_LVAL_P(rbl), Z_LVAL_P(rel));
12204 + }
12205 + zval_ptr_dtor(&rbl);
12206 + zval_ptr_dtor(&rel);
12207 + }
12208 + }
12209 + }
12210 + }
12211 + }
12212 +
12213 + if (PHPSTR_LEN(&rs)) {
12214 + zval *cached_range;
12215 +
12216 + /* ditch last comma */
12217 + PHPSTR_VAL(&rs)[PHPSTR_LEN(&rs)-- -1] = '\0';
12218 + /* cache string */
12219 + MAKE_STD_ZVAL(cached_range);
12220 + ZVAL_STRINGL(cached_range, PHPSTR_VAL(&rs), PHPSTR_LEN(&rs), 0);
12221 + HTTP_CURL_OPT(CURLOPT_RANGE, Z_STRVAL_P(http_request_option_cache(request, "range", cached_range)));
12222 + zval_ptr_dtor(&cached_range);
12223 + }
12224 + }
12225 +
12226 + /* additional headers, array('name' => 'value') */
12227 + if (request->_cache.headers) {
12228 + curl_slist_free_all(request->_cache.headers);
12229 + request->_cache.headers = NULL;
12230 + }
12231 + if ((zoption = http_request_option(request, options, "headers", IS_ARRAY))) {
12232 + HashKey header_key = initHashKey(0);
12233 + zval **header_val;
12234 + HashPosition pos;
12235 + phpstr header;
12236 +
12237 + phpstr_init(&header);
12238 + FOREACH_KEYVAL(pos, zoption, header_key, header_val) {
12239 + if (header_key.type == HASH_KEY_IS_STRING) {
12240 + zval *header_cpy = http_zsep(IS_STRING, *header_val);
12241 +
12242 + if (!strcasecmp(header_key.str, "range")) {
12243 + range_req = 1;
12244 + }
12245 +
12246 + phpstr_appendf(&header, "%s: %s", header_key.str, Z_STRVAL_P(header_cpy));
12247 + phpstr_fix(&header);
12248 + request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header));
12249 + phpstr_reset(&header);
12250 +
12251 + zval_ptr_dtor(&header_cpy);
12252 + }
12253 + }
12254 + phpstr_dtor(&header);
12255 + }
12256 + /* etag */
12257 + if ((zoption = http_request_option(request, options, "etag", IS_STRING)) && Z_STRLEN_P(zoption)) {
12258 + zend_bool is_quoted = !((Z_STRVAL_P(zoption)[0] != '"') || (Z_STRVAL_P(zoption)[Z_STRLEN_P(zoption)-1] != '"'));
12259 + phpstr header;
12260 +
12261 + phpstr_init(&header);
12262 + phpstr_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", range_req?"If-Match":"If-None-Match", Z_STRVAL_P(zoption));
12263 + phpstr_fix(&header);
12264 + request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header));
12265 + phpstr_dtor(&header);
12266 + }
12267 + /* compression */
12268 + if ((zoption = http_request_option(request, options, "compress", IS_BOOL)) && Z_LVAL_P(zoption)) {
12269 + request->_cache.headers = curl_slist_append(request->_cache.headers, "Accept-Encoding: gzip;q=1.0,deflate;q=0.5");
12270 + }
12271 + HTTP_CURL_OPT(CURLOPT_HTTPHEADER, request->_cache.headers);
12272 +
12273 + /* lastmodified */
12274 + if ((zoption = http_request_option(request, options, "lastmodified", IS_LONG))) {
12275 + if (Z_LVAL_P(zoption)) {
12276 + if (Z_LVAL_P(zoption) > 0) {
12277 + HTTP_CURL_OPT(CURLOPT_TIMEVALUE, Z_LVAL_P(zoption));
12278 + } else {
12279 + HTTP_CURL_OPT(CURLOPT_TIMEVALUE, (long) HTTP_G->request.time + Z_LVAL_P(zoption));
12280 + }
12281 + HTTP_CURL_OPT(CURLOPT_TIMECONDITION, (long) (range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE));
12282 + } else {
12283 + HTTP_CURL_OPT(CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
12284 + }
12285 + }
12286 +
12287 + /* cookies, array('name' => 'value') */
12288 + if ((zoption = http_request_option(request, options, "cookies", IS_ARRAY))) {
12289 + phpstr_dtor(&request->_cache.cookies);
12290 + if (zend_hash_num_elements(Z_ARRVAL_P(zoption))) {
12291 + zval *urlenc_cookies = NULL;
12292 + /* check whether cookies should not be urlencoded; default is to urlencode them */
12293 + if ((!(urlenc_cookies = http_request_option(request, options, "encodecookies", IS_BOOL))) || Z_BVAL_P(urlenc_cookies)) {
12294 + if (SUCCESS == http_urlencode_hash_recursive(HASH_OF(zoption), &request->_cache.cookies, "; ", lenof("; "), NULL, 0)) {
12295 + phpstr_fix(&request->_cache.cookies);
12296 + HTTP_CURL_OPT(CURLOPT_COOKIE, request->_cache.cookies.data);
12297 + }
12298 + } else {
12299 + HashPosition pos;
12300 + HashKey cookie_key = initHashKey(0);
12301 + zval **cookie_val;
12302 +
12303 + FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) {
12304 + if (cookie_key.type == HASH_KEY_IS_STRING) {
12305 + zval *val = http_zsep(IS_STRING, *cookie_val);
12306 + phpstr_appendf(&request->_cache.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val));
12307 + zval_ptr_dtor(&val);
12308 + }
12309 + }
12310 +
12311 + phpstr_fix(&request->_cache.cookies);
12312 + if (PHPSTR_LEN(&request->_cache.cookies)) {
12313 + HTTP_CURL_OPT(CURLOPT_COOKIE, PHPSTR_VAL(&request->_cache.cookies));
12314 + }
12315 + }
12316 + }
12317 + }
12318 +
12319 + /* don't load session cookies from cookiestore */
12320 + if ((zoption = http_request_option(request, options, "cookiesession", IS_BOOL)) && Z_BVAL_P(zoption)) {
12321 + HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 1L);
12322 + }
12323 +
12324 + /* cookiestore, read initial cookies from that file and store cookies back into that file */
12325 + if ((zoption = http_request_option(request, options, "cookiestore", IS_STRING))) {
12326 + if (Z_STRLEN_P(zoption)) {
12327 + HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(zoption), return FAILURE);
12328 + }
12329 + if (storage->cookiestore) {
12330 + pefree(storage->cookiestore, 1);
12331 + }
12332 + storage->cookiestore = pestrndup(Z_STRVAL_P(zoption), Z_STRLEN_P(zoption), 1);
12333 + HTTP_CURL_OPT(CURLOPT_COOKIEFILE, storage->cookiestore);
12334 + HTTP_CURL_OPT(CURLOPT_COOKIEJAR, storage->cookiestore);
12335 + }
12336 +
12337 + /* maxfilesize */
12338 + if ((zoption = http_request_option(request, options, "maxfilesize", IS_LONG))) {
12339 + HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, Z_LVAL_P(zoption));
12340 + }
12341 +
12342 + /* http protocol */
12343 + if ((zoption = http_request_option(request, options, "protocol", IS_LONG))) {
12344 + HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, Z_LVAL_P(zoption));
12345 + }
12346 +
12347 +#if HTTP_CURL_VERSION(7,16,2)
12348 + /* timeout, defaults to 0 */
12349 + if ((zoption = http_request_option(request, options, "timeout", IS_DOUBLE))) {
12350 + HTTP_CURL_OPT(CURLOPT_TIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000));
12351 + }
12352 + /* connecttimeout, defaults to 0 */
12353 + if ((zoption = http_request_option(request, options, "connecttimeout", IS_DOUBLE))) {
12354 + HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000));
12355 + }
12356 +#else
12357 + /* timeout, defaults to 0 */
12358 + if ((zoption = http_request_option(request, options, "timeout", IS_LONG))) {
12359 + HTTP_CURL_OPT(CURLOPT_TIMEOUT, Z_LVAL_P(zoption));
12360 + }
12361 + /* connecttimeout, defaults to 0 */
12362 + if ((zoption = http_request_option(request, options, "connecttimeout", IS_LONG))) {
12363 + HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, Z_LVAL_P(zoption));
12364 + }
12365 +#endif
12366 +
12367 + /* ssl */
12368 + if ((zoption = http_request_option(request, options, "ssl", IS_ARRAY))) {
12369 + HashKey key = initHashKey(0);
12370 + zval **param;
12371 + HashPosition pos;
12372 +
12373 + FOREACH_KEYVAL(pos, zoption, key, param) {
12374 + if (key.type == HASH_KEY_IS_STRING) {
12375 + HTTP_CURL_OPT_STRING(CURLOPT_SSLCERT, 0, 1);
12376 + HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTTYPE, 0, 0);
12377 + HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTPASSWD, 0, 0);
12378 +
12379 + HTTP_CURL_OPT_STRING(CURLOPT_SSLKEY, 0, 0);
12380 + HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYTYPE, 0, 0);
12381 + HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYPASSWD, 0, 0);
12382 +
12383 + HTTP_CURL_OPT_STRING(CURLOPT_SSLENGINE, 0, 0);
12384 + HTTP_CURL_OPT_LONG(CURLOPT_SSLVERSION, 0);
12385 +
12386 + HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYPEER, 1);
12387 + HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYHOST, 1);
12388 + HTTP_CURL_OPT_STRING(CURLOPT_SSL_CIPHER_LIST, 1, 0);
12389 +
12390 + HTTP_CURL_OPT_STRING(CURLOPT_CAINFO, -3, 1);
12391 + HTTP_CURL_OPT_STRING(CURLOPT_CAPATH, -3, 1);
12392 + HTTP_CURL_OPT_STRING(CURLOPT_RANDOM_FILE, -3, 1);
12393 + HTTP_CURL_OPT_STRING(CURLOPT_EGDSOCKET, -3, 1);
12394 +#if HTTP_CURL_VERSION(7,19,0)
12395 + HTTP_CURL_OPT_STRING(CURLOPT_ISSUERCERT, -3, 1);
12396 + #if defined(HTTP_HAVE_OPENSSL)
12397 + HTTP_CURL_OPT_STRING(CURLOPT_CRLFILE, -3, 1);
12398 + #endif
12399 +#endif
12400 +#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
12401 + HTTP_CURL_OPT_LONG(CURLOPT_CERTINFO, -3);
12402 +#endif
12403 + }
12404 + }
12405 + }
12406 +
12407 + /* request method */
12408 + switch (request->meth) {
12409 + case HTTP_GET:
12410 + HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L);
12411 + break;
12412 +
12413 + case HTTP_HEAD:
12414 + HTTP_CURL_OPT(CURLOPT_NOBODY, 1L);
12415 + break;
12416 +
12417 + case HTTP_POST:
12418 + HTTP_CURL_OPT(CURLOPT_POST, 1L);
12419 + break;
12420 +
12421 + case HTTP_PUT:
12422 + HTTP_CURL_OPT(CURLOPT_UPLOAD, 1L);
12423 + break;
12424 +
12425 + default:
12426 + if (http_request_method_exists(0, request->meth, NULL)) {
12427 + HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, http_request_method_name(request->meth));
12428 + } else {
12429 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unsupported request method: %d (%s)", request->meth, request->url);
12430 + return FAILURE;
12431 + }
12432 + break;
12433 + }
12434 +
12435 + /* attach request body */
12436 + if (request->body && (request->meth != HTTP_GET) && (request->meth != HTTP_HEAD) && (request->meth != HTTP_OPTIONS)) {
12437 + switch (request->body->type) {
12438 + case HTTP_REQUEST_BODY_EMPTY:
12439 + /* nothing */
12440 + break;
12441 +
12442 + case HTTP_REQUEST_BODY_CURLPOST:
12443 + HTTP_CURL_OPT(CURLOPT_HTTPPOST, (struct curl_httppost *) request->body->data);
12444 + break;
12445 +
12446 + case HTTP_REQUEST_BODY_CSTRING:
12447 + if (request->meth != HTTP_PUT) {
12448 + HTTP_CURL_OPT(CURLOPT_POSTFIELDS, request->body->data);
12449 + HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, request->body->size);
12450 + break;
12451 + }
12452 + /* fallthrough, PUT/UPLOAD _needs_ READDATA */
12453 + case HTTP_REQUEST_BODY_UPLOADFILE:
12454 + HTTP_CURL_OPT(CURLOPT_IOCTLDATA, request);
12455 + HTTP_CURL_OPT(CURLOPT_READDATA, request);
12456 + HTTP_CURL_OPT(CURLOPT_INFILESIZE, request->body->size);
12457 + break;
12458 +
12459 + default:
12460 + /* shouldn't ever happen */
12461 + http_error_ex(HE_ERROR, 0, "Unknown request body type: %d (%s)", request->body->type, request->url);
12462 + return FAILURE;
12463 + }
12464 + }
12465 +
12466 + return SUCCESS;
12467 +}
12468 +/* }}} */
12469 +
12470 +/* {{{ void http_request_exec(http_request *) */
12471 +PHP_HTTP_API void _http_request_exec(http_request *request)
12472 +{
12473 + uint tries = 0;
12474 + CURLcode result;
12475 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12476 +
12477 +retry:
12478 + if (CURLE_OK != (result = curl_easy_perform(request->ch))) {
12479 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(result), http_request_storage_get(request->ch)->errorbuffer, request->url);
12480 +#ifdef ZEND_ENGINE_2
12481 + if ((HTTP_G->only_exceptions || GLOBAL_ERROR_HANDLING == EH_THROW) && EG(exception)) {
12482 + add_property_long(EG(exception), "curlCode", result);
12483 + }
12484 +#endif
12485 +
12486 + if (request->_retry.count > tries++) {
12487 + switch (result) {
12488 + case CURLE_COULDNT_RESOLVE_PROXY:
12489 + case CURLE_COULDNT_RESOLVE_HOST:
12490 + case CURLE_COULDNT_CONNECT:
12491 + case CURLE_WRITE_ERROR:
12492 + case CURLE_READ_ERROR:
12493 + case CURLE_OPERATION_TIMEDOUT:
12494 + case CURLE_SSL_CONNECT_ERROR:
12495 + case CURLE_GOT_NOTHING:
12496 + case CURLE_SSL_ENGINE_SETFAILED:
12497 + case CURLE_SEND_ERROR:
12498 + case CURLE_RECV_ERROR:
12499 + case CURLE_SSL_ENGINE_INITFAILED:
12500 + case CURLE_LOGIN_DENIED:
12501 + if (request->_retry.delay >= HTTP_DIFFSEC) {
12502 + http_sleep(request->_retry.delay);
12503 + }
12504 + goto retry;
12505 + default:
12506 + break;
12507 + }
12508 + }
12509 + }
12510 +}
12511 +/* }}} */
12512 +
12513 +/* {{{ static size_t http_curl_read_callback(void *, size_t, size_t, void *) */
12514 +static size_t http_curl_read_callback(void *data, size_t len, size_t n, void *ctx)
12515 +{
12516 + http_request *request = (http_request *) ctx;
12517 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12518 +
12519 + if (request->body) {
12520 + switch (request->body->type) {
12521 + case HTTP_REQUEST_BODY_CSTRING:
12522 + {
12523 + size_t out = MIN(len * n, request->body->size - request->body->priv);
12524 +
12525 + if (out) {
12526 + memcpy(data, ((char *) request->body->data) + request->body->priv, out);
12527 + request->body->priv += out;
12528 + return out;
12529 + }
12530 + break;
12531 + }
12532 +
12533 + case HTTP_REQUEST_BODY_UPLOADFILE:
12534 + return php_stream_read((php_stream *) request->body->data, data, len * n);
12535 + }
12536 + }
12537 + return 0;
12538 +}
12539 +/* }}} */
12540 +
12541 +/* {{{ static int http_curl_progress_callback(void *, double, double, double, double) */
12542 +static int http_curl_progress_callback(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow)
12543 +{
12544 + zval *param, retval;
12545 + http_request *request = (http_request *) ctx;
12546 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12547 +
12548 + INIT_PZVAL(&retval);
12549 + ZVAL_NULL(&retval);
12550 +
12551 + MAKE_STD_ZVAL(param);
12552 + array_init(param);
12553 + add_assoc_double(param, "dltotal", dltotal);
12554 + add_assoc_double(param, "dlnow", dlnow);
12555 + add_assoc_double(param, "ultotal", ultotal);
12556 + add_assoc_double(param, "ulnow", ulnow);
12557 +
12558 + with_error_handling(EH_NORMAL, NULL) {
12559 + request->_in_progress_cb = 1;
12560 + call_user_function(EG(function_table), NULL, request->_progress_callback, &retval, 1, &param TSRMLS_CC);
12561 + request->_in_progress_cb = 0;
12562 + } end_error_handling();
12563 +
12564 + zval_ptr_dtor(&param);
12565 + zval_dtor(&retval);
12566 +
12567 + return 0;
12568 +}
12569 +/* }}} */
12570 +
12571 +/* {{{ static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *) */
12572 +static curlioerr http_curl_ioctl_callback(CURL *ch, curliocmd cmd, void *ctx)
12573 +{
12574 + http_request *request = (http_request *) ctx;
12575 + TSRMLS_FETCH_FROM_CTX(request->tsrm_ls);
12576 +
12577 + if (cmd != CURLIOCMD_RESTARTREAD) {
12578 + return CURLIOE_UNKNOWNCMD;
12579 + }
12580 +
12581 + if (request->body) {
12582 + switch (request->body->type) {
12583 + case HTTP_REQUEST_BODY_CSTRING:
12584 + request->body->priv = 0;
12585 + return CURLIOE_OK;
12586 + break;
12587 +
12588 + case HTTP_REQUEST_BODY_UPLOADFILE:
12589 + if (SUCCESS == php_stream_rewind((php_stream *) request->body->data)) {
12590 + return CURLIOE_OK;
12591 + }
12592 + break;
12593 + }
12594 + }
12595 +
12596 + return CURLIOE_FAILRESTART;
12597 +}
12598 +/* }}} */
12599 +
12600 +/* {{{ static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *) */
12601 +static int http_curl_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx)
12602 +{
12603 + http_request *request = (http_request *) ctx;
12604 +
12605 +#define EMPTY_HEADER(d, l) (!l || (l == 1 && d[0] == '\n') || (l == 2 && d[0] == '\r' && d[1] == '\n'))
12606 + switch (type) {
12607 + case CURLINFO_DATA_IN:
12608 + if (request->conv.last_type == CURLINFO_HEADER_IN) {
12609 + phpstr_appends(&request->conv.response, HTTP_CRLF);
12610 + }
12611 + phpstr_append(&request->conv.response, data, length);
12612 + break;
12613 + case CURLINFO_HEADER_IN:
12614 + if (!EMPTY_HEADER(data, length)) {
12615 + phpstr_append(&request->conv.response, data, length);
12616 + }
12617 + break;
12618 + case CURLINFO_DATA_OUT:
12619 + case CURLINFO_HEADER_OUT:
12620 + phpstr_append(&request->conv.request, data, length);
12621 + break;
12622 + default:
12623 + break;
12624 + }
12625 +
12626 +#if 0
12627 + {
12628 + const char _sym[] = "><><><";
12629 + if (type) {
12630 + for (fprintf(stderr, "%c ", _sym[type-1]); length--; data++) {
12631 + fprintf(stderr, HTTP_IS_CTYPE(print, *data)?"%c":"\\x%02X", (int) *data);
12632 + if (*data == '\n' && length) {
12633 + fprintf(stderr, "\n%c ", _sym[type-1]);
12634 + }
12635 + }
12636 + fprintf(stderr, "\n");
12637 + } else {
12638 + fprintf(stderr, "# %s", data);
12639 + }
12640 + }
12641 +#endif
12642 +
12643 + if (type) {
12644 + request->conv.last_type = type;
12645 + }
12646 + return 0;
12647 +}
12648 +/* }}} */
12649 +
12650 +/* {{{ static inline zval *http_request_option(http_request *, HashTable *, char *, size_t, int) */
12651 +static inline zval *_http_request_option_ex(http_request *r, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC)
12652 +{
12653 + if (options) {
12654 + zval **zoption;
12655 + ulong h = zend_hash_func(key, keylen);
12656 +
12657 + if (SUCCESS == zend_hash_quick_find(options, key, keylen, h, (void *) &zoption)) {
12658 + zval *option, *cached;
12659 +
12660 + option = http_zsep(type, *zoption);
12661 + cached = http_request_option_cache_ex(r, key, keylen, h, option);
12662 +
12663 + zval_ptr_dtor(&option);
12664 + return cached;
12665 + }
12666 + }
12667 +
12668 + return NULL;
12669 +}
12670 +/* }}} */
12671 +
12672 +/* {{{ static inline zval *http_request_option_cache(http_request *, char *key, zval *) */
12673 +static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC)
12674 +{
12675 + ZVAL_ADDREF(opt);
12676 +
12677 + if (h) {
12678 + zend_hash_quick_update(&r->_cache.options, key, keylen, h, &opt, sizeof(zval *), NULL);
12679 + } else {
12680 + zend_hash_update(&r->_cache.options, key, keylen, &opt, sizeof(zval *), NULL);
12681 + }
12682 +
12683 + return opt;
12684 +}
12685 +/* }}} */
12686 +
12687 +/* {{{ static inline int http_request_cookies_enabled(http_request *) */
12688 +static inline int _http_request_cookies_enabled(http_request *request) {
12689 + http_request_storage *st;
12690 +
12691 + if (request->ch && (st = http_request_storage_get(request->ch)) && st->cookiestore) {
12692 + /* cookies are enabled */
12693 + return 1;
12694 + }
12695 + return 0;
12696 +}
12697 +/* }}} */
12698 +
12699 +#endif /* HTTP_HAVE_CURL */
12700 +
12701 +/*
12702 + * Local variables:
12703 + * tab-width: 4
12704 + * c-basic-offset: 4
12705 + * End:
12706 + * vim600: noet sw=4 ts=4 fdm=marker
12707 + * vim<600: noet sw=4 ts=4
12708 + */
12709 +
12710 --- /dev/null
12711 +++ b/ext/http/http_request_body_api.c
12712 @@ -0,0 +1,332 @@
12713 +/*
12714 + +--------------------------------------------------------------------+
12715 + | PECL :: http |
12716 + +--------------------------------------------------------------------+
12717 + | Redistribution and use in source and binary forms, with or without |
12718 + | modification, are permitted provided that the conditions mentioned |
12719 + | in the accompanying LICENSE file are met. |
12720 + +--------------------------------------------------------------------+
12721 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
12722 + +--------------------------------------------------------------------+
12723 +*/
12724 +
12725 +/* $Id: http_request_body_api.c 292841 2009-12-31 08:48:57Z mike $ */
12726 +
12727 +#define HTTP_WANT_CURL
12728 +#include "php_http.h"
12729 +
12730 +#ifdef HTTP_HAVE_CURL
12731 +
12732 +#include "php_http_api.h"
12733 +#include "php_http_url_api.h"
12734 +#include "php_http_request_body_api.h"
12735 +
12736 +/* {{{ */
12737 +typedef struct curl_httppost *post_data[2];
12738 +static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC);
12739 +static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC);
12740 +/* }}} */
12741 +
12742 +/* {{{ http_request_body *http_request_body_new() */
12743 +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)
12744 +{
12745 + if (!body) {
12746 + body = emalloc_rel(sizeof(http_request_body));
12747 + }
12748 +
12749 + body->type = type;
12750 + body->free = free;
12751 + body->priv = 0;
12752 + body->data = data;
12753 + body->size = size;
12754 +
12755 + return body;
12756 +}
12757 +/* }}} */
12758 +
12759 +/* {{{ http_request_body *http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */
12760 +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)
12761 +{
12762 + if (files && (zend_hash_num_elements(files) > 0)) {
12763 + struct curl_httppost *http_post_data[2] = {NULL, NULL};
12764 +
12765 + if (fields && SUCCESS != recursive_fields(http_post_data, fields, NULL TSRMLS_CC)) {
12766 + return NULL;
12767 + }
12768 + if (SUCCESS != recursive_files(http_post_data, files, NULL TSRMLS_CC)) {
12769 + return NULL;
12770 + }
12771 + return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CURLPOST, http_post_data[0], 0, 1);
12772 + } else if (fields) {
12773 + char *encoded;
12774 + size_t encoded_len;
12775 +
12776 + if (SUCCESS != http_urlencode_hash_ex(fields, 1, NULL, 0, &encoded, &encoded_len)) {
12777 + http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post data");
12778 + return NULL;
12779 + }
12780 +
12781 + return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, encoded, encoded_len, 1);
12782 + } else {
12783 + return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, estrndup("", 0), 0, 1);
12784 + }
12785 +}
12786 +
12787 +/* STATUS http_request_body_encode(http_request_body *, char**, size_t *) */
12788 +PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC)
12789 +{
12790 + switch (body->type) {
12791 + case HTTP_REQUEST_BODY_CURLPOST:
12792 + {
12793 +#ifdef HAVE_CURL_FORMGET
12794 + phpstr str;
12795 +
12796 + phpstr_init_ex(&str, 0x8000, 0);
12797 + if (curl_formget(body->data, &str, (curl_formget_callback) phpstr_append)) {
12798 + phpstr_dtor(&str);
12799 + } else {
12800 + phpstr_fix(&str);
12801 + *buf = PHPSTR_VAL(&str);
12802 + *len = PHPSTR_LEN(&str);
12803 + return SUCCESS;
12804 + }
12805 +#endif
12806 + break;
12807 + }
12808 +
12809 + case HTTP_REQUEST_BODY_CSTRING:
12810 + *buf = estrndup(body->data, *len = body->size);
12811 + return SUCCESS;
12812 +
12813 + default:
12814 + break;
12815 + }
12816 + return FAILURE;
12817 +}
12818 +/* }}} */
12819 +
12820 +/* {{{ void http_request_body_dtor(http_request_body *) */
12821 +PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC)
12822 +{
12823 + if (body) {
12824 + if (body->free) {
12825 + switch (body->type) {
12826 + case HTTP_REQUEST_BODY_CSTRING:
12827 + if (body->data) {
12828 + efree(body->data);
12829 + }
12830 + break;
12831 +
12832 + case HTTP_REQUEST_BODY_CURLPOST:
12833 + curl_formfree(body->data);
12834 + break;
12835 +
12836 + case HTTP_REQUEST_BODY_UPLOADFILE:
12837 + php_stream_close(body->data);
12838 + break;
12839 + }
12840 + }
12841 + memset(body, 0, sizeof(http_request_body));
12842 + }
12843 +}
12844 +/* }}} */
12845 +
12846 +/* {{{ void http_request_body_free(http_request_body *) */
12847 +PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC)
12848 +{
12849 + if (*body) {
12850 + http_request_body_dtor(*body);
12851 + efree(*body);
12852 + *body = NULL;
12853 + }
12854 +}
12855 +/* }}} */
12856 +
12857 +static inline char *format_key(uint type, char *str, ulong num, const char *prefix, int numeric_key_for_empty_prefix) {
12858 + char *new_key = NULL;
12859 +
12860 + if (prefix && *prefix) {
12861 + if (type == HASH_KEY_IS_STRING) {
12862 + spprintf(&new_key, 0, "%s[%s]", prefix, str);
12863 + } else {
12864 + spprintf(&new_key, 0, "%s[%lu]", prefix, num);
12865 + }
12866 + } else if (type == HASH_KEY_IS_STRING) {
12867 + new_key = estrdup(str);
12868 + } else if (numeric_key_for_empty_prefix) {
12869 + spprintf(&new_key, 0, "%lu", num);
12870 + }
12871 +
12872 + return new_key;
12873 +}
12874 +
12875 +/* {{{ static STATUS recursive_fields(post_data d, HashTable *f, const char *p TSRMLS_DC) */
12876 +static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC) {
12877 + HashKey key = initHashKey(0);
12878 + zval **data_ptr;
12879 + HashPosition pos;
12880 + char *new_key = NULL;
12881 + CURLcode err = 0;
12882 +
12883 + if (fields && !fields->nApplyCount) {
12884 + FOREACH_HASH_KEYVAL(pos, fields, key, data_ptr) {
12885 + if (key.type != HASH_KEY_IS_STRING || *key.str) {
12886 + new_key = format_key(key.type, key.str, key.num, prefix, 1);
12887 +
12888 + switch (Z_TYPE_PP(data_ptr)) {
12889 + case IS_ARRAY:
12890 + case IS_OBJECT: {
12891 + STATUS status;
12892 +
12893 + ++fields->nApplyCount;
12894 + status = recursive_fields(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC);
12895 + --fields->nApplyCount;
12896 +
12897 + if (SUCCESS != status) {
12898 + goto error;
12899 + }
12900 + break;
12901 + }
12902 +
12903 + default: {
12904 + zval *data = http_zsep(IS_STRING, *data_ptr);
12905 +
12906 + err = curl_formadd(&http_post_data[0], &http_post_data[1],
12907 + CURLFORM_COPYNAME, new_key,
12908 + CURLFORM_COPYCONTENTS, Z_STRVAL_P(data),
12909 + CURLFORM_CONTENTSLENGTH, (long) Z_STRLEN_P(data),
12910 + CURLFORM_END
12911 + );
12912 +
12913 + zval_ptr_dtor(&data);
12914 +
12915 + if (CURLE_OK != err) {
12916 + goto error;
12917 + }
12918 + break;
12919 + }
12920 + }
12921 + STR_FREE(new_key);
12922 + }
12923 + }
12924 + }
12925 +
12926 + return SUCCESS;
12927 +
12928 +error:
12929 + if (new_key) {
12930 + efree(new_key);
12931 + }
12932 + if (http_post_data[0]) {
12933 + curl_formfree(http_post_data[0]);
12934 + }
12935 + if (err) {
12936 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: %s", curl_easy_strerror(err));
12937 + } else {
12938 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: unknown error");
12939 + }
12940 + return FAILURE;
12941 +}
12942 +/* }}} */
12943 +
12944 +/* {{{ static STATUS recursive_files(post_data d, HashTable *f, const char *p TSRMLS_DC) */
12945 +static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC) {
12946 + HashKey key = initHashKey(0);
12947 + zval **data_ptr;
12948 + HashPosition pos;
12949 + char *new_key = NULL;
12950 + CURLcode err = 0;
12951 +
12952 + if (files && !files->nApplyCount) {
12953 + FOREACH_HASH_KEYVAL(pos, files, key, data_ptr) {
12954 + zval **file_ptr, **type_ptr, **name_ptr;
12955 +
12956 + if (key.type != HASH_KEY_IS_STRING || *key.str) {
12957 + new_key = format_key(key.type, key.str, key.num, prefix, 0);
12958 +
12959 + if (Z_TYPE_PP(data_ptr) != IS_ARRAY && Z_TYPE_PP(data_ptr) != IS_OBJECT) {
12960 + if (new_key || key.type == HASH_KEY_IS_STRING) {
12961 + http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%s'", new_key ? new_key : key.str);
12962 + } else {
12963 + http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%lu'", key.num);
12964 + }
12965 + } else if ( SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "name", sizeof("name"), (void *) &name_ptr) ||
12966 + SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "type", sizeof("type"), (void *) &type_ptr) ||
12967 + SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "file", sizeof("file"), (void *) &file_ptr)) {
12968 + STATUS status;
12969 +
12970 + ++files->nApplyCount;
12971 + status = recursive_files(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC);
12972 + --files->nApplyCount;
12973 +
12974 + if (SUCCESS != status) {
12975 + goto error;
12976 + }
12977 + } else {
12978 + const char *path;
12979 + zval *file = http_zsep(IS_STRING, *file_ptr);
12980 + zval *type = http_zsep(IS_STRING, *type_ptr);
12981 + zval *name = http_zsep(IS_STRING, *name_ptr);
12982 +
12983 + HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(file), goto error);
12984 +
12985 + /* this is blatant but should be sufficient for most cases */
12986 + if (strncasecmp(Z_STRVAL_P(file), "file://", lenof("file://"))) {
12987 + path = Z_STRVAL_P(file);
12988 + } else {
12989 + path = Z_STRVAL_P(file) + lenof("file://");
12990 + }
12991 +
12992 + if (new_key) {
12993 + char *tmp_key = format_key(HASH_KEY_IS_STRING, Z_STRVAL_P(name), 0, new_key, 0);
12994 + STR_SET(new_key, tmp_key);
12995 + }
12996 +
12997 + err = curl_formadd(&http_post_data[0], &http_post_data[1],
12998 + CURLFORM_COPYNAME, new_key ? new_key : Z_STRVAL_P(name),
12999 + CURLFORM_FILE, path,
13000 + CURLFORM_CONTENTTYPE, Z_STRVAL_P(type),
13001 + CURLFORM_END
13002 + );
13003 +
13004 + zval_ptr_dtor(&file);
13005 + zval_ptr_dtor(&type);
13006 + zval_ptr_dtor(&name);
13007 +
13008 + if (CURLE_OK != err) {
13009 + goto error;
13010 + }
13011 + }
13012 + STR_FREE(new_key);
13013 + }
13014 + }
13015 + }
13016 +
13017 + return SUCCESS;
13018 +
13019 +error:
13020 + if (new_key) {
13021 + efree(new_key);
13022 + }
13023 + if (http_post_data[0]) {
13024 + curl_formfree(http_post_data[0]);
13025 + }
13026 + if (err) {
13027 + http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: %s", curl_easy_strerror(err));
13028 + } else {
13029 + http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: unknown error");
13030 + }
13031 + return FAILURE;
13032 +}
13033 +/* }}} */
13034 +
13035 +#endif /* HTTP_HAVE_CURL */
13036 +
13037 +/*
13038 + * Local variables:
13039 + * tab-width: 4
13040 + * c-basic-offset: 4
13041 + * End:
13042 + * vim600: noet sw=4 ts=4 fdm=marker
13043 + * vim<600: noet sw=4 ts=4
13044 + */
13045 --- /dev/null
13046 +++ b/ext/http/http_request_datashare_api.c
13047 @@ -0,0 +1,288 @@
13048 +/*
13049 + +--------------------------------------------------------------------+
13050 + | PECL :: http |
13051 + +--------------------------------------------------------------------+
13052 + | Redistribution and use in source and binary forms, with or without |
13053 + | modification, are permitted provided that the conditions mentioned |
13054 + | in the accompanying LICENSE file are met. |
13055 + +--------------------------------------------------------------------+
13056 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
13057 + +--------------------------------------------------------------------+
13058 +*/
13059 +
13060 +/* $Id: http_request_datashare_api.c 292841 2009-12-31 08:48:57Z mike $ */
13061 +
13062 +#define HTTP_WANT_CURL
13063 +#include "php_http.h"
13064 +
13065 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
13066 +
13067 +#include "php_http_api.h"
13068 +#include "php_http_persistent_handle_api.h"
13069 +#include "php_http_request_datashare_api.h"
13070 +#include "php_http_request_api.h"
13071 +#include "php_http_request_object.h"
13072 +
13073 +static HashTable http_request_datashare_options;
13074 +static http_request_datashare http_request_datashare_global;
13075 +static int http_request_datashare_compare_handles(void *h1, void *h2);
13076 +static void http_request_datashare_destroy_handles(void *el);
13077 +#ifdef ZTS
13078 +static void *http_request_datashare_locks_init(void);
13079 +static void http_request_datashare_locks_dtor(void *l);
13080 +static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr);
13081 +static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr);
13082 +#endif
13083 +
13084 +http_request_datashare *_http_request_datashare_global_get(void)
13085 +{
13086 + return &http_request_datashare_global;
13087 +}
13088 +
13089 +PHP_MINIT_FUNCTION(http_request_datashare)
13090 +{
13091 + curl_lock_data val;
13092 +
13093 + if (SUCCESS != http_persistent_handle_provide("http_request_datashare", curl_share_init, (http_persistent_handle_dtor) curl_share_cleanup, NULL)) {
13094 + return FAILURE;
13095 + }
13096 +#ifdef ZTS
13097 + if (SUCCESS != http_persistent_handle_provide("http_request_datashare_lock", http_request_datashare_locks_init, http_request_datashare_locks_dtor, NULL)) {
13098 + return FAILURE;
13099 + }
13100 +#endif
13101 +
13102 + if (!http_request_datashare_init_ex(&http_request_datashare_global, 1)) {
13103 + return FAILURE;
13104 + }
13105 +
13106 + zend_hash_init(&http_request_datashare_options, 4, NULL, NULL, 1);
13107 +#define ADD_DATASHARE_OPT(name, opt) \
13108 + val = opt; \
13109 + zend_hash_add(&http_request_datashare_options, name, sizeof(name), &val, sizeof(curl_lock_data), NULL)
13110 + ADD_DATASHARE_OPT("cookie", CURL_LOCK_DATA_COOKIE);
13111 + ADD_DATASHARE_OPT("dns", CURL_LOCK_DATA_DNS);
13112 + ADD_DATASHARE_OPT("ssl", CURL_LOCK_DATA_SSL_SESSION);
13113 + ADD_DATASHARE_OPT("connect", CURL_LOCK_DATA_CONNECT);
13114 +
13115 + return SUCCESS;
13116 +}
13117 +
13118 +PHP_MSHUTDOWN_FUNCTION(http_request_datashare)
13119 +{
13120 + http_request_datashare_dtor(&http_request_datashare_global);
13121 + zend_hash_destroy(&http_request_datashare_options);
13122 +
13123 + return SUCCESS;
13124 +}
13125 +
13126 +PHP_RINIT_FUNCTION(http_request_datashare)
13127 +{
13128 + zend_llist_init(&HTTP_G->request.datashare.handles, sizeof(zval *), http_request_datashare_destroy_handles, 0);
13129 +
13130 + return SUCCESS;
13131 +}
13132 +
13133 +PHP_RSHUTDOWN_FUNCTION(http_request_datashare)
13134 +{
13135 + zend_llist_destroy(&HTTP_G->request.datashare.handles);
13136 +
13137 + return SUCCESS;
13138 +}
13139 +
13140 +PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC)
13141 +{
13142 + zend_bool free_share;
13143 +
13144 + if ((free_share = !share)) {
13145 + share = pemalloc(sizeof(http_request_datashare), persistent);
13146 + }
13147 + memset(share, 0, sizeof(http_request_datashare));
13148 +
13149 + if (SUCCESS != http_persistent_handle_acquire("http_request_datashare", &share->ch)) {
13150 + if (free_share) {
13151 + pefree(share, persistent);
13152 + }
13153 + return NULL;
13154 + }
13155 +
13156 + if (!(share->persistent = persistent)) {
13157 + share->handle.list = emalloc(sizeof(zend_llist));
13158 + zend_llist_init(share->handle.list, sizeof(zval *), ZVAL_PTR_DTOR, 0);
13159 +#ifdef ZTS
13160 + } else {
13161 + if (SUCCESS == http_persistent_handle_acquire("http_request_datashare_lock", (void *) &share->handle.locks)) {
13162 + curl_share_setopt(share->ch, CURLSHOPT_LOCKFUNC, http_request_datashare_lock_func);
13163 + curl_share_setopt(share->ch, CURLSHOPT_UNLOCKFUNC, http_request_datashare_unlock_func);
13164 + curl_share_setopt(share->ch, CURLSHOPT_USERDATA, share->handle.locks);
13165 + }
13166 +#endif
13167 + }
13168 +
13169 + return share;
13170 +}
13171 +
13172 +PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC)
13173 +{
13174 + CURLcode rc;
13175 + getObjectEx(http_request_object, obj, request);
13176 +
13177 + if (obj->share) {
13178 + if (obj->share == share) {
13179 + return SUCCESS;
13180 + } else if (SUCCESS != http_request_datashare_detach(obj->share, request)) {
13181 + return FAILURE;
13182 + }
13183 + }
13184 +
13185 + HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init_ex(obj->request->ch, obj->request), return FAILURE);
13186 + if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, share->ch))) {
13187 + 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));
13188 + return FAILURE;
13189 + }
13190 +
13191 + obj->share = share;
13192 + ZVAL_ADDREF(request);
13193 + zend_llist_add_element(HTTP_RSHARE_HANDLES(share), (void *) &request);
13194 +
13195 + return SUCCESS;
13196 +}
13197 +
13198 +PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC)
13199 +{
13200 + CURLcode rc;
13201 + getObjectEx(http_request_object, obj, request);
13202 +
13203 + if (!obj->share) {
13204 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to any HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
13205 + } else if (obj->share != share) {
13206 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to this HttpRequestDataShare", Z_OBJ_HANDLE_P(request));
13207 + } else if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL))) {
13208 + 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));
13209 + } else {
13210 + obj->share = NULL;
13211 + zend_llist_del_element(HTTP_RSHARE_HANDLES(share), request, http_request_datashare_compare_handles);
13212 + return SUCCESS;
13213 + }
13214 + return FAILURE;
13215 +}
13216 +
13217 +PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC)
13218 +{
13219 + zval **r;
13220 +
13221 + while ((r = zend_llist_get_first(HTTP_RSHARE_HANDLES(share)))) {
13222 + http_request_datashare_detach(share, *r);
13223 + }
13224 +}
13225 +
13226 +PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC)
13227 +{
13228 + if (!share->persistent) {
13229 + zend_llist_destroy(share->handle.list);
13230 + efree(share->handle.list);
13231 + }
13232 + http_persistent_handle_release("http_request_datashare", &share->ch);
13233 +#ifdef ZTS
13234 + if (share->persistent) {
13235 + http_persistent_handle_release("http_request_datashare_lock", (void *) &share->handle.locks);
13236 + }
13237 +#endif
13238 +}
13239 +
13240 +PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC)
13241 +{
13242 + http_request_datashare_dtor(*share);
13243 + pefree(*share, (*share)->persistent);
13244 + *share = NULL;
13245 +}
13246 +
13247 +PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC)
13248 +{
13249 + curl_lock_data *opt;
13250 + CURLSHcode rc;
13251 +
13252 + if (SUCCESS == zend_hash_find(&http_request_datashare_options, (char *) option, option_len + 1, (void *) &opt)) {
13253 + if (CURLSHE_OK == (rc = curl_share_setopt(share->ch, enable ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, *opt))) {
13254 + return SUCCESS;
13255 + }
13256 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not %s sharing of %s data: %s", enable ? "enable" : "disable", option, curl_share_strerror(rc));
13257 + }
13258 + return FAILURE;
13259 +}
13260 +
13261 +static int http_request_datashare_compare_handles(void *h1, void *h2)
13262 +{
13263 + return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
13264 +}
13265 +
13266 +static void http_request_datashare_destroy_handles(void *el)
13267 +{
13268 + zval **r = (zval **) el;
13269 + TSRMLS_FETCH();
13270 +
13271 + { /* gcc 2.95 needs these braces */
13272 + getObjectEx(http_request_object, obj, *r);
13273 +
13274 + curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL);
13275 + zval_ptr_dtor(r);
13276 + }
13277 +}
13278 +
13279 +#ifdef ZTS
13280 +static void *http_request_datashare_locks_init(void)
13281 +{
13282 + int i;
13283 + http_request_datashare_lock *locks = pecalloc(CURL_LOCK_DATA_LAST, sizeof(http_request_datashare_lock), 1);
13284 +
13285 + if (locks) {
13286 + for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
13287 + locks[i].mx = tsrm_mutex_alloc();
13288 + }
13289 + }
13290 +
13291 + return locks;
13292 +}
13293 +
13294 +static void http_request_datashare_locks_dtor(void *l)
13295 +{
13296 + int i;
13297 + http_request_datashare_lock *locks = (http_request_datashare_lock *) l;
13298 +
13299 + for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) {
13300 + tsrm_mutex_free(locks[i].mx);
13301 + }
13302 + pefree(locks, 1);
13303 +}
13304 +
13305 +static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr)
13306 +{
13307 + http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
13308 +
13309 + /* TSRM can't distinguish shared/exclusive locks */
13310 + tsrm_mutex_lock(locks[data].mx);
13311 + locks[data].ch = handle;
13312 +}
13313 +
13314 +static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr)
13315 +{
13316 + http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr;
13317 +
13318 + if (locks[data].ch == handle) {
13319 + tsrm_mutex_unlock(locks[data].mx);
13320 + }
13321 +}
13322 +#endif
13323 +
13324 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
13325 +
13326 +
13327 +/*
13328 + * Local variables:
13329 + * tab-width: 4
13330 + * c-basic-offset: 4
13331 + * End:
13332 + * vim600: noet sw=4 ts=4 fdm=marker
13333 + * vim<600: noet sw=4 ts=4
13334 + */
13335 +
13336 --- /dev/null
13337 +++ b/ext/http/http_request_info.c
13338 @@ -0,0 +1,213 @@
13339 +/*
13340 + +--------------------------------------------------------------------+
13341 + | PECL :: http |
13342 + +--------------------------------------------------------------------+
13343 + | Redistribution and use in source and binary forms, with or without |
13344 + | modification, are permitted provided that the conditions mentioned |
13345 + | in the accompanying LICENSE file are met. |
13346 + +--------------------------------------------------------------------+
13347 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
13348 + +--------------------------------------------------------------------+
13349 +*/
13350 +
13351 +/* $Id: http_request_info.c 323304 2012-02-17 21:13:24Z mike $ */
13352 +
13353 +#define HTTP_WANT_CURL
13354 +#include "php_http.h"
13355 +
13356 +#ifdef HTTP_HAVE_CURL
13357 +#include "php_http_request_api.h"
13358 +
13359 +/* {{{ void http_request_info(http_request *, HashTable *) */
13360 +PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info)
13361 +{
13362 + char *c;
13363 + long l;
13364 + double d;
13365 + struct curl_slist *s, *p;
13366 + zval *subarray, array;
13367 + INIT_ZARR(array, info);
13368 +
13369 + /* BEGIN */
13370 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_EFFECTIVE_URL, &c)) {
13371 + add_assoc_string_ex(&array, "effective_url", sizeof("effective_url"), c ? c : "", 1);
13372 + }
13373 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_RESPONSE_CODE, &l)) {
13374 + add_assoc_long_ex(&array, "response_code", sizeof("response_code"), l);
13375 + }
13376 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_TOTAL_TIME, &d)) {
13377 + add_assoc_double_ex(&array, "total_time", sizeof("total_time"), d);
13378 + }
13379 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NAMELOOKUP_TIME, &d)) {
13380 + add_assoc_double_ex(&array, "namelookup_time", sizeof("namelookup_time"), d);
13381 + }
13382 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONNECT_TIME, &d)) {
13383 + add_assoc_double_ex(&array, "connect_time", sizeof("connect_time"), d);
13384 + }
13385 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRETRANSFER_TIME, &d)) {
13386 + add_assoc_double_ex(&array, "pretransfer_time", sizeof("pretransfer_time"), d);
13387 + }
13388 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_UPLOAD, &d)) {
13389 + add_assoc_double_ex(&array, "size_upload", sizeof("size_upload"), d);
13390 + }
13391 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_DOWNLOAD, &d)) {
13392 + add_assoc_double_ex(&array, "size_download", sizeof("size_download"), d);
13393 + }
13394 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_DOWNLOAD, &d)) {
13395 + add_assoc_double_ex(&array, "speed_download", sizeof("speed_download"), d);
13396 + }
13397 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_UPLOAD, &d)) {
13398 + add_assoc_double_ex(&array, "speed_upload", sizeof("speed_upload"), d);
13399 + }
13400 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HEADER_SIZE, &l)) {
13401 + add_assoc_long_ex(&array, "header_size", sizeof("header_size"), l);
13402 + }
13403 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REQUEST_SIZE, &l)) {
13404 + add_assoc_long_ex(&array, "request_size", sizeof("request_size"), l);
13405 + }
13406 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_VERIFYRESULT, &l)) {
13407 + add_assoc_long_ex(&array, "ssl_verifyresult", sizeof("ssl_verifyresult"), l);
13408 + }
13409 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_FILETIME, &l)) {
13410 + add_assoc_long_ex(&array, "filetime", sizeof("filetime"), l);
13411 + }
13412 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) {
13413 + add_assoc_double_ex(&array, "content_length_download", sizeof("content_length_download"), d);
13414 + }
13415 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_UPLOAD, &d)) {
13416 + add_assoc_double_ex(&array, "content_length_upload", sizeof("content_length_upload"), d);
13417 + }
13418 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_STARTTRANSFER_TIME, &d)) {
13419 + add_assoc_double_ex(&array, "starttransfer_time", sizeof("starttransfer_time"), d);
13420 + }
13421 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_TYPE, &c)) {
13422 + add_assoc_string_ex(&array, "content_type", sizeof("content_type"), c ? c : "", 1);
13423 + }
13424 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_TIME, &d)) {
13425 + add_assoc_double_ex(&array, "redirect_time", sizeof("redirect_time"), d);
13426 + }
13427 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_COUNT, &l)) {
13428 + add_assoc_long_ex(&array, "redirect_count", sizeof("redirect_count"), l);
13429 + }
13430 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTP_CONNECTCODE, &l)) {
13431 + add_assoc_long_ex(&array, "connect_code", sizeof("connect_code"), l);
13432 + }
13433 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTPAUTH_AVAIL, &l)) {
13434 + add_assoc_long_ex(&array, "httpauth_avail", sizeof("httpauth_avail"), l);
13435 + }
13436 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PROXYAUTH_AVAIL, &l)) {
13437 + add_assoc_long_ex(&array, "proxyauth_avail", sizeof("proxyauth_avail"), l);
13438 + }
13439 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_OS_ERRNO, &l)) {
13440 + add_assoc_long_ex(&array, "os_errno", sizeof("os_errno"), l);
13441 + }
13442 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NUM_CONNECTS, &l)) {
13443 + add_assoc_long_ex(&array, "num_connects", sizeof("num_connects"), l);
13444 + }
13445 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_ENGINES, &s)) {
13446 + MAKE_STD_ZVAL(subarray);
13447 + array_init(subarray);
13448 + for (p = s; p; p = p->next) {
13449 + if (p->data) {
13450 + add_next_index_string(subarray, p->data, 1);
13451 + }
13452 + }
13453 + add_assoc_zval_ex(&array, "ssl_engines", sizeof("ssl_engines"), subarray);
13454 + curl_slist_free_all(s);
13455 + }
13456 +#if HTTP_CURL_VERSION(7,14,1)
13457 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_COOKIELIST, &s)) {
13458 + MAKE_STD_ZVAL(subarray);
13459 + array_init(subarray);
13460 + for (p = s; p; p = p->next) {
13461 + if (p->data) {
13462 + add_next_index_string(subarray, p->data, 1);
13463 + }
13464 + }
13465 + add_assoc_zval_ex(&array, "cookies", sizeof("cookies"), subarray);
13466 + curl_slist_free_all(s);
13467 + }
13468 +#endif
13469 +#if HTTP_CURL_VERSION(7,18,2)
13470 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_URL, &c)) {
13471 + add_assoc_string_ex(&array, "redirect_url", sizeof("redirect_url"), c ? c : "", 1);
13472 + }
13473 +#endif
13474 +#if HTTP_CURL_VERSION(7,19,0)
13475 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRIMARY_IP, &c)) {
13476 + add_assoc_string_ex(&array, "primary_ip", sizeof("primary_ip"), c ? c : "", 1);
13477 + }
13478 +#endif
13479 +#if HTTP_CURL_VERSION(7,19,0)
13480 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_APPCONNECT_TIME, &d)) {
13481 + add_assoc_double_ex(&array, "appconnect_time", sizeof("appconnect_time"), d);
13482 + }
13483 +#endif
13484 +#if HTTP_CURL_VERSION(7,19,4)
13485 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONDITION_UNMET, &l)) {
13486 + add_assoc_long_ex(&array, "condition_unmet", sizeof("condition_unmet"), l);
13487 + }
13488 +#endif
13489 +#if HTTP_CURL_VERSION(7,21,0)
13490 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRIMARY_PORT, &l)) {
13491 + add_assoc_long_ex(&array, "primary_port", sizeof("primary_port"), l);
13492 + }
13493 +#endif
13494 +#if HTTP_CURL_VERSION(7,21,0)
13495 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_LOCAL_IP, &c)) {
13496 + add_assoc_string_ex(&array, "local_ip", sizeof("local_ip"), c ? c : "", 1);
13497 + }
13498 +#endif
13499 +#if HTTP_CURL_VERSION(7,21,0)
13500 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_LOCAL_PORT, &l)) {
13501 + add_assoc_long_ex(&array, "local_port", sizeof("local_port"), l);
13502 + }
13503 +#endif
13504 +/* END */
13505 +#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL)
13506 + {
13507 + int i;
13508 + zval *ci_array;
13509 + struct curl_certinfo *ci;
13510 + char *colon, *keyname;
13511 +
13512 + if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CERTINFO, &ci)) {
13513 + MAKE_STD_ZVAL(ci_array);
13514 + array_init(ci_array);
13515 +
13516 + for (i = 0; i < ci->num_of_certs; ++i) {
13517 + s = ci->certinfo[i];
13518 +
13519 + MAKE_STD_ZVAL(subarray);
13520 + array_init(subarray);
13521 + for (p = s; p; p = p->next) {
13522 + if (p->data) {
13523 + if ((colon = strchr(p->data, ':'))) {
13524 + keyname = estrndup(p->data, colon - p->data);
13525 + add_assoc_string_ex(subarray, keyname, colon - p->data + 1, colon + 1, 1);
13526 + efree(keyname);
13527 + } else {
13528 + add_next_index_string(subarray, p->data, 1);
13529 + }
13530 + }
13531 + }
13532 + add_next_index_zval(ci_array, subarray);
13533 + }
13534 + add_assoc_zval_ex(&array, "certinfo", sizeof("certinfo"), ci_array);
13535 + }
13536 + }
13537 +#endif
13538 + add_assoc_string_ex(&array, "error", sizeof("error"), http_request_storage_get(request->ch)->errorbuffer, 1);
13539 +}
13540 +/* }}} */
13541 +
13542 +#endif /* HTTP_HAVE_CURL */
13543 +
13544 +/*
13545 + * Local variables:
13546 + * tab-width: 4
13547 + * c-basic-offset: 4
13548 + * End:
13549 + * vim600: noet sw=4 ts=4 fdm=marker
13550 + * vim<600: noet sw=4 ts=4
13551 + */
13552 --- /dev/null
13553 +++ b/ext/http/http_request_method_api.c
13554 @@ -0,0 +1,322 @@
13555 +/*
13556 + +--------------------------------------------------------------------+
13557 + | PECL :: http |
13558 + +--------------------------------------------------------------------+
13559 + | Redistribution and use in source and binary forms, with or without |
13560 + | modification, are permitted provided that the conditions mentioned |
13561 + | in the accompanying LICENSE file are met. |
13562 + +--------------------------------------------------------------------+
13563 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
13564 + +--------------------------------------------------------------------+
13565 +*/
13566 +
13567 +/* $Id: http_request_method_api.c 323406 2012-02-21 10:05:52Z mike $ */
13568 +
13569 +#define HTTP_WANT_CURL
13570 +#include "php_http.h"
13571 +
13572 +#include "php_http_api.h"
13573 +#include "php_http_request_api.h"
13574 +#include "php_http_request_method_api.h"
13575 +
13576 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
13577 +# include "php_http_request_object.h"
13578 +#endif
13579 +
13580 +/* {{{ char *http_request_methods[] */
13581 +static const char *const http_request_methods[] = {
13582 + "UNKNOWN",
13583 + /* HTTP/1.1 */
13584 + "GET",
13585 + "HEAD",
13586 + "POST",
13587 + "PUT",
13588 + "DELETE",
13589 + "OPTIONS",
13590 + "TRACE",
13591 + "CONNECT",
13592 + /* WebDAV - RFC 2518 */
13593 + "PROPFIND",
13594 + "PROPPATCH",
13595 + "MKCOL",
13596 + "COPY",
13597 + "MOVE",
13598 + "LOCK",
13599 + "UNLOCK",
13600 + /* WebDAV Versioning - RFC 3253 */
13601 + "VERSION-CONTROL",
13602 + "REPORT",
13603 + "CHECKOUT",
13604 + "CHECKIN",
13605 + "UNCHECKOUT",
13606 + "MKWORKSPACE",
13607 + "UPDATE",
13608 + "LABEL",
13609 + "MERGE",
13610 + "BASELINE-CONTROL",
13611 + "MKACTIVITY",
13612 + /* WebDAV Access Control - RFC 3744 */
13613 + "ACL",
13614 + NULL
13615 +};
13616 +/* }}} */
13617 +
13618 +/* {{{ */
13619 +PHP_MINIT_FUNCTION(http_request_method)
13620 +{
13621 + /* HTTP/1.1 */
13622 + HTTP_LONG_CONSTANT("HTTP_METH_GET", HTTP_GET);
13623 + HTTP_LONG_CONSTANT("HTTP_METH_HEAD", HTTP_HEAD);
13624 + HTTP_LONG_CONSTANT("HTTP_METH_POST", HTTP_POST);
13625 + HTTP_LONG_CONSTANT("HTTP_METH_PUT", HTTP_PUT);
13626 + HTTP_LONG_CONSTANT("HTTP_METH_DELETE", HTTP_DELETE);
13627 + HTTP_LONG_CONSTANT("HTTP_METH_OPTIONS", HTTP_OPTIONS);
13628 + HTTP_LONG_CONSTANT("HTTP_METH_TRACE", HTTP_TRACE);
13629 + HTTP_LONG_CONSTANT("HTTP_METH_CONNECT", HTTP_CONNECT);
13630 + /* WebDAV - RFC 2518 */
13631 + HTTP_LONG_CONSTANT("HTTP_METH_PROPFIND", HTTP_PROPFIND);
13632 + HTTP_LONG_CONSTANT("HTTP_METH_PROPPATCH", HTTP_PROPPATCH);
13633 + HTTP_LONG_CONSTANT("HTTP_METH_MKCOL", HTTP_MKCOL);
13634 + HTTP_LONG_CONSTANT("HTTP_METH_COPY", HTTP_COPY);
13635 + HTTP_LONG_CONSTANT("HTTP_METH_MOVE", HTTP_MOVE);
13636 + HTTP_LONG_CONSTANT("HTTP_METH_LOCK", HTTP_LOCK);
13637 + HTTP_LONG_CONSTANT("HTTP_METH_UNLOCK", HTTP_UNLOCK);
13638 + /* WebDAV Versioning - RFC 3253 */
13639 + HTTP_LONG_CONSTANT("HTTP_METH_VERSION_CONTROL", HTTP_VERSION_CONTROL);
13640 + HTTP_LONG_CONSTANT("HTTP_METH_REPORT", HTTP_REPORT);
13641 + HTTP_LONG_CONSTANT("HTTP_METH_CHECKOUT", HTTP_CHECKOUT);
13642 + HTTP_LONG_CONSTANT("HTTP_METH_CHECKIN", HTTP_CHECKIN);
13643 + HTTP_LONG_CONSTANT("HTTP_METH_UNCHECKOUT", HTTP_UNCHECKOUT);
13644 + HTTP_LONG_CONSTANT("HTTP_METH_MKWORKSPACE", HTTP_MKWORKSPACE);
13645 + HTTP_LONG_CONSTANT("HTTP_METH_UPDATE", HTTP_UPDATE);
13646 + HTTP_LONG_CONSTANT("HTTP_METH_LABEL", HTTP_LABEL);
13647 + HTTP_LONG_CONSTANT("HTTP_METH_MERGE", HTTP_MERGE);
13648 + HTTP_LONG_CONSTANT("HTTP_METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL);
13649 + HTTP_LONG_CONSTANT("HTTP_METH_MKACTIVITY", HTTP_MKACTIVITY);
13650 + /* WebDAV Access Control - RFC 3744 */
13651 + HTTP_LONG_CONSTANT("HTTP_METH_ACL", HTTP_ACL);
13652 +
13653 + return SUCCESS;
13654 +}
13655 +
13656 +static void free_method(void *el)
13657 +{
13658 + efree(*(char **)el);
13659 +}
13660 +
13661 +static void unregister_method(const char *name TSRMLS_DC)
13662 +{
13663 + char *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_";
13664 +
13665 + strlcpy(tmp + lenof("HTTP_METH_"), name, HTTP_REQUEST_METHOD_MAXLEN);
13666 + for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) {
13667 + if (*ptr == '-') {
13668 + *ptr = '_';
13669 + }
13670 + }
13671 +
13672 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
13673 + if (SUCCESS != zend_hash_del(&http_request_object_ce->constants_table, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")) + 1)) {
13674 + http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: HttpRequest::%s", tmp + lenof("HTTP_"));
13675 + }
13676 +#endif
13677 + if (SUCCESS != zend_hash_del(EG(zend_constants), tmp, strlen(tmp) + 1)) {
13678 + http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: %s", tmp);
13679 + }
13680 +}
13681 +
13682 +PHP_RINIT_FUNCTION(http_request_method)
13683 +{
13684 + HashTable ht;
13685 +
13686 + zend_hash_init(&HTTP_G->request.methods.registered, 0, NULL, free_method, 0);
13687 +#define HTTP_METH_REG(m) \
13688 + { \
13689 + char *_m=estrdup(m); \
13690 + zend_hash_next_index_insert(&HTTP_G->request.methods.registered, (void *) &_m, sizeof(char *), NULL); \
13691 + }
13692 + HTTP_METH_REG("UNKNOWN");
13693 + /* HTTP/1.1 */
13694 + HTTP_METH_REG("GET");
13695 + HTTP_METH_REG("HEAD");
13696 + HTTP_METH_REG("POST");
13697 + HTTP_METH_REG("PUT");
13698 + HTTP_METH_REG("DELETE");
13699 + HTTP_METH_REG("OPTIONS");
13700 + HTTP_METH_REG("TRACE");
13701 + HTTP_METH_REG("CONNECT");
13702 + /* WebDAV - RFC 2518 */
13703 + HTTP_METH_REG("PROPFIND");
13704 + HTTP_METH_REG("PROPPATCH");
13705 + HTTP_METH_REG("MKCOL");
13706 + HTTP_METH_REG("COPY");
13707 + HTTP_METH_REG("MOVE");
13708 + HTTP_METH_REG("LOCK");
13709 + HTTP_METH_REG("UNLOCK");
13710 + /* WebDAV Versioning - RFC 3253 */
13711 + HTTP_METH_REG("VERSION-CONTROL");
13712 + HTTP_METH_REG("REPORT");
13713 + HTTP_METH_REG("CHECKOUT");
13714 + HTTP_METH_REG("CHECKIN");
13715 + HTTP_METH_REG("UNCHECKOUT");
13716 + HTTP_METH_REG("MKWORKSPACE");
13717 + HTTP_METH_REG("UPDATE");
13718 + HTTP_METH_REG("LABEL");
13719 + HTTP_METH_REG("MERGE");
13720 + HTTP_METH_REG("BASELINE-CONTROL");
13721 + HTTP_METH_REG("MKACTIVITY");
13722 + /* WebDAV Access Control - RFC 3744 */
13723 + HTTP_METH_REG("ACL");
13724 +
13725 + zend_hash_init(&ht, 0, NULL, ZVAL_PTR_DTOR, 0);
13726 + if (*HTTP_G->request.methods.custom && SUCCESS == http_parse_params(HTTP_G->request.methods.custom, HTTP_PARAMS_DEFAULT, &ht)) {
13727 + HashPosition pos;
13728 + zval **val;
13729 +
13730 + FOREACH_HASH_VAL(pos, &ht, val) {
13731 + if (Z_TYPE_PP(val) == IS_STRING) {
13732 + http_request_method_register(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
13733 + }
13734 + }
13735 + }
13736 + zend_hash_destroy(&ht);
13737 +
13738 + return SUCCESS;
13739 +}
13740 +
13741 +PHP_RSHUTDOWN_FUNCTION(http_request_method)
13742 +{
13743 + char **name;
13744 + int i, c = zend_hash_next_free_element(&HTTP_G->request.methods.registered);
13745 +
13746 + for (i = HTTP_MAX_REQUEST_METHOD; i < c; ++i) {
13747 + if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, i, (void *) &name)) {
13748 + unregister_method(*name TSRMLS_CC);
13749 + }
13750 + }
13751 +
13752 + zend_hash_destroy(&HTTP_G->request.methods.registered);
13753 + return SUCCESS;
13754 +}
13755 +
13756 +#define http_request_method_cncl(m, c) _http_request_method_cncl_ex((m), strlen(m), (c) TSRMLS_CC)
13757 +#define http_request_method_cncl_ex(m, l, c) _http_request_method_cncl_ex((m), (l), (c) TSRMLS_CC)
13758 +static STATUS _http_request_method_cncl_ex(const char *method_name, int method_name_len, char **cnst TSRMLS_DC)
13759 +{
13760 + int i;
13761 + char *cncl;
13762 +
13763 + if (method_name_len >= HTTP_REQUEST_METHOD_MAXLEN) {
13764 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method too long (%s)", method_name);
13765 + }
13766 + cncl = emalloc(method_name_len + 1);
13767 +
13768 + for (i = 0; i < method_name_len; ++i) {
13769 + switch (method_name[i]) {
13770 + case '-':
13771 + case '_':
13772 + cncl[i] = method_name[i];
13773 + break;
13774 +
13775 + default:
13776 + if (!HTTP_IS_CTYPE(alnum, method_name[i])) {
13777 + efree(cncl);
13778 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method contains illegal characters (%s)", method_name);
13779 + return FAILURE;
13780 + }
13781 + cncl[i] = HTTP_TO_CTYPE(upper, method_name[i]);
13782 + break;
13783 + }
13784 + }
13785 + cncl[method_name_len] = '\0';
13786 +
13787 + *cnst = cncl;
13788 + return SUCCESS;
13789 +}
13790 +
13791 +PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC)
13792 +{
13793 + char **name;
13794 +
13795 + if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, m, (void *) &name)) {
13796 + return *name;
13797 + }
13798 + return "UNKNOWN";
13799 +}
13800 +
13801 +PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id_num, const char *id_str TSRMLS_DC)
13802 +{
13803 + char *id_dup;
13804 +
13805 + if (by_name && (SUCCESS == http_request_method_cncl(id_str, &id_dup))) {
13806 + char **name;
13807 + HashPosition pos;
13808 + HashKey key = initHashKey(0);
13809 +
13810 + FOREACH_HASH_KEYVAL(pos, &HTTP_G->request.methods.registered, key, name) {
13811 + if (key.type == HASH_KEY_IS_LONG && !strcmp(*name, id_dup)) {
13812 + efree(id_dup);
13813 + return key.num;
13814 + }
13815 + }
13816 + efree(id_dup);
13817 + } else if (zend_hash_index_exists(&HTTP_G->request.methods.registered, id_num)){
13818 + return id_num;
13819 + }
13820 + return 0;
13821 +}
13822 +
13823 +PHP_HTTP_API int _http_request_method_register(const char *method_str, int method_len TSRMLS_DC)
13824 +{
13825 + char *method_dup, *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_";
13826 + int method_num = http_request_method_exists(1, 0, method_str);
13827 +
13828 + if (!method_num && (SUCCESS == http_request_method_cncl_ex(method_str, method_len, &method_dup))) {
13829 + method_num = zend_hash_next_free_element(&HTTP_G->request.methods.registered);
13830 + zend_hash_index_update(&HTTP_G->request.methods.registered, method_num, (void *) &method_dup, sizeof(char *), NULL);
13831 +
13832 + strlcpy(tmp + lenof("HTTP_METH_"), method_dup, HTTP_REQUEST_METHOD_MAXLEN);
13833 + for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) {
13834 + if (*ptr == '-') {
13835 + *ptr = '_';
13836 + }
13837 + }
13838 +
13839 + zend_register_long_constant(tmp, strlen(tmp) + 1, method_num, CONST_CS, http_module_number TSRMLS_CC);
13840 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
13841 + zend_declare_class_constant_long(http_request_object_ce, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")), method_num TSRMLS_CC);
13842 +#endif
13843 + }
13844 +
13845 + return method_num;
13846 +}
13847 +
13848 +PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC)
13849 +{
13850 + char **name;
13851 +
13852 + if (HTTP_STD_REQUEST_METHOD(method)) {
13853 + http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Standard request methods cannot be unregistered");
13854 + return FAILURE;
13855 + }
13856 +
13857 + if (SUCCESS != zend_hash_index_find(&HTTP_G->request.methods.registered, method, (void *) &name)) {
13858 + http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Custom request method with id %d does not exist", method);
13859 + return FAILURE;
13860 + }
13861 +
13862 + unregister_method(*name TSRMLS_CC);
13863 +
13864 + zend_hash_index_del(&HTTP_G->request.methods.registered, method);
13865 + return SUCCESS;
13866 +}
13867 +
13868 +/*
13869 + * Local variables:
13870 + * tab-width: 4
13871 + * c-basic-offset: 4
13872 + * End:
13873 + * vim600: noet sw=4 ts=4 fdm=marker
13874 + * vim<600: noet sw=4 ts=4
13875 + */
13876 +
13877 --- /dev/null
13878 +++ b/ext/http/http_request_object.c
13879 @@ -0,0 +1,1931 @@
13880 +/*
13881 + +--------------------------------------------------------------------+
13882 + | PECL :: http |
13883 + +--------------------------------------------------------------------+
13884 + | Redistribution and use in source and binary forms, with or without |
13885 + | modification, are permitted provided that the conditions mentioned |
13886 + | in the accompanying LICENSE file are met. |
13887 + +--------------------------------------------------------------------+
13888 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
13889 + +--------------------------------------------------------------------+
13890 +*/
13891 +
13892 +/* $Id: http_request_object.c 323304 2012-02-17 21:13:24Z mike $ */
13893 +
13894 +#define HTTP_WANT_CURL
13895 +#include "php_http.h"
13896 +
13897 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
13898 +
13899 +#include "zend_interfaces.h"
13900 +
13901 +#include "php_http_api.h"
13902 +#include "php_http_cookie_api.h"
13903 +#include "php_http_exception_object.h"
13904 +#include "php_http_message_api.h"
13905 +#include "php_http_message_object.h"
13906 +#include "php_http_request_api.h"
13907 +#include "php_http_request_object.h"
13908 +#include "php_http_request_pool_api.h"
13909 +#include "php_http_url_api.h"
13910 +
13911 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequest, method, 0, req_args)
13912 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequest, method, 0)
13913 +#define HTTP_REQUEST_ME(method, visibility) PHP_ME(HttpRequest, method, HTTP_ARGS(HttpRequest, method), visibility)
13914 +#define HTTP_REQUEST_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpRequest, method))
13915 +#define HTTP_REQUEST_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpRequest_##al), HTTP_ARGS(HttpRequest, al), vis)
13916 +
13917 +HTTP_BEGIN_ARGS(__construct, 0)
13918 + HTTP_ARG_VAL(url, 0)
13919 + HTTP_ARG_VAL(method, 0)
13920 + HTTP_ARG_VAL(options, 0)
13921 +HTTP_END_ARGS;
13922 +
13923 +HTTP_BEGIN_ARGS(factory, 0)
13924 + HTTP_ARG_VAL(url, 0)
13925 + HTTP_ARG_VAL(method, 0)
13926 + HTTP_ARG_VAL(options, 0)
13927 + HTTP_ARG_VAL(class_name, 0)
13928 +HTTP_END_ARGS;
13929 +
13930 +HTTP_EMPTY_ARGS(getOptions);
13931 +HTTP_BEGIN_ARGS(setOptions, 0)
13932 + HTTP_ARG_VAL(options, 0)
13933 +HTTP_END_ARGS;
13934 +
13935 +HTTP_EMPTY_ARGS(getSslOptions);
13936 +HTTP_BEGIN_ARGS(setSslOptions, 0)
13937 + HTTP_ARG_VAL(ssl_options, 0)
13938 +HTTP_END_ARGS;
13939 +
13940 +HTTP_BEGIN_ARGS(addSslOptions, 0)
13941 + HTTP_ARG_VAL(ssl_optins, 0)
13942 +HTTP_END_ARGS;
13943 +
13944 +HTTP_EMPTY_ARGS(getHeaders);
13945 +HTTP_BEGIN_ARGS(setHeaders, 0)
13946 + HTTP_ARG_VAL(headers, 0)
13947 +HTTP_END_ARGS;
13948 +
13949 +HTTP_BEGIN_ARGS(addHeaders, 1)
13950 + HTTP_ARG_VAL(headers, 0)
13951 +HTTP_END_ARGS;
13952 +
13953 +HTTP_EMPTY_ARGS(getCookies);
13954 +HTTP_BEGIN_ARGS(setCookies, 0)
13955 + HTTP_ARG_VAL(cookies, 0)
13956 +HTTP_END_ARGS;
13957 +
13958 +HTTP_BEGIN_ARGS(addCookies, 1)
13959 + HTTP_ARG_VAL(cookies, 0)
13960 +HTTP_END_ARGS;
13961 +
13962 +HTTP_EMPTY_ARGS(enableCookies);
13963 +HTTP_BEGIN_ARGS(resetCookies, 0)
13964 + HTTP_ARG_VAL(session_only, 0)
13965 +HTTP_END_ARGS;
13966 +HTTP_EMPTY_ARGS(flushCookies);
13967 +
13968 +HTTP_EMPTY_ARGS(getUrl);
13969 +HTTP_BEGIN_ARGS(setUrl, 1)
13970 + HTTP_ARG_VAL(url, 0)
13971 +HTTP_END_ARGS;
13972 +
13973 +HTTP_EMPTY_ARGS(getMethod);
13974 +HTTP_BEGIN_ARGS(setMethod, 1)
13975 + HTTP_ARG_VAL(request_method, 0)
13976 +HTTP_END_ARGS;
13977 +
13978 +HTTP_EMPTY_ARGS(getContentType);
13979 +HTTP_BEGIN_ARGS(setContentType, 1)
13980 + HTTP_ARG_VAL(content_type, 0)
13981 +HTTP_END_ARGS;
13982 +
13983 +HTTP_EMPTY_ARGS(getQueryData);
13984 +HTTP_BEGIN_ARGS(setQueryData, 0)
13985 + HTTP_ARG_VAL(query_data, 0)
13986 +HTTP_END_ARGS;
13987 +
13988 +HTTP_BEGIN_ARGS(addQueryData, 1)
13989 + HTTP_ARG_VAL(query_data, 0)
13990 +HTTP_END_ARGS;
13991 +
13992 +HTTP_EMPTY_ARGS(getPostFields);
13993 +HTTP_BEGIN_ARGS(setPostFields, 0)
13994 + HTTP_ARG_VAL(post_fields, 0)
13995 +HTTP_END_ARGS;
13996 +
13997 +HTTP_BEGIN_ARGS(addPostFields, 1)
13998 + HTTP_ARG_VAL(post_fields, 0)
13999 +HTTP_END_ARGS;
14000 +
14001 +HTTP_EMPTY_ARGS(getPostFiles);
14002 +HTTP_BEGIN_ARGS(setPostFiles, 0)
14003 + HTTP_ARG_VAL(post_files, 0)
14004 +HTTP_END_ARGS;
14005 +
14006 +HTTP_BEGIN_ARGS(addPostFile, 2)
14007 + HTTP_ARG_VAL(formname, 0)
14008 + HTTP_ARG_VAL(filename, 0)
14009 + HTTP_ARG_VAL(content_type, 0)
14010 +HTTP_END_ARGS;
14011 +
14012 +HTTP_EMPTY_ARGS(getBody);
14013 +HTTP_BEGIN_ARGS(setBody, 0)
14014 + HTTP_ARG_VAL(request_body_data, 0)
14015 +HTTP_END_ARGS;
14016 +
14017 +HTTP_BEGIN_ARGS(addBody, 1)
14018 + HTTP_ARG_VAL(request_body_data, 0)
14019 +HTTP_END_ARGS;
14020 +
14021 +HTTP_EMPTY_ARGS(getPutFile);
14022 +HTTP_BEGIN_ARGS(setPutFile, 0)
14023 + HTTP_ARG_VAL(filename, 0)
14024 +HTTP_END_ARGS;
14025 +
14026 +HTTP_EMPTY_ARGS(getPutData);
14027 +HTTP_BEGIN_ARGS(setPutData, 0)
14028 + HTTP_ARG_VAL(put_data, 0)
14029 +HTTP_END_ARGS;
14030 +
14031 +HTTP_BEGIN_ARGS(addPutData, 1)
14032 + HTTP_ARG_VAL(put_data, 0)
14033 +HTTP_END_ARGS;
14034 +
14035 +HTTP_EMPTY_ARGS(getResponseData);
14036 +HTTP_BEGIN_ARGS(getResponseHeader, 0)
14037 + HTTP_ARG_VAL(name, 0)
14038 +HTTP_END_ARGS;
14039 +
14040 +HTTP_BEGIN_ARGS(getResponseCookies, 0)
14041 + HTTP_ARG_VAL(flags, 0)
14042 + HTTP_ARG_VAL(allowed_extras, 0)
14043 +HTTP_END_ARGS;
14044 +
14045 +HTTP_EMPTY_ARGS(getResponseBody);
14046 +HTTP_EMPTY_ARGS(getResponseCode);
14047 +HTTP_EMPTY_ARGS(getResponseStatus);
14048 +HTTP_BEGIN_ARGS(getResponseInfo, 0)
14049 + HTTP_ARG_VAL(name, 0)
14050 +HTTP_END_ARGS;
14051 +
14052 +HTTP_EMPTY_ARGS(getMessageClass);
14053 +HTTP_BEGIN_ARGS(setMessageClass, 1)
14054 + HTTP_ARG_VAL(message_class_name, 0)
14055 +HTTP_END_ARGS;
14056 +
14057 +HTTP_EMPTY_ARGS(getResponseMessage);
14058 +HTTP_EMPTY_ARGS(getRawResponseMessage);
14059 +HTTP_EMPTY_ARGS(getRequestMessage);
14060 +HTTP_EMPTY_ARGS(getRawRequestMessage);
14061 +HTTP_EMPTY_ARGS(getHistory);
14062 +HTTP_EMPTY_ARGS(clearHistory);
14063 +HTTP_EMPTY_ARGS(send);
14064 +
14065 +HTTP_BEGIN_ARGS(get, 1)
14066 + HTTP_ARG_VAL(url, 0)
14067 + HTTP_ARG_VAL(options, 0)
14068 + HTTP_ARG_VAL(info, 1)
14069 +HTTP_END_ARGS;
14070 +
14071 +HTTP_BEGIN_ARGS(head, 1)
14072 + HTTP_ARG_VAL(url, 0)
14073 + HTTP_ARG_VAL(options, 0)
14074 + HTTP_ARG_VAL(info, 1)
14075 +HTTP_END_ARGS;
14076 +
14077 +HTTP_BEGIN_ARGS(postData, 2)
14078 + HTTP_ARG_VAL(url, 0)
14079 + HTTP_ARG_VAL(data, 0)
14080 + HTTP_ARG_VAL(options, 0)
14081 + HTTP_ARG_VAL(info, 1)
14082 +HTTP_END_ARGS;
14083 +
14084 +HTTP_BEGIN_ARGS(postFields, 2)
14085 + HTTP_ARG_VAL(url, 0)
14086 + HTTP_ARG_VAL(data, 0)
14087 + HTTP_ARG_VAL(options, 0)
14088 + HTTP_ARG_VAL(info, 1)
14089 +HTTP_END_ARGS;
14090 +
14091 +HTTP_BEGIN_ARGS(putData, 2)
14092 + HTTP_ARG_VAL(url, 0)
14093 + HTTP_ARG_VAL(data, 0)
14094 + HTTP_ARG_VAL(options, 0)
14095 + HTTP_ARG_VAL(info, 1)
14096 +HTTP_END_ARGS;
14097 +
14098 +HTTP_BEGIN_ARGS(putFile, 2)
14099 + HTTP_ARG_VAL(url, 0)
14100 + HTTP_ARG_VAL(file, 0)
14101 + HTTP_ARG_VAL(options, 0)
14102 + HTTP_ARG_VAL(info, 1)
14103 +HTTP_END_ARGS;
14104 +
14105 +HTTP_BEGIN_ARGS(putStream, 2)
14106 + HTTP_ARG_VAL(url, 0)
14107 + HTTP_ARG_VAL(stream, 0)
14108 + HTTP_ARG_VAL(options, 0)
14109 + HTTP_ARG_VAL(info, 1)
14110 +HTTP_END_ARGS;
14111 +
14112 +HTTP_BEGIN_ARGS(methodRegister, 1)
14113 + HTTP_ARG_VAL(method_name, 0)
14114 +HTTP_END_ARGS;
14115 +
14116 +HTTP_BEGIN_ARGS(methodUnregister, 1)
14117 + HTTP_ARG_VAL(method, 0)
14118 +HTTP_END_ARGS;
14119 +
14120 +HTTP_BEGIN_ARGS(methodName, 1)
14121 + HTTP_ARG_VAL(method_id, 0)
14122 +HTTP_END_ARGS;
14123 +
14124 +HTTP_BEGIN_ARGS(methodExists, 1)
14125 + HTTP_ARG_VAL(method, 0)
14126 +HTTP_END_ARGS;
14127 +
14128 +#ifdef HAVE_CURL_FORMGET
14129 +HTTP_BEGIN_ARGS(encodeBody, 2)
14130 + HTTP_ARG_VAL(fields, 0)
14131 + HTTP_ARG_VAL(files, 0)
14132 +HTTP_END_ARGS;
14133 +#endif
14134 +
14135 +#define THIS_CE http_request_object_ce
14136 +zend_class_entry *http_request_object_ce;
14137 +zend_function_entry http_request_object_fe[] = {
14138 + HTTP_REQUEST_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
14139 +
14140 + HTTP_REQUEST_ME(setOptions, ZEND_ACC_PUBLIC)
14141 + HTTP_REQUEST_ME(getOptions, ZEND_ACC_PUBLIC)
14142 + HTTP_REQUEST_ME(setSslOptions, ZEND_ACC_PUBLIC)
14143 + HTTP_REQUEST_ME(getSslOptions, ZEND_ACC_PUBLIC)
14144 + HTTP_REQUEST_ME(addSslOptions, ZEND_ACC_PUBLIC)
14145 +
14146 + HTTP_REQUEST_ME(addHeaders, ZEND_ACC_PUBLIC)
14147 + HTTP_REQUEST_ME(getHeaders, ZEND_ACC_PUBLIC)
14148 + HTTP_REQUEST_ME(setHeaders, ZEND_ACC_PUBLIC)
14149 +
14150 + HTTP_REQUEST_ME(addCookies, ZEND_ACC_PUBLIC)
14151 + HTTP_REQUEST_ME(getCookies, ZEND_ACC_PUBLIC)
14152 + HTTP_REQUEST_ME(setCookies, ZEND_ACC_PUBLIC)
14153 +
14154 + HTTP_REQUEST_ME(enableCookies, ZEND_ACC_PUBLIC)
14155 + HTTP_REQUEST_ME(resetCookies, ZEND_ACC_PUBLIC)
14156 + HTTP_REQUEST_ME(flushCookies, ZEND_ACC_PUBLIC)
14157 +
14158 + HTTP_REQUEST_ME(setMethod, ZEND_ACC_PUBLIC)
14159 + HTTP_REQUEST_ME(getMethod, ZEND_ACC_PUBLIC)
14160 +
14161 + HTTP_REQUEST_ME(setUrl, ZEND_ACC_PUBLIC)
14162 + HTTP_REQUEST_ME(getUrl, ZEND_ACC_PUBLIC)
14163 +
14164 + HTTP_REQUEST_ME(setContentType, ZEND_ACC_PUBLIC)
14165 + HTTP_REQUEST_ME(getContentType, ZEND_ACC_PUBLIC)
14166 +
14167 + HTTP_REQUEST_ME(setQueryData, ZEND_ACC_PUBLIC)
14168 + HTTP_REQUEST_ME(getQueryData, ZEND_ACC_PUBLIC)
14169 + HTTP_REQUEST_ME(addQueryData, ZEND_ACC_PUBLIC)
14170 +
14171 + HTTP_REQUEST_ME(setPostFields, ZEND_ACC_PUBLIC)
14172 + HTTP_REQUEST_ME(getPostFields, ZEND_ACC_PUBLIC)
14173 + HTTP_REQUEST_ME(addPostFields, ZEND_ACC_PUBLIC)
14174 +
14175 + HTTP_REQUEST_ME(setBody, ZEND_ACC_PUBLIC)
14176 + HTTP_REQUEST_ME(getBody, ZEND_ACC_PUBLIC)
14177 + HTTP_REQUEST_ME(addBody, ZEND_ACC_PUBLIC)
14178 + HTTP_REQUEST_MALIAS(setRawPostData, setBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
14179 + HTTP_REQUEST_MALIAS(getRawPostData, getBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
14180 + HTTP_REQUEST_MALIAS(addRawPostData, addBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED)
14181 +
14182 + HTTP_REQUEST_ME(setPostFiles, ZEND_ACC_PUBLIC)
14183 + HTTP_REQUEST_ME(addPostFile, ZEND_ACC_PUBLIC)
14184 + HTTP_REQUEST_ME(getPostFiles, ZEND_ACC_PUBLIC)
14185 +
14186 + HTTP_REQUEST_ME(setPutFile, ZEND_ACC_PUBLIC)
14187 + HTTP_REQUEST_ME(getPutFile, ZEND_ACC_PUBLIC)
14188 +
14189 + HTTP_REQUEST_ME(setPutData, ZEND_ACC_PUBLIC)
14190 + HTTP_REQUEST_ME(getPutData, ZEND_ACC_PUBLIC)
14191 + HTTP_REQUEST_ME(addPutData, ZEND_ACC_PUBLIC)
14192 +
14193 + HTTP_REQUEST_ME(send, ZEND_ACC_PUBLIC)
14194 +
14195 + HTTP_REQUEST_ME(getResponseData, ZEND_ACC_PUBLIC)
14196 + HTTP_REQUEST_ME(getResponseHeader, ZEND_ACC_PUBLIC)
14197 + HTTP_REQUEST_ME(getResponseCookies, ZEND_ACC_PUBLIC)
14198 + HTTP_REQUEST_ME(getResponseCode, ZEND_ACC_PUBLIC)
14199 + HTTP_REQUEST_ME(getResponseStatus, ZEND_ACC_PUBLIC)
14200 + HTTP_REQUEST_ME(getResponseBody, ZEND_ACC_PUBLIC)
14201 + HTTP_REQUEST_ME(getResponseInfo, ZEND_ACC_PUBLIC)
14202 + HTTP_REQUEST_ME(getResponseMessage, ZEND_ACC_PUBLIC)
14203 + HTTP_REQUEST_ME(getRawResponseMessage, ZEND_ACC_PUBLIC)
14204 + HTTP_REQUEST_ME(getRequestMessage, ZEND_ACC_PUBLIC)
14205 + HTTP_REQUEST_ME(getRawRequestMessage, ZEND_ACC_PUBLIC)
14206 + HTTP_REQUEST_ME(getHistory, ZEND_ACC_PUBLIC)
14207 + HTTP_REQUEST_ME(clearHistory, ZEND_ACC_PUBLIC)
14208 +
14209 + HTTP_REQUEST_ME(getMessageClass, ZEND_ACC_PUBLIC)
14210 + HTTP_REQUEST_ME(setMessageClass, ZEND_ACC_PUBLIC)
14211 +
14212 + HTTP_REQUEST_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
14213 +
14214 + HTTP_REQUEST_ALIAS(get, http_get)
14215 + HTTP_REQUEST_ALIAS(head, http_head)
14216 + HTTP_REQUEST_ALIAS(postData, http_post_data)
14217 + HTTP_REQUEST_ALIAS(postFields, http_post_fields)
14218 + HTTP_REQUEST_ALIAS(putData, http_put_data)
14219 + HTTP_REQUEST_ALIAS(putFile, http_put_file)
14220 + HTTP_REQUEST_ALIAS(putStream, http_put_stream)
14221 +
14222 + HTTP_REQUEST_ALIAS(methodRegister, http_request_method_register)
14223 + HTTP_REQUEST_ALIAS(methodUnregister, http_request_method_unregister)
14224 + HTTP_REQUEST_ALIAS(methodName, http_request_method_name)
14225 + HTTP_REQUEST_ALIAS(methodExists, http_request_method_exists)
14226 +#ifdef HAVE_CURL_FORMGET
14227 + HTTP_REQUEST_ALIAS(encodeBody, http_request_body_encode)
14228 +#endif
14229 + EMPTY_FUNCTION_ENTRY
14230 +};
14231 +static zend_object_handlers http_request_object_handlers;
14232 +
14233 +PHP_MINIT_FUNCTION(http_request_object)
14234 +{
14235 + HTTP_REGISTER_CLASS_EX(HttpRequest, http_request_object, NULL, 0);
14236 + http_request_object_handlers.clone_obj = _http_request_object_clone_obj;
14237 +
14238 + zend_declare_property_null(THIS_CE, ZEND_STRS("options")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14239 + zend_declare_property_null(THIS_CE, ZEND_STRS("postFields")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14240 + zend_declare_property_null(THIS_CE, ZEND_STRS("postFiles")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14241 + zend_declare_property_null(THIS_CE, ZEND_STRS("responseInfo")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14242 + zend_declare_property_null(THIS_CE, ZEND_STRS("responseMessage")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14243 + zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PRIVATE TSRMLS_CC);
14244 + zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14245 + zend_declare_property_long(THIS_CE, ZEND_STRS("method")-1, HTTP_GET, ZEND_ACC_PRIVATE TSRMLS_CC);
14246 + zend_declare_property_string(THIS_CE, ZEND_STRS("url")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14247 + zend_declare_property_string(THIS_CE, ZEND_STRS("contentType")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14248 + zend_declare_property_string(THIS_CE, ZEND_STRS("requestBody")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14249 + zend_declare_property_string(THIS_CE, ZEND_STRS("queryData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14250 + zend_declare_property_string(THIS_CE, ZEND_STRS("putFile")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14251 + zend_declare_property_string(THIS_CE, ZEND_STRS("putData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14252 + zend_declare_property_null(THIS_CE, ZEND_STRS("history")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
14253 + zend_declare_property_bool(THIS_CE, ZEND_STRS("recordHistory")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
14254 + zend_declare_property_string(THIS_CE, ZEND_STRS("messageClass")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);
14255 +
14256 +#ifndef WONKY
14257 + /*
14258 + * Request Method Constants
14259 + */
14260 + /* HTTP/1.1 */
14261 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_GET")-1, HTTP_GET TSRMLS_CC);
14262 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_HEAD")-1, HTTP_HEAD TSRMLS_CC);
14263 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_POST")-1, HTTP_POST TSRMLS_CC);
14264 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PUT")-1, HTTP_PUT TSRMLS_CC);
14265 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_DELETE")-1, HTTP_DELETE TSRMLS_CC);
14266 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_OPTIONS")-1, HTTP_OPTIONS TSRMLS_CC);
14267 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_TRACE")-1, HTTP_TRACE TSRMLS_CC);
14268 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CONNECT")-1, HTTP_CONNECT TSRMLS_CC);
14269 + /* WebDAV - RFC 2518 */
14270 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPFIND")-1, HTTP_PROPFIND TSRMLS_CC);
14271 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPPATCH")-1, HTTP_PROPPATCH TSRMLS_CC);
14272 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKCOL")-1, HTTP_MKCOL TSRMLS_CC);
14273 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_COPY")-1, HTTP_COPY TSRMLS_CC);
14274 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MOVE")-1, HTTP_MOVE TSRMLS_CC);
14275 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LOCK")-1, HTTP_LOCK TSRMLS_CC);
14276 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNLOCK")-1, HTTP_UNLOCK TSRMLS_CC);
14277 + /* WebDAV Versioning - RFC 3253 */
14278 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_VERSION_CONTROL")-1, HTTP_VERSION_CONTROL TSRMLS_CC);
14279 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_REPORT")-1, HTTP_REPORT TSRMLS_CC);
14280 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKOUT")-1, HTTP_CHECKOUT TSRMLS_CC);
14281 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKIN")-1, HTTP_CHECKIN TSRMLS_CC);
14282 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNCHECKOUT")-1, HTTP_UNCHECKOUT TSRMLS_CC);
14283 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKWORKSPACE")-1, HTTP_MKWORKSPACE TSRMLS_CC);
14284 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UPDATE")-1, HTTP_UPDATE TSRMLS_CC);
14285 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LABEL")-1, HTTP_LABEL TSRMLS_CC);
14286 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MERGE")-1, HTTP_MERGE TSRMLS_CC);
14287 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_BASELINE_CONTROL")-1, HTTP_BASELINE_CONTROL TSRMLS_CC);
14288 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKACTIVITY")-1, HTTP_MKACTIVITY TSRMLS_CC);
14289 + /* WebDAV Access Control - RFC 3744 */
14290 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_ACL")-1, HTTP_ACL TSRMLS_CC);
14291 +
14292 + /*
14293 + * HTTP Protocol Version Constants
14294 + */
14295 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_0")-1, CURL_HTTP_VERSION_1_0 TSRMLS_CC);
14296 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_1")-1, CURL_HTTP_VERSION_1_1 TSRMLS_CC);
14297 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_NONE")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC); /* to be removed */
14298 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_ANY")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC);
14299 +
14300 + /*
14301 + * SSL Version Constants
14302 + */
14303 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_TLSv1")-1, CURL_SSLVERSION_TLSv1 TSRMLS_CC);
14304 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv2")-1, CURL_SSLVERSION_SSLv2 TSRMLS_CC);
14305 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv3")-1, CURL_SSLVERSION_SSLv3 TSRMLS_CC);
14306 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_ANY")-1, CURL_SSLVERSION_DEFAULT TSRMLS_CC);
14307 +
14308 + /*
14309 + * DNS IPvX resolving
14310 + */
14311 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V4")-1, CURL_IPRESOLVE_V4 TSRMLS_CC);
14312 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V6")-1, CURL_IPRESOLVE_V6 TSRMLS_CC);
14313 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_ANY")-1, CURL_IPRESOLVE_WHATEVER TSRMLS_CC);
14314 +
14315 + /*
14316 + * Auth Constants
14317 + */
14318 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_BASIC")-1, CURLAUTH_BASIC TSRMLS_CC);
14319 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST")-1, CURLAUTH_DIGEST TSRMLS_CC);
14320 +#if HTTP_CURL_VERSION(7,19,3)
14321 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST_IE")-1, CURLAUTH_DIGEST_IE TSRMLS_CC);
14322 +#endif
14323 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_NTLM")-1, CURLAUTH_NTLM TSRMLS_CC);
14324 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_GSSNEG")-1, CURLAUTH_GSSNEGOTIATE TSRMLS_CC);
14325 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_ANY")-1, CURLAUTH_ANY TSRMLS_CC);
14326 +
14327 + /*
14328 + * Proxy Type Constants
14329 + */
14330 +# if HTTP_CURL_VERSION(7,15,2)
14331 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4")-1, CURLPROXY_SOCKS4 TSRMLS_CC);
14332 +# endif
14333 +#if HTTP_CURL_VERSION(7,18,0)
14334 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4A")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
14335 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5_HOSTNAME")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
14336 +#endif
14337 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5")-1, CURLPROXY_SOCKS5 TSRMLS_CC);
14338 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP")-1, CURLPROXY_HTTP TSRMLS_CC);
14339 +# if HTTP_CURL_VERSION(7,19,4)
14340 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP_1_0")-1, CURLPROXY_HTTP_1_0 TSRMLS_CC);
14341 +# endif
14342 +#endif /* WONKY */
14343 +
14344 + /*
14345 + * Post Redirection Constants
14346 + */
14347 +#if HTTP_CURL_VERSION(7,19,1)
14348 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_301")-1, CURL_REDIR_POST_301 TSRMLS_CC);
14349 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_302")-1, CURL_REDIR_POST_302 TSRMLS_CC);
14350 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_ALL")-1, CURL_REDIR_POST_ALL TSRMLS_CC);
14351 +#endif
14352 +
14353 + return SUCCESS;
14354 +}
14355 +
14356 +zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC)
14357 +{
14358 + return http_request_object_new_ex(ce, NULL, NULL);
14359 +}
14360 +
14361 +zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC)
14362 +{
14363 + zend_object_value ov;
14364 + http_request_object *o;
14365 +
14366 + o = ecalloc(1, sizeof(http_request_object));
14367 + o->zo.ce = ce;
14368 + o->request = http_request_init_ex(NULL, ch, 0, NULL);
14369 +
14370 + if (ptr) {
14371 + *ptr = o;
14372 + }
14373 +
14374 +#ifdef ZEND_ENGINE_2_4
14375 + zend_object_std_init(o, ce TSRMLS_CC);
14376 + object_properties_init(o, ce);
14377 +#else
14378 + ALLOC_HASHTABLE(OBJ_PROP(o));
14379 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
14380 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
14381 +#endif
14382 +
14383 + ov.handle = putObject(http_request_object, o);
14384 + ov.handlers = &http_request_object_handlers;
14385 +
14386 + return ov;
14387 +}
14388 +
14389 +zend_object_value _http_request_object_clone_obj(zval *this_ptr TSRMLS_DC)
14390 +{
14391 + zend_object_value new_ov;
14392 + http_request_object *new_obj;
14393 + getObject(http_request_object, old_obj);
14394 +
14395 + new_ov = http_request_object_new_ex(old_obj->zo.ce, NULL, &new_obj);
14396 + if (old_obj->request->ch) {
14397 + http_curl_init_ex(http_curl_copy(old_obj->request->ch), new_obj->request);
14398 + }
14399 +
14400 + zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
14401 + phpstr_append(&new_obj->request->conv.request, old_obj->request->conv.request.data, old_obj->request->conv.request.used);
14402 + phpstr_append(&new_obj->request->conv.response, old_obj->request->conv.response.data, old_obj->request->conv.response.used);
14403 +
14404 + return new_ov;
14405 +}
14406 +
14407 +void _http_request_object_free(zend_object *object TSRMLS_DC)
14408 +{
14409 + http_request_object *o = (http_request_object *) object;
14410 +
14411 + http_request_free(&o->request);
14412 + freeObject(o);
14413 +}
14414 +
14415 +#define http_request_object_check_request_content_type(t) _http_request_object_check_request_content_type((t) TSRMLS_CC)
14416 +static inline void _http_request_object_check_request_content_type(zval *this_ptr TSRMLS_DC)
14417 +{
14418 + zval *ctype = zend_read_property(THIS_CE, getThis(), ZEND_STRS("contentType")-1, 0 TSRMLS_CC);
14419 +
14420 + if (Z_STRLEN_P(ctype)) {
14421 + zval **headers, *opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14422 +
14423 + if ( (Z_TYPE_P(opts) == IS_ARRAY) &&
14424 + (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void *) &headers)) &&
14425 + (Z_TYPE_PP(headers) == IS_ARRAY)) {
14426 + zval **ct_header;
14427 +
14428 + /* only override if not already set */
14429 + if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(headers), "Content-Type", sizeof("Content-Type"), (void *) &ct_header))) {
14430 + add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14431 + } else
14432 + /* or not a string, zero length string or a string of spaces */
14433 + if ((Z_TYPE_PP(ct_header) != IS_STRING) || !Z_STRLEN_PP(ct_header)) {
14434 + add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14435 + } else {
14436 + int i, only_space = 1;
14437 +
14438 + /* check for spaces only */
14439 + for (i = 0; i < Z_STRLEN_PP(ct_header); ++i) {
14440 + if (!HTTP_IS_CTYPE(space, Z_STRVAL_PP(ct_header)[i])) {
14441 + only_space = 0;
14442 + break;
14443 + }
14444 + }
14445 + if (only_space) {
14446 + add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14447 + }
14448 + }
14449 + } else {
14450 + zval *headers;
14451 +
14452 + MAKE_STD_ZVAL(headers);
14453 + array_init(headers);
14454 + add_assoc_stringl(headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
14455 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, headers);
14456 + zval_ptr_dtor(&headers);
14457 + }
14458 + }
14459 +}
14460 +
14461 +#define http_request_object_message(zo, msg) _http_request_object_message((zo), (msg) TSRMLS_CC)
14462 +static inline zend_object_value _http_request_object_message(zval *this_ptr, http_message *msg TSRMLS_DC)
14463 +{
14464 + zend_object_value ov;
14465 + zval *zcn = zend_read_property(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, 0 TSRMLS_CC);
14466 +
14467 + 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))) {
14468 + return ov;
14469 + } else {
14470 + return http_message_object_new_ex(http_message_object_ce, msg, NULL);
14471 + }
14472 +}
14473 +
14474 +STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC)
14475 +{
14476 + STATUS status = SUCCESS;
14477 + char *url = http_absolute_url(Z_STRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("url")-1, 0 TSRMLS_CC)));
14478 +
14479 + if (!url) {
14480 + return FAILURE;
14481 + }
14482 +
14483 + http_request_reset(obj->request);
14484 + obj->request->url = url;
14485 + HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init(obj->request), return FAILURE);
14486 +
14487 + switch (obj->request->meth = Z_LVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("method")-1, 0 TSRMLS_CC)))
14488 + {
14489 + case HTTP_GET:
14490 + case HTTP_HEAD:
14491 + break;
14492 +
14493 + case HTTP_PUT:
14494 + {
14495 + zval *put_file = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putFile")-1, 0 TSRMLS_CC);
14496 +
14497 + http_request_object_check_request_content_type(getThis());
14498 +
14499 + if (Z_STRLEN_P(put_file)) {
14500 + php_stream_statbuf ssb;
14501 + php_stream *stream = php_stream_open_wrapper_ex(Z_STRVAL_P(put_file), "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT);
14502 +
14503 + if (stream && SUCCESS == php_stream_stat(stream, &ssb)) {
14504 + obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
14505 + } else {
14506 + status = FAILURE;
14507 + }
14508 + } else {
14509 + zval *put_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC);
14510 + obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING,
14511 + estrndup(Z_STRVAL_P(put_data), Z_STRLEN_P(put_data)), Z_STRLEN_P(put_data), 1);
14512 + }
14513 + break;
14514 + }
14515 +
14516 + case HTTP_POST:
14517 + default:
14518 + {
14519 + /* check for raw request body */
14520 + zval *raw_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC);
14521 +
14522 + if (Z_STRLEN_P(raw_data)) {
14523 + http_request_object_check_request_content_type(getThis());
14524 + obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING,
14525 + estrndup(Z_STRVAL_P(raw_data), Z_STRLEN_P(raw_data)), Z_STRLEN_P(raw_data), 1);
14526 + } else {
14527 + 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);
14528 + HashTable *fields;
14529 + HashTable *files;
14530 +
14531 + fields = (Z_TYPE_P(zfields) == IS_ARRAY) ? Z_ARRVAL_P(zfields) : NULL;
14532 + files = (Z_TYPE_P(zfiles) == IS_ARRAY) ? Z_ARRVAL_P(zfiles) : NULL;
14533 +
14534 + if ((fields && zend_hash_num_elements(fields)) || (files && zend_hash_num_elements(files))) {
14535 + if (!(obj->request->body = http_request_body_fill(obj->request->body, fields, files))) {
14536 + status = FAILURE;
14537 + }
14538 + }
14539 + }
14540 + break;
14541 + }
14542 + }
14543 +
14544 + if (status == SUCCESS) {
14545 + zval *qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC);
14546 + zval *options = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14547 +
14548 + if (Z_STRLEN_P(qdata)) {
14549 + if (!strchr(obj->request->url, '?')) {
14550 + strlcat(obj->request->url, "?", HTTP_URL_MAXLEN);
14551 + } else {
14552 + strlcat(obj->request->url, "&", HTTP_URL_MAXLEN);
14553 + }
14554 + strlcat(obj->request->url, Z_STRVAL_P(qdata), HTTP_URL_MAXLEN);
14555 + }
14556 +
14557 + http_request_prepare(obj->request, Z_ARRVAL_P(options));
14558 +
14559 + /* check if there's a onProgress method and add it as progress callback if one isn't already set */
14560 + if (zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onprogress", sizeof("onprogress"))) {
14561 + zval **entry, *pcb;
14562 +
14563 + if ( (Z_TYPE_P(options) != IS_ARRAY)
14564 + || (SUCCESS != zend_hash_find(Z_ARRVAL_P(options), "onprogress", sizeof("onprogress"), (void *) &entry)
14565 + || (!HTTP_IS_CALLABLE(*entry, 0, NULL)))) {
14566 + MAKE_STD_ZVAL(pcb);
14567 + array_init(pcb);
14568 + ZVAL_ADDREF(getThis());
14569 + add_next_index_zval(pcb, getThis());
14570 + add_next_index_stringl(pcb, "onprogress", lenof("onprogress"), 1);
14571 + http_request_set_progress_callback(obj->request, pcb);
14572 + zval_ptr_dtor(&pcb);
14573 + }
14574 + }
14575 + }
14576 +
14577 + return status;
14578 +}
14579 +
14580 +STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC)
14581 +{
14582 + STATUS ret;
14583 + zval *info;
14584 + http_message *msg;
14585 +
14586 + /* always fetch info */
14587 + MAKE_STD_ZVAL(info);
14588 + array_init(info);
14589 + http_request_info(obj->request, Z_ARRVAL_P(info));
14590 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, info TSRMLS_CC);
14591 + zval_ptr_dtor(&info);
14592 +
14593 + /* parse response message */
14594 + phpstr_fix(&obj->request->conv.request);
14595 + phpstr_fix(&obj->request->conv.response);
14596 +
14597 + if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response)))) {
14598 + zval *message;
14599 +
14600 + if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) {
14601 + zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
14602 + http_message *response = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response));
14603 + http_message *request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request));
14604 +
14605 + MAKE_STD_ZVAL(hist);
14606 + ZVAL_OBJVAL(hist, http_request_object_message(getThis(), http_message_interconnect(response, request)), 0);
14607 + if (Z_TYPE_P(history) == IS_OBJECT) {
14608 + http_message_object_prepend(hist, history);
14609 + }
14610 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
14611 + zval_ptr_dtor(&hist);
14612 + }
14613 +
14614 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, msg->http.info.response.code TSRMLS_CC);
14615 + zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, STR_PTR(msg->http.info.response.status) TSRMLS_CC);
14616 +
14617 + MAKE_STD_ZVAL(message);
14618 + ZVAL_OBJVAL(message, http_request_object_message(getThis(), msg), 0);
14619 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, message TSRMLS_CC);
14620 + zval_ptr_dtor(&message);
14621 +
14622 + ret = SUCCESS;
14623 + } else {
14624 + /* update properties with empty values*/
14625 + zval *znull;
14626 +
14627 + MAKE_STD_ZVAL(znull);
14628 + ZVAL_NULL(znull);
14629 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, znull TSRMLS_CC);
14630 + zval_ptr_dtor(&znull);
14631 +
14632 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, 0 TSRMLS_CC);
14633 + zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, "" TSRMLS_CC);
14634 +
14635 + /* append request message to history */
14636 + if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) {
14637 + http_message *request;
14638 +
14639 + if ((request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) {
14640 + zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
14641 +
14642 + MAKE_STD_ZVAL(hist);
14643 + ZVAL_OBJVAL(hist, http_request_object_message(getThis(), request), 0);
14644 + if (Z_TYPE_P(history) == IS_OBJECT) {
14645 + http_message_object_prepend(hist, history);
14646 + }
14647 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
14648 + zval_ptr_dtor(&hist);
14649 + }
14650 + }
14651 +
14652 + ret = FAILURE;
14653 + }
14654 +
14655 + http_request_set_progress_callback(obj->request, NULL);
14656 +
14657 + if (!EG(exception) && zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onfinish", sizeof("onfinish"))) {
14658 + zval *param;
14659 +
14660 + MAKE_STD_ZVAL(param);
14661 + ZVAL_BOOL(param, ret == SUCCESS);
14662 + with_error_handling(EH_NORMAL, NULL) {
14663 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "onfinish", NULL, param);
14664 + } end_error_handling();
14665 + zval_ptr_dtor(&param);
14666 + }
14667 +
14668 + return ret;
14669 +}
14670 +#ifdef ZEND_ENGINE_2_4
14671 +# define APK_DC TSRMLS_DC
14672 +#else
14673 +# define APK_DC
14674 +#endif
14675 +static int apply_pretty_key(void *pDest APK_DC, int num_args, va_list args, zend_hash_key *hash_key)
14676 +{
14677 + if (hash_key->arKey && hash_key->nKeyLength > 1) {
14678 + hash_key->h = zend_hash_func(pretty_key(hash_key->arKey, hash_key->nKeyLength - 1, 1, 0), hash_key->nKeyLength);
14679 + }
14680 + return ZEND_HASH_APPLY_KEEP;
14681 +}
14682 +
14683 +#define http_request_object_set_options_subr(key, ow, pk) \
14684 + _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key), (ow), (pk))
14685 +static inline void _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len, int overwrite, int prettify_keys)
14686 +{
14687 + zval *old_opts, *new_opts, *opts = NULL, **entry = NULL;
14688 +
14689 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opts)) {
14690 + RETURN_FALSE;
14691 + }
14692 +
14693 + MAKE_STD_ZVAL(new_opts);
14694 + array_init(new_opts);
14695 + old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14696 + if (Z_TYPE_P(old_opts) == IS_ARRAY) {
14697 + array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
14698 + }
14699 +
14700 + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), key, len, (void *) &entry)) {
14701 + if (overwrite) {
14702 + zend_hash_clean(Z_ARRVAL_PP(entry));
14703 + }
14704 + if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
14705 + if (overwrite) {
14706 + array_copy(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry));
14707 + } else {
14708 + array_join(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry), 0, prettify_keys ? ARRAY_JOIN_PRETTIFY : 0);
14709 + }
14710 + }
14711 + } else if (opts) {
14712 + if (prettify_keys) {
14713 + zend_hash_apply_with_arguments(Z_ARRVAL_P(opts) HTTP_ZAPI_HASH_TSRMLS_CC, apply_pretty_key, 0, NULL);
14714 + }
14715 + ZVAL_ADDREF(opts);
14716 + add_assoc_zval_ex(new_opts, key, len, opts);
14717 + }
14718 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
14719 + zval_ptr_dtor(&new_opts);
14720 +
14721 + RETURN_TRUE;
14722 +}
14723 +
14724 +#define http_request_object_get_options_subr(key) \
14725 + _http_request_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key))
14726 +static inline void _http_request_get_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len)
14727 +{
14728 + NO_ARGS;
14729 +
14730 + if (return_value_used) {
14731 + zval *opts, **options;
14732 +
14733 + opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14734 + array_init(return_value);
14735 +
14736 + if ( (Z_TYPE_P(opts) == IS_ARRAY) &&
14737 + (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), key, len, (void *) &options))) {
14738 + convert_to_array(*options);
14739 + array_copy(Z_ARRVAL_PP(options), Z_ARRVAL_P(return_value));
14740 + }
14741 + }
14742 +}
14743 +
14744 +
14745 +/* ### USERLAND ### */
14746 +
14747 +/* {{{ proto void HttpRequest::__construct([string url[, int request_method = HTTP_METH_GET[, array options]]])
14748 + Create a new HttpRequest object instance. */
14749 +PHP_METHOD(HttpRequest, __construct)
14750 +{
14751 + char *URL = NULL;
14752 + int URL_len;
14753 + long meth = -1;
14754 + zval *options = NULL;
14755 +
14756 + SET_EH_THROW_HTTP();
14757 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!", &URL, &URL_len, &meth, &options)) {
14758 + if (URL) {
14759 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
14760 + }
14761 + if (meth > -1) {
14762 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
14763 + }
14764 + if (options) {
14765 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options);
14766 + }
14767 + }
14768 + SET_EH_NORMAL();
14769 +}
14770 +/* }}} */
14771 +
14772 +/* {{{ proto HttpRequest HttpRequest::factory([string url[, int request_method HTTP_METH_GET[, array options[, string class_name = "HttpRequest"]]]])
14773 + Create a new HttpRequest object instance. */
14774 +PHP_METHOD(HttpRequest, factory)
14775 +{
14776 + char *cn = NULL, *URL = NULL;
14777 + int cl = 0, URL_len = 0;
14778 + long meth = -1;
14779 + zval *options = NULL;
14780 + zend_object_value ov;
14781 +
14782 + SET_EH_THROW_HTTP();
14783 + if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!s", &URL, &URL_len, &meth, &options, &cn, &cl) &&
14784 + SUCCESS == http_object_new(&ov, cn, cl, _http_request_object_new_ex, http_request_object_ce, NULL, NULL)) {
14785 + RETVAL_OBJVAL(ov, 0);
14786 + getThis() = return_value;
14787 + if (URL) {
14788 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
14789 + }
14790 + if (meth > -1) {
14791 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
14792 + }
14793 + if (options) {
14794 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options);
14795 + }
14796 + }
14797 + SET_EH_NORMAL();
14798 +}
14799 +/* }}} */
14800 +
14801 +/* {{{ proto bool HttpRequest::setOptions([array options])
14802 + Set the request options to use. See http_get() for a full list of available options. */
14803 +PHP_METHOD(HttpRequest, setOptions)
14804 +{
14805 + HashKey key = initHashKey(0);
14806 + HashPosition pos;
14807 + zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt;
14808 +
14809 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) {
14810 + RETURN_FALSE;
14811 + }
14812 +
14813 + MAKE_STD_ZVAL(new_opts);
14814 + array_init(new_opts);
14815 +
14816 + if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
14817 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
14818 + zval_ptr_dtor(&new_opts);
14819 + RETURN_TRUE;
14820 + }
14821 +
14822 + MAKE_STD_ZVAL(add_opts);
14823 + array_init(add_opts);
14824 + /* some options need extra attention -- thus cannot use array_merge() directly */
14825 + FOREACH_KEYVAL(pos, opts, key, opt) {
14826 + if (key.type == HASH_KEY_IS_STRING) {
14827 +#define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
14828 + if (KEYMATCH(key, "headers")) {
14829 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, *opt);
14830 + } else if (KEYMATCH(key, "cookies")) {
14831 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt);
14832 + } else if (KEYMATCH(key, "ssl")) {
14833 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt);
14834 + } else if (KEYMATCH(key, "url") || KEYMATCH(key, "uri")) {
14835 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "seturl", NULL, *opt);
14836 + } else if (KEYMATCH(key, "method")) {
14837 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmethod", NULL, *opt);
14838 + } else if (KEYMATCH(key, "flushcookies")) {
14839 + getObject(http_request_object, obj);
14840 + if (i_zend_is_true(*opt)) {
14841 + http_request_flush_cookies(obj->request);
14842 + }
14843 + } else if (KEYMATCH(key, "resetcookies")) {
14844 + getObject(http_request_object, obj);
14845 + http_request_reset_cookies(obj->request, (zend_bool) i_zend_is_true(*opt));
14846 + } else if (KEYMATCH(key, "enablecookies")) {
14847 + getObject(http_request_object, obj);
14848 + http_request_enable_cookies(obj->request);
14849 + } else if (KEYMATCH(key, "recordHistory")) {
14850 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, *opt TSRMLS_CC);
14851 + } else if (KEYMATCH(key, "messageClass")) {
14852 + zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmessageclass", NULL, *opt);
14853 + } else if (Z_TYPE_PP(opt) == IS_NULL) {
14854 + old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14855 + if (Z_TYPE_P(old_opts) == IS_ARRAY) {
14856 + zend_hash_del(Z_ARRVAL_P(old_opts), key.str, key.len);
14857 + }
14858 + } else {
14859 + ZVAL_ADDREF(*opt);
14860 + add_assoc_zval_ex(add_opts, key.str, key.len, *opt);
14861 + }
14862 + }
14863 + }
14864 +
14865 + old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC);
14866 + if (Z_TYPE_P(old_opts) == IS_ARRAY) {
14867 + array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts));
14868 + }
14869 + array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0);
14870 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC);
14871 + zval_ptr_dtor(&new_opts);
14872 + zval_ptr_dtor(&add_opts);
14873 +
14874 + RETURN_TRUE;
14875 +}
14876 +/* }}} */
14877 +
14878 +/* {{{ proto array HttpRequest::getOptions()
14879 + Get currently set options. */
14880 +PHP_METHOD(HttpRequest, getOptions)
14881 +{
14882 + NO_ARGS;
14883 +
14884 + if (return_value_used) {
14885 + RETURN_PROP(options);
14886 + }
14887 +}
14888 +/* }}} */
14889 +
14890 +/* {{{ proto bool HttpRequest::setSslOptions([array options])
14891 + Set SSL options. */
14892 +PHP_METHOD(HttpRequest, setSslOptions)
14893 +{
14894 + http_request_object_set_options_subr("ssl", 1, 0);
14895 +}
14896 +/* }}} */
14897 +
14898 +/* {{{ proto bool HttpRequest::addSslOptions(array options)
14899 + Set additional SSL options. */
14900 +PHP_METHOD(HttpRequest, addSslOptions)
14901 +{
14902 + http_request_object_set_options_subr("ssl", 0, 0);
14903 +}
14904 +/* }}} */
14905 +
14906 +/* {{{ proto array HttpRequest::getSslOtpions()
14907 + Get previously set SSL options. */
14908 +PHP_METHOD(HttpRequest, getSslOptions)
14909 +{
14910 + http_request_object_get_options_subr("ssl");
14911 +}
14912 +/* }}} */
14913 +
14914 +/* {{{ proto bool HttpRequest::addHeaders(array headers)
14915 + Add request header name/value pairs. */
14916 +PHP_METHOD(HttpRequest, addHeaders)
14917 +{
14918 + http_request_object_set_options_subr("headers", 0, 1);
14919 +}
14920 +
14921 +/* {{{ proto bool HttpRequest::setHeaders([array headers])
14922 + Set request header name/value pairs. */
14923 +PHP_METHOD(HttpRequest, setHeaders)
14924 +{
14925 + http_request_object_set_options_subr("headers", 1, 1);
14926 +}
14927 +/* }}} */
14928 +
14929 +/* {{{ proto array HttpRequest::getHeaders()
14930 + Get previously set request headers. */
14931 +PHP_METHOD(HttpRequest, getHeaders)
14932 +{
14933 + http_request_object_get_options_subr("headers");
14934 +}
14935 +/* }}} */
14936 +
14937 +/* {{{ proto bool HttpRequest::setCookies([array cookies])
14938 + Set cookies. */
14939 +PHP_METHOD(HttpRequest, setCookies)
14940 +{
14941 + http_request_object_set_options_subr("cookies", 1, 0);
14942 +}
14943 +/* }}} */
14944 +
14945 +/* {{{ proto bool HttpRequest::addCookies(array cookies)
14946 + Add cookies. */
14947 +PHP_METHOD(HttpRequest, addCookies)
14948 +{
14949 + http_request_object_set_options_subr("cookies", 0, 0);
14950 +}
14951 +/* }}} */
14952 +
14953 +/* {{{ proto array HttpRequest::getCookies()
14954 + Get previously set cookies. */
14955 +PHP_METHOD(HttpRequest, getCookies)
14956 +{
14957 + http_request_object_get_options_subr("cookies");
14958 +}
14959 +/* }}} */
14960 +
14961 +/* {{{ proto bool HttpRequest::enableCookies()
14962 + Enable automatic sending of received cookies. Note that customly set cookies will be sent anyway. */
14963 +PHP_METHOD(HttpRequest, enableCookies)
14964 +{
14965 + NO_ARGS {
14966 + getObject(http_request_object, obj);
14967 + RETURN_SUCCESS(http_request_enable_cookies(obj->request));
14968 + }
14969 +
14970 +}
14971 +/* }}} */
14972 +
14973 +/* {{{ proto bool HttpRequest::resetCookies([bool session_only = FALSE])
14974 + Reset all automatically received/sent cookies. Note that customly set cookies are not affected. */
14975 +PHP_METHOD(HttpRequest, resetCookies)
14976 +{
14977 + zend_bool session_only = 0;
14978 + getObject(http_request_object, obj);
14979 +
14980 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &session_only)) {
14981 + RETURN_FALSE;
14982 + }
14983 + RETURN_SUCCESS(http_request_reset_cookies(obj->request, session_only));
14984 +}
14985 +/* }}} */
14986 +
14987 +/* {{{ proto bool HttpRequest::flushCookies()
14988 + Flush internal cookies to the cookiestore file */
14989 +PHP_METHOD(HttpRequest, flushCookies)
14990 +{
14991 + NO_ARGS {
14992 + getObject(http_request_object, obj);
14993 + RETURN_SUCCESS(http_request_flush_cookies(obj->request));
14994 + }
14995 +}
14996 +/* }}} */
14997 +
14998 +/* {{{ proto bool HttpRequest::setUrl(string url)
14999 + Set the request URL. */
15000 +PHP_METHOD(HttpRequest, setUrl)
15001 +{
15002 + char *URL = NULL;
15003 + int URL_len;
15004 +
15005 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
15006 + RETURN_FALSE;
15007 + }
15008 +
15009 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC);
15010 + RETURN_TRUE;
15011 +}
15012 +/* }}} */
15013 +
15014 +/* {{{ proto string HttpRequest::getUrl()
15015 + Get the previously set request URL. */
15016 +PHP_METHOD(HttpRequest, getUrl)
15017 +{
15018 + NO_ARGS;
15019 +
15020 + if (return_value_used) {
15021 + RETURN_PROP(url);
15022 + }
15023 +}
15024 +/* }}} */
15025 +
15026 +/* {{{ proto bool HttpRequest::setMethod(int request_method)
15027 + Set the request method. */
15028 +PHP_METHOD(HttpRequest, setMethod)
15029 +{
15030 + long meth;
15031 +
15032 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
15033 + RETURN_FALSE;
15034 + }
15035 +
15036 + zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC);
15037 + RETURN_TRUE;
15038 +}
15039 +/* }}} */
15040 +
15041 +/* {{{ proto int HttpRequest::getMethod()
15042 + Get the previously set request method. */
15043 +PHP_METHOD(HttpRequest, getMethod)
15044 +{
15045 + NO_ARGS;
15046 +
15047 + if (return_value_used) {
15048 + RETURN_PROP(method);
15049 + }
15050 +}
15051 +/* }}} */
15052 +
15053 +/* {{{ proto bool HttpRequest::setContentType(string content_type)
15054 + Set the content type the post request should have. */
15055 +PHP_METHOD(HttpRequest, setContentType)
15056 +{
15057 + char *ctype;
15058 + int ct_len;
15059 +
15060 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
15061 + RETURN_FALSE;
15062 + }
15063 +
15064 + if (ct_len) {
15065 + HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
15066 + }
15067 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("contentType")-1, ctype, ct_len TSRMLS_CC);
15068 + RETURN_TRUE;
15069 +}
15070 +/* }}} */
15071 +
15072 +/* {{{ proto string HttpRequest::getContentType()
15073 + Get the previously content type. */
15074 +PHP_METHOD(HttpRequest, getContentType)
15075 +{
15076 + NO_ARGS;
15077 +
15078 + if (return_value_used) {
15079 + RETURN_PROP(contentType);
15080 + }
15081 +}
15082 +/* }}} */
15083 +
15084 +/* {{{ proto bool HttpRequest::setQueryData([mixed query_data])
15085 + Set the URL query parameters to use, overwriting previously set query parameters. */
15086 +PHP_METHOD(HttpRequest, setQueryData)
15087 +{
15088 + zval *qdata = NULL;
15089 +
15090 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!", &qdata)) {
15091 + RETURN_FALSE;
15092 + }
15093 +
15094 + if ((!qdata) || Z_TYPE_P(qdata) == IS_NULL) {
15095 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, "", 0 TSRMLS_CC);
15096 + } else if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
15097 + char *query_data = NULL;
15098 +
15099 + if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) {
15100 + RETURN_FALSE;
15101 + }
15102 +
15103 + zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data TSRMLS_CC);
15104 + efree(query_data);
15105 + } else {
15106 + zval *data = http_zsep(IS_STRING, qdata);
15107 +
15108 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, Z_STRVAL_P(data), Z_STRLEN_P(data) TSRMLS_CC);
15109 + zval_ptr_dtor(&data);
15110 + }
15111 + RETURN_TRUE;
15112 +}
15113 +/* }}} */
15114 +
15115 +/* {{{ proto string HttpRequest::getQueryData()
15116 + Get the current query data in form of an urlencoded query string. */
15117 +PHP_METHOD(HttpRequest, getQueryData)
15118 +{
15119 + NO_ARGS;
15120 +
15121 + if (return_value_used) {
15122 + RETURN_PROP(queryData);
15123 + }
15124 +}
15125 +/* }}} */
15126 +
15127 +/* {{{ proto bool HttpRequest::addQueryData(array query_params)
15128 + Add parameters to the query parameter list, leaving previously set unchanged. */
15129 +PHP_METHOD(HttpRequest, addQueryData)
15130 +{
15131 + zval *qdata, *old_qdata;
15132 + char *query_data = NULL;
15133 + size_t query_data_len = 0;
15134 +
15135 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &qdata)) {
15136 + RETURN_FALSE;
15137 + }
15138 +
15139 + old_qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC);
15140 +
15141 + 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)) {
15142 + RETURN_FALSE;
15143 + }
15144 +
15145 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data, query_data_len TSRMLS_CC);
15146 + efree(query_data);
15147 +
15148 + RETURN_TRUE;
15149 +}
15150 +/* }}} */
15151 +
15152 +/* {{{ proto bool HttpRequest::addPostFields(array post_data)
15153 + Adds POST data entries, leaving previously set unchanged, unless a post entry with the same name already exists. */
15154 +PHP_METHOD(HttpRequest, addPostFields)
15155 +{
15156 + zval *post_data, *old_post, *new_post;
15157 +
15158 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &post_data)) {
15159 + RETURN_FALSE;
15160 + }
15161 +
15162 + if (zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
15163 + MAKE_STD_ZVAL(new_post);
15164 + array_init(new_post);
15165 + old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, 0 TSRMLS_CC);
15166 + if (Z_TYPE_P(old_post) == IS_ARRAY) {
15167 + array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
15168 + }
15169 + array_join(Z_ARRVAL_P(post_data), Z_ARRVAL_P(new_post), 0, 0);
15170 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, new_post TSRMLS_CC);
15171 + zval_ptr_dtor(&new_post);
15172 + }
15173 +
15174 + RETURN_TRUE;
15175 +}
15176 +/* }}} */
15177 +
15178 +/* {{{ proto bool HttpRequest::setPostFields([array post_data])
15179 + Set the POST data entries, overwriting previously set POST data. */
15180 +PHP_METHOD(HttpRequest, setPostFields)
15181 +{
15182 + zval *post, *post_data = NULL;
15183 +
15184 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &post_data)) {
15185 + RETURN_FALSE;
15186 + }
15187 +
15188 + MAKE_STD_ZVAL(post);
15189 + array_init(post);
15190 + if (post_data && zend_hash_num_elements(Z_ARRVAL_P(post_data))) {
15191 + array_copy(Z_ARRVAL_P(post_data), Z_ARRVAL_P(post));
15192 + }
15193 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, post TSRMLS_CC);
15194 + zval_ptr_dtor(&post);
15195 +
15196 + RETURN_TRUE;
15197 +}
15198 +/* }}}*/
15199 +
15200 +/* {{{ proto array HttpRequest::getPostFields()
15201 + Get previously set POST data. */
15202 +PHP_METHOD(HttpRequest, getPostFields)
15203 +{
15204 + NO_ARGS;
15205 +
15206 + if (return_value_used) {
15207 + RETURN_PROP(postFields);
15208 + }
15209 +}
15210 +/* }}} */
15211 +
15212 +/* {{{ proto bool HttpRequest::setBody([string request_body_data])
15213 + Set request body to send, overwriting previously set request body. Don't forget to specify a content type. */
15214 +PHP_METHOD(HttpRequest, setBody)
15215 +{
15216 + char *raw_data = NULL;
15217 + int data_len = 0;
15218 +
15219 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &raw_data, &data_len)) {
15220 + RETURN_FALSE;
15221 + }
15222 +
15223 + if (!raw_data) {
15224 + raw_data = "";
15225 + }
15226 +
15227 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC);
15228 + RETURN_TRUE;
15229 +}
15230 +/* }}} */
15231 +
15232 +/* {{{ proto bool HttpRequest::addBody(string request_body_data)
15233 + Add request body data, leaving previously set request body data unchanged. */
15234 +PHP_METHOD(HttpRequest, addBody)
15235 +{
15236 + char *raw_data;
15237 + int data_len;
15238 +
15239 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &raw_data, &data_len)) {
15240 + RETURN_FALSE;
15241 + }
15242 +
15243 + if (data_len) {
15244 + zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC);
15245 +
15246 + if (Z_STRLEN_P(data)) {
15247 + Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1);
15248 + Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0';
15249 + memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, raw_data, data_len);
15250 + } else {
15251 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC);
15252 + }
15253 + }
15254 +
15255 + RETURN_TRUE;
15256 +}
15257 +/* }}} */
15258 +
15259 +/* {{{ proto string HttpRequest::getBody()
15260 + Get previously set request body data. */
15261 +PHP_METHOD(HttpRequest, getBody)
15262 +{
15263 + NO_ARGS;
15264 +
15265 + if (return_value_used) {
15266 + RETURN_PROP(requestBody);
15267 + }
15268 +}
15269 +/* }}} */
15270 +
15271 +/* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
15272 + Add a file to the POST request, leaving previously set files unchanged. */
15273 +PHP_METHOD(HttpRequest, addPostFile)
15274 +{
15275 + zval *entry, *old_post, *new_post;
15276 + char *name, *file, *type = NULL;
15277 + int name_len, file_len, type_len = 0;
15278 +
15279 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
15280 + RETURN_FALSE;
15281 + }
15282 +
15283 + if (type_len) {
15284 + HTTP_CHECK_CONTENT_TYPE(type, RETURN_FALSE);
15285 + } else {
15286 + type = "application/x-octetstream";
15287 + type_len = sizeof("application/x-octetstream") - 1;
15288 + }
15289 +
15290 + MAKE_STD_ZVAL(entry);
15291 + array_init(entry);
15292 +
15293 + add_assoc_stringl(entry, "name", name, name_len, 1);
15294 + add_assoc_stringl(entry, "type", type, type_len, 1);
15295 + add_assoc_stringl(entry, "file", file, file_len, 1);
15296 +
15297 + MAKE_STD_ZVAL(new_post);
15298 + array_init(new_post);
15299 + old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, 0 TSRMLS_CC);
15300 + if (Z_TYPE_P(old_post) == IS_ARRAY) {
15301 + array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post));
15302 + }
15303 + add_next_index_zval(new_post, entry);
15304 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, new_post TSRMLS_CC);
15305 + zval_ptr_dtor(&new_post);
15306 +
15307 + RETURN_TRUE;
15308 +}
15309 +/* }}} */
15310 +
15311 +/* {{{ proto bool HttpRequest::setPostFiles([array post_files])
15312 + Set files to post, overwriting previously set post files. */
15313 +PHP_METHOD(HttpRequest, setPostFiles)
15314 +{
15315 + zval *files = NULL, *post;
15316 +
15317 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!/", &files)) {
15318 + RETURN_FALSE;
15319 + }
15320 +
15321 + MAKE_STD_ZVAL(post);
15322 + array_init(post);
15323 + if (files && (Z_TYPE_P(files) == IS_ARRAY)) {
15324 + array_copy(Z_ARRVAL_P(files), Z_ARRVAL_P(post));
15325 + }
15326 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, post TSRMLS_CC);
15327 + zval_ptr_dtor(&post);
15328 +
15329 + RETURN_TRUE;
15330 +}
15331 +/* }}} */
15332 +
15333 +/* {{{ proto array HttpRequest::getPostFiles()
15334 + Get all previously added POST files. */
15335 +PHP_METHOD(HttpRequest, getPostFiles)
15336 +{
15337 + NO_ARGS;
15338 +
15339 + if (return_value_used) {
15340 + RETURN_PROP(postFiles);
15341 + }
15342 +}
15343 +/* }}} */
15344 +
15345 +/* {{{ proto bool HttpRequest::setPutFile([string file])
15346 + Set file to put. Affects only PUT requests. */
15347 +PHP_METHOD(HttpRequest, setPutFile)
15348 +{
15349 + char *file = "";
15350 + int file_len = 0;
15351 +
15352 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &file, &file_len)) {
15353 + RETURN_FALSE;
15354 + }
15355 +
15356 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putFile")-1, file, file_len TSRMLS_CC);
15357 + RETURN_TRUE;
15358 +}
15359 +/* }}} */
15360 +
15361 +/* {{{ proto string HttpRequest::getPutFile()
15362 + Get previously set put file. */
15363 +PHP_METHOD(HttpRequest, getPutFile)
15364 +{
15365 + NO_ARGS;
15366 +
15367 + if (return_value_used) {
15368 + RETURN_PROP(putFile);
15369 + }
15370 +}
15371 +/* }}} */
15372 +
15373 +/* {{{ proto bool HttpRequest::setPutData([string put_data])
15374 + Set PUT data to send, overwriting previously set PUT data. */
15375 +PHP_METHOD(HttpRequest, setPutData)
15376 +{
15377 + char *put_data = NULL;
15378 + int data_len = 0;
15379 +
15380 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &put_data, &data_len)) {
15381 + RETURN_FALSE;
15382 + }
15383 +
15384 + if (!put_data) {
15385 + put_data = "";
15386 + }
15387 +
15388 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC);
15389 + RETURN_TRUE;
15390 +}
15391 +/* }}} */
15392 +
15393 +/* {{{ proto bool HttpRequest::addPutData(string put_data)
15394 + Add PUT data, leaving previously set PUT data unchanged. */
15395 +PHP_METHOD(HttpRequest, addPutData)
15396 +{
15397 + char *put_data;
15398 + int data_len;
15399 +
15400 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &put_data, &data_len)) {
15401 + RETURN_FALSE;
15402 + }
15403 +
15404 + if (data_len) {
15405 + zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC);
15406 +
15407 + if (Z_STRLEN_P(data)) {
15408 + Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1);
15409 + Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0';
15410 + memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, put_data, data_len);
15411 + } else {
15412 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC);
15413 + }
15414 + }
15415 +
15416 + RETURN_TRUE;
15417 +}
15418 +/* }}} */
15419 +
15420 +/* {{{ proto string HttpRequest::getPutData()
15421 + Get previously set PUT data. */
15422 +PHP_METHOD(HttpRequest, getPutData)
15423 +{
15424 + NO_ARGS;
15425 +
15426 + if (return_value_used) {
15427 + RETURN_PROP(putData);
15428 + }
15429 +}
15430 +/* }}} */
15431 +
15432 +/* {{{ proto array HttpRequest::getResponseData()
15433 + Get all response data after the request has been sent. */
15434 +PHP_METHOD(HttpRequest, getResponseData)
15435 +{
15436 + NO_ARGS;
15437 +
15438 + if (return_value_used) {
15439 + char *body;
15440 + size_t body_len;
15441 + zval *headers, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15442 +
15443 + if (Z_TYPE_P(message) == IS_OBJECT) {
15444 + getObjectEx(http_message_object, msg, message);
15445 +
15446 + array_init(return_value);
15447 +
15448 + MAKE_STD_ZVAL(headers);
15449 + array_init(headers);
15450 + zend_hash_copy(Z_ARRVAL_P(headers), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
15451 + add_assoc_zval(return_value, "headers", headers);
15452 +
15453 + phpstr_data(PHPSTR(msg->message), &body, &body_len);
15454 + add_assoc_stringl(return_value, "body", body, body_len, 0);
15455 + }
15456 + }
15457 +}
15458 +/* }}} */
15459 +
15460 +/* {{{ proto mixed HttpRequest::getResponseHeader([string name])
15461 + Get response header(s) after the request has been sent. */
15462 +PHP_METHOD(HttpRequest, getResponseHeader)
15463 +{
15464 + if (return_value_used) {
15465 + zval *header;
15466 + char *header_name = NULL;
15467 + int header_len = 0;
15468 +
15469 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) {
15470 + zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15471 +
15472 + if (Z_TYPE_P(message) == IS_OBJECT) {
15473 + getObjectEx(http_message_object, msg, message);
15474 +
15475 + if (header_len) {
15476 + if ((header = http_message_header_ex(msg->message, pretty_key(header_name, header_len, 1, 1), header_len + 1, 0))) {
15477 + RETURN_ZVAL(header, 1, 1);
15478 + }
15479 + } else {
15480 + array_init(return_value);
15481 + zend_hash_copy(Z_ARRVAL_P(return_value), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
15482 + return;
15483 + }
15484 + }
15485 + }
15486 + RETURN_FALSE;
15487 + }
15488 +}
15489 +/* }}} */
15490 +
15491 +/* {{{ proto array HttpRequest::getResponseCookies([int flags[, array allowed_extras]])
15492 + Get response cookie(s) after the request has been sent. */
15493 +PHP_METHOD(HttpRequest, getResponseCookies)
15494 +{
15495 + if (return_value_used) {
15496 + long flags = 0;
15497 + zval *allowed_extras_array = NULL;
15498 +
15499 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|la!", &flags, &allowed_extras_array)) {
15500 + int i = 0;
15501 + HashKey key = initHashKey(0);
15502 + char **allowed_extras = NULL;
15503 + zval **header = NULL, **entry = NULL, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15504 + HashPosition pos, pos1, pos2;
15505 +
15506 + if (Z_TYPE_P(message) == IS_OBJECT) {
15507 + getObjectEx(http_message_object, msg, message);
15508 +
15509 + array_init(return_value);
15510 +
15511 + if (allowed_extras_array) {
15512 + allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
15513 + FOREACH_VAL(pos, allowed_extras_array, entry) {
15514 + zval *data = http_zsep(IS_STRING, *entry);
15515 + allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
15516 + zval_ptr_dtor(&data);
15517 + }
15518 + }
15519 +
15520 + FOREACH_HASH_KEYVAL(pos1, &msg->message->hdrs, key, header) {
15521 + if (key.type == HASH_KEY_IS_STRING && !strcasecmp(key.str, "Set-Cookie")) {
15522 + http_cookie_list list;
15523 +
15524 + if (Z_TYPE_PP(header) == IS_ARRAY) {
15525 + zval **single_header;
15526 +
15527 + FOREACH_VAL(pos2, *header, single_header) {
15528 + zval *data = http_zsep(IS_STRING, *single_header);
15529 +
15530 + if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) {
15531 + zval *cookie;
15532 +
15533 + MAKE_STD_ZVAL(cookie);
15534 + object_init(cookie);
15535 + http_cookie_list_tostruct(&list, cookie);
15536 + add_next_index_zval(return_value, cookie);
15537 + http_cookie_list_dtor(&list);
15538 + }
15539 + zval_ptr_dtor(&data);
15540 + }
15541 + } else {
15542 + zval *data = http_zsep(IS_STRING, *header);
15543 + if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) {
15544 + zval *cookie;
15545 +
15546 + MAKE_STD_ZVAL(cookie);
15547 + object_init(cookie);
15548 + http_cookie_list_tostruct(&list, cookie);
15549 + add_next_index_zval(return_value, cookie);
15550 + http_cookie_list_dtor(&list);
15551 + }
15552 + zval_ptr_dtor(&data);
15553 + }
15554 + }
15555 + }
15556 +
15557 + if (allowed_extras) {
15558 + for (i = 0; allowed_extras[i]; ++i) {
15559 + efree(allowed_extras[i]);
15560 + }
15561 + efree(allowed_extras);
15562 + }
15563 +
15564 + return;
15565 + }
15566 + }
15567 + RETURN_FALSE;
15568 + }
15569 +}
15570 +/* }}} */
15571 +
15572 +/* {{{ proto string HttpRequest::getResponseBody()
15573 + Get the response body after the request has been sent. */
15574 +PHP_METHOD(HttpRequest, getResponseBody)
15575 +{
15576 + NO_ARGS;
15577 +
15578 + if (return_value_used) {
15579 + zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15580 +
15581 + if (Z_TYPE_P(message) == IS_OBJECT) {
15582 + getObjectEx(http_message_object, msg, message);
15583 + RETURN_PHPSTR_DUP(&msg->message->body);
15584 + } else {
15585 + RETURN_FALSE;
15586 + }
15587 + }
15588 +}
15589 +/* }}} */
15590 +
15591 +/* {{{ proto int HttpRequest::getResponseCode()
15592 + Get the response code after the request has been sent. */
15593 +PHP_METHOD(HttpRequest, getResponseCode)
15594 +{
15595 + NO_ARGS;
15596 +
15597 + if (return_value_used) {
15598 + RETURN_PROP(responseCode);
15599 + }
15600 +}
15601 +/* }}} */
15602 +
15603 +/* {{{ proto string HttpRequest::getResponseStatus()
15604 + Get the response status (i.e. the string after the response code) after the message has been sent. */
15605 +PHP_METHOD(HttpRequest, getResponseStatus)
15606 +{
15607 + NO_ARGS;
15608 +
15609 + if (return_value_used) {
15610 + RETURN_PROP(responseStatus);
15611 + }
15612 +}
15613 +/* }}} */
15614 +
15615 +/* {{{ proto mixed HttpRequest::getResponseInfo([string name])
15616 + Get response info after the request has been sent. */
15617 +PHP_METHOD(HttpRequest, getResponseInfo)
15618 +{
15619 + if (return_value_used) {
15620 + zval *info, **infop;
15621 + char *info_name = NULL;
15622 + int info_len = 0;
15623 +
15624 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) {
15625 + RETURN_FALSE;
15626 + }
15627 +
15628 + info = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, 0 TSRMLS_CC);
15629 +
15630 + if (Z_TYPE_P(info) != IS_ARRAY) {
15631 + RETURN_FALSE;
15632 + }
15633 +
15634 + if (info_len && info_name) {
15635 + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void *) &infop)) {
15636 + RETURN_ZVAL(*infop, 1, 0);
15637 + } else {
15638 + http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Could not find response info named %s", info_name);
15639 + RETURN_FALSE;
15640 + }
15641 + } else {
15642 + RETURN_ZVAL(info, 1, 0);
15643 + }
15644 + }
15645 +}
15646 +/* }}}*/
15647 +
15648 +/* {{{ proto HttpMessage HttpRequest::getResponseMessage()
15649 + Get the full response as HttpMessage object after the request has been sent. */
15650 +PHP_METHOD(HttpRequest, getResponseMessage)
15651 +{
15652 + NO_ARGS {
15653 + zval *message;
15654 +
15655 + SET_EH_THROW_HTTP();
15656 + message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC);
15657 + if (Z_TYPE_P(message) == IS_OBJECT) {
15658 + RETVAL_OBJECT(message, 1);
15659 + } else {
15660 + http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpRequest does not contain a response message");
15661 + }
15662 + SET_EH_NORMAL();
15663 + }
15664 +}
15665 +/* }}} */
15666 +
15667 +/* {{{ proto HttpMessage HttpRequest::getRequestMessage()
15668 + Get sent HTTP message. */
15669 +PHP_METHOD(HttpRequest, getRequestMessage)
15670 +{
15671 + NO_ARGS;
15672 +
15673 + if (return_value_used) {
15674 + http_message *msg;
15675 + getObject(http_request_object, obj);
15676 +
15677 + SET_EH_THROW_HTTP();
15678 + if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) {
15679 + RETVAL_OBJVAL(http_request_object_message(getThis(), msg), 0);
15680 + }
15681 + SET_EH_NORMAL();
15682 + }
15683 +}
15684 +/* }}} */
15685 +
15686 +/* {{{ proto string HttpRequest::getRawRequestMessage()
15687 + Get sent HTTP message. */
15688 +PHP_METHOD(HttpRequest, getRawRequestMessage)
15689 +{
15690 + NO_ARGS;
15691 +
15692 + if (return_value_used) {
15693 + getObject(http_request_object, obj);
15694 +
15695 + RETURN_PHPSTR_DUP(&obj->request->conv.request);
15696 + }
15697 +}
15698 +/* }}} */
15699 +
15700 +/* {{{ proto string HttpRequest::getRawResponseMessage()
15701 + Get the entire HTTP response. */
15702 +PHP_METHOD(HttpRequest, getRawResponseMessage)
15703 +{
15704 + NO_ARGS;
15705 +
15706 + if (return_value_used) {
15707 + getObject(http_request_object, obj);
15708 +
15709 + RETURN_PHPSTR_DUP(&obj->request->conv.response);
15710 + }
15711 +}
15712 +/* }}} */
15713 +
15714 +/* {{{ proto HttpMessage HttpRequest::getHistory()
15715 + Get all sent requests and received responses as an HttpMessage object. */
15716 +PHP_METHOD(HttpRequest, getHistory)
15717 +{
15718 + NO_ARGS;
15719 +
15720 + if (return_value_used) {
15721 + zval *hist;
15722 +
15723 + SET_EH_THROW_HTTP();
15724 + hist = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC);
15725 + if (Z_TYPE_P(hist) == IS_OBJECT) {
15726 + RETVAL_OBJECT(hist, 1);
15727 + } else {
15728 + http_error(HE_WARNING, HTTP_E_RUNTIME, "The history is empty");
15729 + }
15730 + SET_EH_NORMAL();
15731 + }
15732 +}
15733 +/* }}} */
15734 +
15735 +/* {{{ proto void HttpRequest::clearHistory()
15736 + Clear the history. */
15737 +PHP_METHOD(HttpRequest, clearHistory)
15738 +{
15739 + NO_ARGS {
15740 + zval *hist;
15741 +
15742 + MAKE_STD_ZVAL(hist);
15743 + ZVAL_NULL(hist);
15744 + zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC);
15745 + zval_ptr_dtor(&hist);
15746 + }
15747 +}
15748 +/* }}} */
15749 +
15750 +/* {{{ proto string HttpRequest::getMessageClass()
15751 + Get the message class name. */
15752 +PHP_METHOD(HttpRequest, getMessageClass)
15753 +{
15754 + NO_ARGS;
15755 +
15756 + if (return_value_used) {
15757 + RETURN_PROP("messageClass");
15758 + }
15759 +}
15760 +/* }}} */
15761 +
15762 +/* {{{ proto void setMessageClass(string class_name)
15763 + Set the message class name. */
15764 +PHP_METHOD(HttpRequest, setMessageClass)
15765 +{
15766 + char *cn;
15767 + int cl;
15768 +
15769 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &cn, &cl)) {
15770 + zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, cn, cl TSRMLS_CC);
15771 + }
15772 +}
15773 +/* }}} */
15774 +
15775 +/* {{{ proto HttpMessage HttpRequest::send()
15776 + Send the HTTP request. */
15777 +PHP_METHOD(HttpRequest, send)
15778 +{
15779 + getObject(http_request_object, obj);
15780 +
15781 + NO_ARGS;
15782 +
15783 + SET_EH_THROW_HTTP();
15784 +
15785 + RETVAL_FALSE;
15786 +
15787 + if (obj->pool) {
15788 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool");
15789 + } else if (SUCCESS == http_request_object_requesthandler(obj, getThis())) {
15790 + http_request_exec(obj->request);
15791 + if (SUCCESS == http_request_object_responsehandler(obj, getThis())) {
15792 + RETVAL_OBJECT(zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC), 1);
15793 + }
15794 + }
15795 +
15796 + SET_EH_NORMAL();
15797 +}
15798 +/* }}} */
15799 +
15800 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
15801 +
15802 +/*
15803 + * Local variables:
15804 + * tab-width: 4
15805 + * c-basic-offset: 4
15806 + * End:
15807 + * vim600: noet sw=4 ts=4 fdm=marker
15808 + * vim<600: noet sw=4 ts=4
15809 + */
15810 +
15811 --- /dev/null
15812 +++ b/ext/http/http_request_pool_api.c
15813 @@ -0,0 +1,660 @@
15814 +/*
15815 + +--------------------------------------------------------------------+
15816 + | PECL :: http |
15817 + +--------------------------------------------------------------------+
15818 + | Redistribution and use in source and binary forms, with or without |
15819 + | modification, are permitted provided that the conditions mentioned |
15820 + | in the accompanying LICENSE file are met. |
15821 + +--------------------------------------------------------------------+
15822 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
15823 + +--------------------------------------------------------------------+
15824 +*/
15825 +
15826 +/* $Id: http_request_pool_api.c 292841 2009-12-31 08:48:57Z mike $ */
15827 +
15828 +#define HTTP_WANT_CURL
15829 +#define HTTP_WANT_EVENT
15830 +#include "php_http.h"
15831 +
15832 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
15833 +
15834 +#include "php_http_api.h"
15835 +#include "php_http_exception_object.h"
15836 +#include "php_http_persistent_handle_api.h"
15837 +#include "php_http_request_api.h"
15838 +#include "php_http_request_object.h"
15839 +#include "php_http_request_pool_api.h"
15840 +#include "php_http_requestpool_object.h"
15841 +
15842 +#ifndef HTTP_DEBUG_REQPOOLS
15843 +# define HTTP_DEBUG_REQPOOLS 0
15844 +#endif
15845 +
15846 +#ifdef HTTP_HAVE_EVENT
15847 +typedef struct _http_request_pool_event_t {
15848 + struct event evnt;
15849 + http_request_pool *pool;
15850 +} http_request_pool_event;
15851 +
15852 +static void http_request_pool_timeout_callback(int socket, short action, void *event_data);
15853 +static void http_request_pool_event_callback(int socket, short action, void *event_data);
15854 +static int http_request_pool_socket_callback(CURL *easy, curl_socket_t s, int action, void *, void *);
15855 +static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data);
15856 +#endif
15857 +
15858 +static int http_request_pool_compare_handles(void *h1, void *h2);
15859 +
15860 +PHP_MINIT_FUNCTION(http_request_pool)
15861 +{
15862 + if (SUCCESS != http_persistent_handle_provide("http_request_pool", curl_multi_init, (http_persistent_handle_dtor) curl_multi_cleanup, NULL)) {
15863 + return FAILURE;
15864 + }
15865 + return SUCCESS;
15866 +}
15867 +
15868 +#ifdef HTTP_HAVE_EVENT
15869 +PHP_RINIT_FUNCTION(http_request_pool)
15870 +{
15871 + if (!HTTP_G->request.pool.event.base && !(HTTP_G->request.pool.event.base = event_init())) {
15872 + return FAILURE;
15873 + }
15874 +
15875 + return SUCCESS;
15876 +}
15877 +#endif
15878 +
15879 +/* {{{ http_request_pool *http_request_pool_init(http_request_pool *) */
15880 +PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC)
15881 +{
15882 + zend_bool free_pool;
15883 +
15884 +#if HTTP_DEBUG_REQPOOLS
15885 + fprintf(stderr, "Initializing request pool %p\n", pool);
15886 +#endif
15887 +
15888 + if ((free_pool = (!pool))) {
15889 + pool = emalloc(sizeof(http_request_pool));
15890 + pool->ch = NULL;
15891 + }
15892 +
15893 + if (SUCCESS != http_persistent_handle_acquire("http_request_pool", &pool->ch)) {
15894 + if (free_pool) {
15895 + efree(pool);
15896 + }
15897 + return NULL;
15898 + }
15899 +
15900 + TSRMLS_SET_CTX(pool->tsrm_ls);
15901 +
15902 +#ifdef HTTP_HAVE_EVENT
15903 + pool->timeout = ecalloc(1, sizeof(struct event));
15904 + curl_multi_setopt(pool->ch, CURLMOPT_SOCKETDATA, pool);
15905 + curl_multi_setopt(pool->ch, CURLMOPT_SOCKETFUNCTION, http_request_pool_socket_callback);
15906 + curl_multi_setopt(pool->ch, CURLMOPT_TIMERDATA, pool);
15907 + curl_multi_setopt(pool->ch, CURLMOPT_TIMERFUNCTION, http_request_pool_timer_callback);
15908 +#endif
15909 +
15910 + pool->unfinished = 0;
15911 + zend_llist_init(&pool->finished, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0);
15912 + zend_llist_init(&pool->handles, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0);
15913 +
15914 +#if HTTP_DEBUG_REQPOOLS
15915 + fprintf(stderr, "Initialized request pool %p\n", pool);
15916 +#endif
15917 +
15918 + return pool;
15919 +}
15920 +/* }}} */
15921 +
15922 +/* {{{ STATUS http_request_pool_attach(http_request_pool *, zval *) */
15923 +PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request)
15924 +{
15925 +#ifdef ZTS
15926 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
15927 +#endif
15928 + getObjectEx(http_request_object, req, request);
15929 +
15930 +#if HTTP_DEBUG_REQPOOLS
15931 + fprintf(stderr, "Attaching HttpRequest(#%d) %p to pool %p\n", Z_OBJ_HANDLE_P(request), req, pool);
15932 +#endif
15933 +
15934 + if (req->pool) {
15935 + 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");
15936 + } else if (SUCCESS != http_request_object_requesthandler(req, request)) {
15937 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not initialize HttpRequest object(#%d) for attaching to the HttpRequestPool", Z_OBJ_HANDLE_P(request));
15938 + } else {
15939 + CURLMcode code = curl_multi_add_handle(pool->ch, req->request->ch);
15940 +
15941 + if (CURLM_OK != code) {
15942 + 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));
15943 + } else {
15944 + req->pool = pool;
15945 +
15946 + ZVAL_ADDREF(request);
15947 + zend_llist_add_element(&pool->handles, &request);
15948 + ++pool->unfinished;
15949 +
15950 +#if HTTP_DEBUG_REQPOOLS
15951 + fprintf(stderr, "> %d HttpRequests attached to pool %p\n", zend_llist_count(&pool->handles), pool);
15952 +#endif
15953 + return SUCCESS;
15954 + }
15955 + }
15956 + return FAILURE;
15957 +}
15958 +/* }}} */
15959 +
15960 +/* {{{ STATUS http_request_pool_detach(http_request_pool *, zval *) */
15961 +PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request)
15962 +{
15963 + CURLMcode code;
15964 +#ifdef ZTS
15965 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
15966 +#endif
15967 + getObjectEx(http_request_object, req, request);
15968 +
15969 +#if HTTP_DEBUG_REQPOOLS
15970 + fprintf(stderr, "Detaching HttpRequest(#%d) %p from pool %p\n", Z_OBJ_HANDLE_P(request), req, pool);
15971 +#endif
15972 +
15973 + if (!req->pool) {
15974 + /* not attached to any pool */
15975 +#if HTTP_DEBUG_REQPOOLS
15976 + fprintf(stderr, "HttpRequest object(#%d) %p is not attached to any HttpRequestPool\n", Z_OBJ_HANDLE_P(request), req);
15977 +#endif
15978 + } else if (req->pool != pool) {
15979 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is not attached to this HttpRequestPool", Z_OBJ_HANDLE_P(request));
15980 + } else if (req->request->_in_progress_cb) {
15981 + 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));
15982 + } else if (CURLM_OK != (code = curl_multi_remove_handle(pool->ch, req->request->ch))) {
15983 + 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));
15984 + } else {
15985 + req->pool = NULL;
15986 + zend_llist_del_element(&pool->finished, request, http_request_pool_compare_handles);
15987 + zend_llist_del_element(&pool->handles, request, http_request_pool_compare_handles);
15988 +
15989 +#if HTTP_DEBUG_REQPOOLS
15990 + fprintf(stderr, "> %d HttpRequests remaining in pool %p\n", zend_llist_count(&pool->handles), pool);
15991 +#endif
15992 +
15993 + return SUCCESS;
15994 + }
15995 + return FAILURE;
15996 +}
15997 +/* }}} */
15998 +
15999 +/* {{{ void http_request_pool_apply(http_request_pool *, http_request_pool_apply_func) */
16000 +PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb)
16001 +{
16002 + int count = zend_llist_count(&pool->handles);
16003 +
16004 + if (count) {
16005 + int i = 0;
16006 + zend_llist_position pos;
16007 + zval **handle, **handles = emalloc(count * sizeof(zval *));
16008 +
16009 + for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) {
16010 + handles[i++] = *handle;
16011 + }
16012 +
16013 + /* should never happen */
16014 + if (i != count) {
16015 + zend_error(E_ERROR, "number of fetched request handles do not match overall count");
16016 + count = i;
16017 + }
16018 +
16019 + for (i = 0; i < count; ++i) {
16020 + if (cb(pool, handles[i])) {
16021 + break;
16022 + }
16023 + }
16024 + efree(handles);
16025 + }
16026 +}
16027 +/* }}} */
16028 +
16029 +/* {{{ void http_request_pool_apply_with_arg(http_request_pool *, http_request_pool_apply_with_arg_func, void *) */
16030 +PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg)
16031 +{
16032 + int count = zend_llist_count(&pool->handles);
16033 +
16034 + if (count) {
16035 + int i = 0;
16036 + zend_llist_position pos;
16037 + zval **handle, **handles = emalloc(count * sizeof(zval *));
16038 +
16039 + for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) {
16040 + handles[i++] = *handle;
16041 + }
16042 +
16043 + /* should never happen */
16044 + if (i != count) {
16045 + zend_error(E_ERROR, "number of fetched request handles do not match overall count");
16046 + count = i;
16047 + }
16048 +
16049 + for (i = 0; i < count; ++i) {
16050 + if (cb(pool, handles[i], arg)) {
16051 + break;
16052 + }
16053 + }
16054 + efree(handles);
16055 + }
16056 +}
16057 +/* }}} */
16058 +
16059 +/* {{{ void http_request_pool_detach_all(http_request_pool *) */
16060 +PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool)
16061 +{
16062 +#if HTTP_DEBUG_REQPOOLS
16063 + fprintf(stderr, "Detaching %d requests from pool %p\n", zend_llist_count(&pool->handles), pool);
16064 +#endif
16065 + http_request_pool_apply(pool, _http_request_pool_detach);
16066 +}
16067 +/* }}} */
16068 +
16069 +/* {{{ STATUS http_request_pool_send(http_request_pool *) */
16070 +PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool)
16071 +{
16072 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16073 +
16074 +#if HTTP_DEBUG_REQPOOLS
16075 + fprintf(stderr, "Attempt to send %d requests of pool %p\n", zend_llist_count(&pool->handles), pool);
16076 +#endif
16077 +
16078 +#ifdef HTTP_HAVE_EVENT
16079 + if (pool->useevents) {
16080 + do {
16081 +#if HTTP_DEBUG_REQPOOLS
16082 + fprintf(stderr, "& Starting event dispatcher of pool %p\n", pool);
16083 +#endif
16084 + event_base_dispatch(HTTP_G->request.pool.event.base);
16085 + } while (pool->unfinished);
16086 + } else
16087 +#endif
16088 + {
16089 + while (http_request_pool_perform(pool)) {
16090 + if (SUCCESS != http_request_pool_select(pool)) {
16091 +#ifdef PHP_WIN32
16092 + /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */
16093 + http_error_ex(HE_WARNING, HTTP_E_SOCKET, "WinSock error: %d", WSAGetLastError());
16094 +#else
16095 + http_error(HE_WARNING, HTTP_E_SOCKET, strerror(errno));
16096 +#endif
16097 + return FAILURE;
16098 + }
16099 + }
16100 + }
16101 +
16102 +#if HTTP_DEBUG_REQPOOLS
16103 + fprintf(stderr, "Finished sending %d HttpRequests of pool %p (still unfinished: %d)\n", zend_llist_count(&pool->handles), pool, pool->unfinished);
16104 +#endif
16105 +
16106 + return SUCCESS;
16107 +}
16108 +/* }}} */
16109 +
16110 +/* {{{ void http_request_pool_dtor(http_request_pool *) */
16111 +PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool)
16112 +{
16113 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16114 +
16115 +#if HTTP_DEBUG_REQPOOLS
16116 + fprintf(stderr, "Destructing request pool %p\n", pool);
16117 +#endif
16118 +
16119 +#ifdef HTTP_HAVE_EVENT
16120 + efree(pool->timeout);
16121 +#endif
16122 +
16123 + http_request_pool_detach_all(pool);
16124 +
16125 + pool->unfinished = 0;
16126 + zend_llist_clean(&pool->finished);
16127 + zend_llist_clean(&pool->handles);
16128 + http_persistent_handle_release("http_request_pool", &pool->ch);
16129 +}
16130 +/* }}} */
16131 +
16132 +#ifdef PHP_WIN32
16133 +# define SELECT_ERROR SOCKET_ERROR
16134 +#else
16135 +# define SELECT_ERROR -1
16136 +#endif
16137 +
16138 +/* {{{ STATUS http_request_pool_select(http_request_pool *) */
16139 +PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool)
16140 +{
16141 + return http_request_pool_select_ex(pool, NULL);
16142 +}
16143 +/* }}} */
16144 +
16145 +/* {{{ STATUS http_request_pool_select_ex(http_request_pool *, struct timeval *) */
16146 +PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout)
16147 +{
16148 + int MAX;
16149 + fd_set R, W, E;
16150 + struct timeval timeout;
16151 +
16152 +#ifdef HTTP_HAVE_EVENT
16153 + if (pool->useevents) {
16154 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16155 + http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks");
16156 + return FAILURE;
16157 + }
16158 +#endif
16159 +
16160 + if (custom_timeout && timerisset(custom_timeout)) {
16161 + timeout = *custom_timeout;
16162 + } else {
16163 + http_request_pool_timeout(pool, &timeout);
16164 + }
16165 +
16166 + FD_ZERO(&R);
16167 + FD_ZERO(&W);
16168 + FD_ZERO(&E);
16169 +
16170 + if (CURLM_OK == curl_multi_fdset(pool->ch, &R, &W, &E, &MAX)) {
16171 + if (MAX == -1) {
16172 + http_sleep((double) timeout.tv_sec + (double) (timeout.tv_usec / HTTP_MCROSEC));
16173 + return SUCCESS;
16174 + } else if (SELECT_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) {
16175 + return SUCCESS;
16176 + }
16177 + }
16178 + return FAILURE;
16179 +}
16180 +/* }}} */
16181 +
16182 +/* {{{ int http_request_pool_perform(http_request_pool *) */
16183 +PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool)
16184 +{
16185 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16186 +
16187 +#ifdef HTTP_HAVE_EVENT
16188 + if (pool->useevents) {
16189 + http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks");
16190 + return FAILURE;
16191 + }
16192 +#endif
16193 +
16194 + while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(pool->ch, &pool->unfinished));
16195 +
16196 +#if HTTP_DEBUG_REQPOOLS
16197 + fprintf(stderr, "%u unfinished requests of pool %p remaining\n", pool->unfinished, pool);
16198 +#endif
16199 +
16200 + http_request_pool_responsehandler(pool);
16201 +
16202 + return pool->unfinished;
16203 +}
16204 +/* }}} */
16205 +
16206 +/* {{{ void http_request_pool_responsehandler(http_request_pool *) */
16207 +void _http_request_pool_responsehandler(http_request_pool *pool)
16208 +{
16209 + CURLMsg *msg;
16210 + int remaining = 0;
16211 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16212 +
16213 + do {
16214 + msg = curl_multi_info_read(pool->ch, &remaining);
16215 + if (msg && CURLMSG_DONE == msg->msg) {
16216 + if (CURLE_OK != msg->data.result) {
16217 + http_request_storage *st = http_request_storage_get(msg->easy_handle);
16218 + http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(msg->data.result), st?st->errorbuffer:"", st?st->url:"");
16219 + }
16220 + http_request_pool_apply_with_arg(pool, _http_request_pool_apply_responsehandler, msg->easy_handle);
16221 + }
16222 + } while (remaining);
16223 +}
16224 +/* }}} */
16225 +
16226 +/* {{{ int http_request_pool_apply_responsehandler(http_request_pool *, zval *, void *) */
16227 +int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch)
16228 +{
16229 +#ifdef ZTS
16230 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16231 +#endif
16232 + getObjectEx(http_request_object, obj, req);
16233 +
16234 + if ((!ch) || obj->request->ch == (CURL *) ch) {
16235 +
16236 +#if HTTP_DEBUG_REQPOOLS
16237 + fprintf(stderr, "Fetching data from HttpRequest(#%d) %p of pool %p\n", Z_OBJ_HANDLE_P(req), obj, obj->pool);
16238 +#endif
16239 +
16240 + ZVAL_ADDREF(req);
16241 + zend_llist_add_element(&obj->pool->finished, &req);
16242 + http_request_object_responsehandler(obj, req);
16243 + return 1;
16244 + }
16245 + return 0;
16246 +}
16247 +/* }}} */
16248 +
16249 +/* {{{ struct timeval *_http_request_pool_timeout(http_request_pool *, struct timeval *) */
16250 +struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout)
16251 +{
16252 +#ifdef HAVE_CURL_MULTI_TIMEOUT
16253 + long max_tout = 1000;
16254 +
16255 + if ((CURLM_OK == curl_multi_timeout(pool->ch, &max_tout)) && (max_tout > 0)) {
16256 + timeout->tv_sec = max_tout / 1000;
16257 + timeout->tv_usec = (max_tout % 1000) * 1000;
16258 + } else {
16259 +#endif
16260 + timeout->tv_sec = 0;
16261 + timeout->tv_usec = 1000;
16262 +#ifdef HAVE_CURL_MULTI_TIMEOUT
16263 + }
16264 +#endif
16265 +
16266 +#if HTTP_DEBUG_REQPOOLS
16267 + fprintf(stderr, "Calculating timeout (%lu, %lu) of pool %p\n", (ulong) timeout->tv_sec, (ulong) timeout->tv_usec, pool);
16268 +#endif
16269 +
16270 + return timeout;
16271 +}
16272 +/* }}} */
16273 +
16274 +/*#*/
16275 +
16276 +/* {{{ static int http_request_pool_compare_handles(void *, void *) */
16277 +static int http_request_pool_compare_handles(void *h1, void *h2)
16278 +{
16279 + return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
16280 +}
16281 +/* }}} */
16282 +
16283 +#ifdef HTTP_HAVE_EVENT
16284 +/* {{{ static void http_request_pool_timeout_callback(int, short, void *) */
16285 +static void http_request_pool_timeout_callback(int socket, short action, void *event_data)
16286 +{
16287 + http_request_pool *pool = event_data;
16288 +
16289 + if (pool->useevents) {
16290 + CURLMcode rc;
16291 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16292 +
16293 +#if HTTP_DEBUG_REQPOOLS
16294 + fprintf(stderr, "Timeout occurred of pool %p\n", pool);
16295 +#endif
16296 +
16297 + while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket(pool->ch, CURL_SOCKET_TIMEOUT, &pool->unfinished)));
16298 +
16299 + if (CURLM_OK != rc) {
16300 + http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc));
16301 + }
16302 +
16303 + http_request_pool_responsehandler(pool);
16304 + }
16305 +}
16306 +/* }}} */
16307 +
16308 +/* {{{ static void http_request_pool_event_callback(int, short, void *) */
16309 +static void http_request_pool_event_callback(int socket, short action, void *event_data)
16310 +{
16311 + http_request_pool_event *ev = event_data;
16312 + http_request_pool *pool = ev->pool;
16313 +
16314 + if (pool->useevents) {
16315 + CURLMcode rc = CURLE_OK;
16316 + TSRMLS_FETCH_FROM_CTX(ev->pool->tsrm_ls);
16317 +
16318 +#if HTTP_DEBUG_REQPOOLS
16319 + {
16320 + static const char event_strings[][20] = {"NONE","TIMEOUT","READ","TIMEOUT|READ","WRITE","TIMEOUT|WRITE","READ|WRITE","TIMEOUT|READ|WRITE","SIGNAL"};
16321 + fprintf(stderr, "Event on socket %d (%s) event %p of pool %p\n", socket, event_strings[action], ev, pool);
16322 + }
16323 +#endif
16324 +
16325 + /* don't use 'ev' below this loop as it might 've been freed in the socket callback */
16326 + do {
16327 +#ifdef HAVE_CURL_MULTI_SOCKET_ACTION
16328 + switch (action & (EV_READ|EV_WRITE)) {
16329 + case EV_READ:
16330 + rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN, &pool->unfinished);
16331 + break;
16332 + case EV_WRITE:
16333 + rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_OUT, &pool->unfinished);
16334 + break;
16335 + case EV_READ|EV_WRITE:
16336 + rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN|CURL_CSELECT_OUT, &pool->unfinished);
16337 + break;
16338 + default:
16339 + http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown event %d", (int) action);
16340 + return;
16341 + }
16342 +#else
16343 + rc = curl_multi_socket(pool->ch, socket, &pool->unfinished);
16344 +#endif
16345 + } while (CURLM_CALL_MULTI_PERFORM == rc);
16346 +
16347 + switch (rc) {
16348 + case CURLM_BAD_SOCKET:
16349 +#if 0
16350 + fprintf(stderr, "!!! Bad socket: %d (%d)\n", socket, (int) action);
16351 +#endif
16352 + case CURLM_OK:
16353 + break;
16354 + default:
16355 + http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc));
16356 + break;
16357 + }
16358 +
16359 + http_request_pool_responsehandler(pool);
16360 +
16361 + /* remove timeout if there are no transfers left */
16362 + if (!pool->unfinished && event_initialized(pool->timeout) && event_pending(pool->timeout, EV_TIMEOUT, NULL)) {
16363 + event_del(pool->timeout);
16364 +#if HTTP_DEBUG_REQPOOLS
16365 + fprintf(stderr, "Removed timeout of pool %p\n", pool);
16366 +#endif
16367 + }
16368 + }
16369 +}
16370 +/* }}} */
16371 +
16372 +/* {{{ static int http_request_pool_socket_callback(CURL *, curl_socket_t, int, void *, void *) */
16373 +static int http_request_pool_socket_callback(CURL *easy, curl_socket_t sock, int action, void *socket_data, void *assign_data)
16374 +{
16375 + http_request_pool *pool = socket_data;
16376 +
16377 + if (pool->useevents) {
16378 + int events = EV_PERSIST;
16379 + http_request_pool_event *ev = assign_data;
16380 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16381 +
16382 + if (!ev) {
16383 + ev = ecalloc(1, sizeof(http_request_pool_event));
16384 + ev->pool = pool;
16385 + curl_multi_assign(pool->ch, sock, ev);
16386 + event_base_set(HTTP_G->request.pool.event.base, &ev->evnt);
16387 + } else {
16388 + event_del(&ev->evnt);
16389 + }
16390 +
16391 +#if HTTP_DEBUG_REQPOOLS
16392 + {
16393 + static const char action_strings[][8] = {"NONE", "IN", "OUT", "INOUT", "REMOVE"};
16394 + http_request *r;
16395 + curl_easy_getinfo(easy, CURLINFO_PRIVATE, &r);
16396 + fprintf(stderr, "Callback on socket %2d (%8s) event %p of pool %p (%d)\n", (int) sock, action_strings[action], ev, pool, pool->unfinished);
16397 + }
16398 +#endif
16399 +
16400 + switch (action) {
16401 + case CURL_POLL_IN:
16402 + events |= EV_READ;
16403 + break;
16404 + case CURL_POLL_OUT:
16405 + events |= EV_WRITE;
16406 + break;
16407 + case CURL_POLL_INOUT:
16408 + events |= EV_READ|EV_WRITE;
16409 + break;
16410 +
16411 + case CURL_POLL_REMOVE:
16412 + efree(ev);
16413 + case CURL_POLL_NONE:
16414 + return 0;
16415 +
16416 + default:
16417 + http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown socket action %d", action);
16418 + return -1;
16419 + }
16420 +
16421 + event_set(&ev->evnt, sock, events, http_request_pool_event_callback, ev);
16422 + event_add(&ev->evnt, NULL);
16423 + }
16424 +
16425 + return 0;
16426 +}
16427 +/* }}} */
16428 +
16429 +/* {{{ static void http_request_pool_timer_callback(CURLM *, long, void*) */
16430 +static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data)
16431 +{
16432 + http_request_pool *pool = timer_data;
16433 +
16434 + if (pool->useevents) {
16435 + TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls);
16436 + struct timeval timeout;
16437 +
16438 + if (!event_initialized(pool->timeout)) {
16439 + event_set(pool->timeout, -1, 0, http_request_pool_timeout_callback, pool);
16440 + event_base_set(HTTP_G->request.pool.event.base, pool->timeout);
16441 + } else if (event_pending(pool->timeout, EV_TIMEOUT, NULL)) {
16442 + event_del(pool->timeout);
16443 + }
16444 +
16445 + if (timeout_ms > 0) {
16446 + timeout.tv_sec = timeout_ms / 1000;
16447 + timeout.tv_usec = (timeout_ms % 1000) * 1000;
16448 + } else {
16449 + http_request_pool_timeout(pool, &timeout);
16450 + }
16451 +
16452 + event_add(pool->timeout, &timeout);
16453 +
16454 +#if HTTP_DEBUG_REQPOOLS
16455 + fprintf(stderr, "Updating timeout %lu (%lu, %lu) of pool %p\n", (ulong) timeout_ms, (ulong) timeout.tv_sec, (ulong) timeout.tv_usec, pool);
16456 +#endif
16457 + }
16458 +}
16459 +/* }}} */
16460 +#endif /* HTTP_HAVE_EVENT */
16461 +
16462 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
16463 +
16464 +
16465 +/*
16466 + * Local variables:
16467 + * tab-width: 4
16468 + * c-basic-offset: 4
16469 + * End:
16470 + * vim600: noet sw=4 ts=4 fdm=marker
16471 + * vim<600: noet sw=4 ts=4
16472 + */
16473 +
16474 --- /dev/null
16475 +++ b/ext/http/http_requestdatashare_object.c
16476 @@ -0,0 +1,332 @@
16477 +/*
16478 + +--------------------------------------------------------------------+
16479 + | PECL :: http |
16480 + +--------------------------------------------------------------------+
16481 + | Redistribution and use in source and binary forms, with or without |
16482 + | modification, are permitted provided that the conditions mentioned |
16483 + | in the accompanying LICENSE file are met. |
16484 + +--------------------------------------------------------------------+
16485 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
16486 + +--------------------------------------------------------------------+
16487 +*/
16488 +
16489 +/* $Id: http_requestdatashare_object.c 323304 2012-02-17 21:13:24Z mike $ */
16490 +
16491 +#define HTTP_WANT_CURL
16492 +#include "php_http.h"
16493 +
16494 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
16495 +
16496 +#include "zend_interfaces.h"
16497 +
16498 +#include "php_http_api.h"
16499 +#include "php_http_exception_object.h"
16500 +#include "php_http_request_api.h"
16501 +#include "php_http_request_object.h"
16502 +#include "php_http_request_datashare_api.h"
16503 +#include "php_http_requestdatashare_object.h"
16504 +
16505 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestDataShare, method, 0, req_args)
16506 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestDataShare, method, 0)
16507 +#define HTTP_RSHARE_ME(method, visibility) PHP_ME(HttpRequestDataShare, method, HTTP_ARGS(HttpRequestDataShare, method), visibility)
16508 +
16509 +#if defined(HAVE_SPL) && !defined(WONKY)
16510 +/* SPL doesn't install its headers */
16511 +extern PHPAPI zend_class_entry *spl_ce_Countable;
16512 +#endif
16513 +
16514 +HTTP_EMPTY_ARGS(__destruct);
16515 +HTTP_EMPTY_ARGS(count);
16516 +
16517 +HTTP_BEGIN_ARGS(attach, 1)
16518 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16519 +HTTP_END_ARGS;
16520 +HTTP_BEGIN_ARGS(detach, 1)
16521 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16522 +HTTP_END_ARGS;
16523 +
16524 +HTTP_EMPTY_ARGS(reset);
16525 +
16526 +HTTP_BEGIN_ARGS(factory, 0)
16527 + HTTP_ARG_VAL(global, 0)
16528 + HTTP_ARG_VAL(class_name, 0)
16529 +HTTP_END_ARGS;
16530 +
16531 +#ifndef WONKY
16532 +HTTP_BEGIN_ARGS(singleton, 0)
16533 + HTTP_ARG_VAL(global, 0)
16534 +HTTP_END_ARGS;
16535 +#endif
16536 +
16537 +
16538 +#define http_requestdatashare_object_read_prop _http_requestdatashare_object_read_prop
16539 +static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC);
16540 +#define http_requestdatashare_object_write_prop _http_requestdatashare_object_write_prop
16541 +static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC);
16542 +#define http_requestdatashare_instantiate(t, g) _http_requestdatashare_instantiate((t), (g) TSRMLS_CC)
16543 +static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC);
16544 +
16545 +#define THIS_CE http_requestdatashare_object_ce
16546 +zend_class_entry *http_requestdatashare_object_ce;
16547 +zend_function_entry http_requestdatashare_object_fe[] = {
16548 + HTTP_RSHARE_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
16549 + HTTP_RSHARE_ME(count, ZEND_ACC_PUBLIC)
16550 + HTTP_RSHARE_ME(attach, ZEND_ACC_PUBLIC)
16551 + HTTP_RSHARE_ME(detach, ZEND_ACC_PUBLIC)
16552 + HTTP_RSHARE_ME(reset, ZEND_ACC_PUBLIC)
16553 + HTTP_RSHARE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
16554 +#ifndef WONKY
16555 + HTTP_RSHARE_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
16556 +#endif
16557 + EMPTY_FUNCTION_ENTRY
16558 +};
16559 +static zend_object_handlers http_requestdatashare_object_handlers;
16560 +
16561 +PHP_MINIT_FUNCTION(http_requestdatashare_object)
16562 +{
16563 + HTTP_REGISTER_CLASS_EX(HttpRequestDataShare, http_requestdatashare_object, NULL, 0);
16564 + http_requestdatashare_object_handlers.clone_obj = NULL;
16565 + http_requestdatashare_object_handlers.read_property = http_requestdatashare_object_read_prop;
16566 + http_requestdatashare_object_handlers.write_property = http_requestdatashare_object_write_prop;
16567 +
16568 +#if defined(HAVE_SPL) && !defined(WONKY)
16569 + zend_class_implements(http_requestdatashare_object_ce TSRMLS_CC, 1, spl_ce_Countable);
16570 +#endif
16571 +
16572 + zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
16573 + zend_declare_property_bool(THIS_CE, ZEND_STRS("cookie")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16574 + zend_declare_property_bool(THIS_CE, ZEND_STRS("dns")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16575 + zend_declare_property_bool(THIS_CE, ZEND_STRS("ssl")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16576 + zend_declare_property_bool(THIS_CE, ZEND_STRS("connect")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
16577 +
16578 + return SUCCESS;
16579 +}
16580 +
16581 +zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC)
16582 +{
16583 + return http_requestdatashare_object_new_ex(ce, NULL, NULL);
16584 +}
16585 +
16586 +zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC)
16587 +{
16588 + zend_object_value ov;
16589 + http_requestdatashare_object *o;
16590 +
16591 + o = ecalloc(1, sizeof(http_requestdatashare_object));
16592 + o->zo.ce = ce;
16593 +
16594 + if (share) {
16595 + o->share = share;
16596 + } else {
16597 + o->share = http_request_datashare_new();
16598 + }
16599 +
16600 + if (ptr) {
16601 + *ptr = o;
16602 + }
16603 +
16604 +#ifdef ZEND_ENGINE_2_4
16605 + zend_object_std_init(o, ce TSRMLS_CC);
16606 + object_properties_init(o, ce);
16607 +#else
16608 + ALLOC_HASHTABLE(OBJ_PROP(o));
16609 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
16610 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
16611 +#endif
16612 +
16613 + ov.handle = putObject(http_requestdatashare_object, o);
16614 + ov.handlers = &http_requestdatashare_object_handlers;
16615 +
16616 + return ov;
16617 +}
16618 +
16619 +void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC)
16620 +{
16621 + http_requestdatashare_object *o = (http_requestdatashare_object *) object;
16622 +
16623 + if (!o->share->persistent) {
16624 + http_request_datashare_free(&o->share);
16625 + }
16626 + freeObject(o);
16627 +}
16628 +
16629 +static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC)
16630 +{
16631 + if (type == BP_VAR_W &&
16632 +#ifdef ZEND_ENGINE_2_4
16633 + zend_hash_exists(&THIS_CE->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
16634 +#else
16635 + zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
16636 +#endif
16637 + ) {
16638 + zend_error(E_ERROR, "Cannot access HttpRequestDataShare default properties by reference or array key/index");
16639 + return NULL;
16640 + }
16641 +
16642 + return zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC);
16643 +}
16644 +
16645 +static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC)
16646 +{
16647 + if (
16648 +#ifdef ZEND_ENGINE_2_4
16649 + zend_hash_exists(&THIS_CE->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
16650 +#else
16651 + zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
16652 +#endif
16653 + ) {
16654 + int status;
16655 + getObjectEx(http_requestdatashare_object, obj, object);
16656 +
16657 + status = http_request_datashare_set(obj->share, Z_STRVAL_P(member), Z_STRLEN_P(member), (zend_bool) i_zend_is_true(value));
16658 + if (SUCCESS != status) {
16659 + return;
16660 + }
16661 + }
16662 +
16663 + zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC);
16664 +}
16665 +
16666 +/* {{{ proto void HttpRequestDataShare::__destruct()
16667 + Clean up HttpRequestDataShare object. */
16668 +PHP_METHOD(HttpRequestDataShare, __destruct)
16669 +{
16670 + NO_ARGS {
16671 + getObject(http_requestdatashare_object, obj);
16672 + http_request_datashare_detach_all(obj->share);
16673 + }
16674 +}
16675 +/* }}} */
16676 +
16677 +/* {{{ proto int HttpRequestDataShare::count()
16678 + Implements Countable::count(). */
16679 +PHP_METHOD(HttpRequestDataShare, count)
16680 +{
16681 + getObject(http_requestdatashare_object, obj);
16682 +
16683 + NO_ARGS;
16684 +
16685 + RETURN_LONG(zend_llist_count(HTTP_RSHARE_HANDLES(obj->share)));
16686 +}
16687 +/* }}} */
16688 +
16689 +PHP_METHOD(HttpRequestDataShare, attach)
16690 +{
16691 + zval *request;
16692 + getObject(http_requestdatashare_object, obj);
16693 +
16694 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
16695 + RETURN_FALSE;
16696 + }
16697 +
16698 + RETURN_SUCCESS(http_request_datashare_attach(obj->share, request));
16699 +}
16700 +
16701 +PHP_METHOD(HttpRequestDataShare, detach)
16702 +{
16703 + zval *request;
16704 + getObject(http_requestdatashare_object, obj);
16705 +
16706 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
16707 + RETURN_FALSE;
16708 + }
16709 +
16710 + RETURN_SUCCESS(http_request_datashare_detach(obj->share, request));
16711 +}
16712 +
16713 +PHP_METHOD(HttpRequestDataShare, reset)
16714 +{
16715 + NO_ARGS {
16716 + getObject(http_requestdatashare_object, obj);
16717 + http_request_datashare_detach_all(obj->share);
16718 + }
16719 +}
16720 +
16721 +PHP_METHOD(HttpRequestDataShare, factory)
16722 +{
16723 + zend_bool global = 0;
16724 + char *cn = NULL;
16725 + int cl = 0;
16726 + zend_object_value ov;
16727 +
16728 + SET_EH_THROW_HTTP();
16729 + if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs", &global, &cn, &cl) &&
16730 + SUCCESS == http_object_new(&ov, cn, cl, _http_requestdatashare_object_new_ex, http_requestdatashare_object_ce, NULL, NULL)) {
16731 + RETVAL_OBJVAL(ov, 0);
16732 + http_requestdatashare_instantiate(return_value, global);
16733 + }
16734 + SET_EH_NORMAL();
16735 +}
16736 +
16737 +#ifndef WONKY
16738 +/* {{{ proto static HttpRequestDataShare HttpRequestDataShare::singleton([bool global = false])
16739 + Get a single instance (differentiates between the global setting). */
16740 +PHP_METHOD(HttpRequestDataShare, singleton)
16741 +{
16742 + zend_bool global = 0;
16743 + zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
16744 +
16745 + SET_EH_THROW_HTTP();
16746 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) {
16747 + zval **zobj_ptr = NULL, *zobj = NULL;
16748 +
16749 + if (Z_TYPE_P(instance) == IS_ARRAY) {
16750 + if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) {
16751 + RETVAL_ZVAL(*zobj_ptr, 1, 0);
16752 + } else {
16753 + zobj = http_requestdatashare_instantiate(NULL, global);
16754 + add_index_zval(instance, global, zobj);
16755 + RETVAL_OBJECT(zobj, 1);
16756 + }
16757 + } else {
16758 + MAKE_STD_ZVAL(instance);
16759 + array_init(instance);
16760 +
16761 + zobj = http_requestdatashare_instantiate(NULL, global);
16762 + add_index_zval(instance, global, zobj);
16763 + RETVAL_OBJECT(zobj, 1);
16764 +
16765 + zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC);
16766 + zval_ptr_dtor(&instance);
16767 + }
16768 + }
16769 + SET_EH_NORMAL();
16770 +}
16771 +/* }}} */
16772 +#endif /* !WONKY */
16773 +
16774 +static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC)
16775 +{
16776 + if (!this_ptr) {
16777 + MAKE_STD_ZVAL(this_ptr);
16778 + Z_TYPE_P(this_ptr) = IS_OBJECT;
16779 + this_ptr->value.obj = http_requestdatashare_object_new_ex(http_requestdatashare_object_ce, global ? http_request_datashare_global_get() : NULL, NULL);
16780 + }
16781 + if (global) {
16782 + if (HTTP_G->request.datashare.cookie) {
16783 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("cookie")-1, HTTP_G->request.datashare.cookie TSRMLS_CC);
16784 + }
16785 + if (HTTP_G->request.datashare.dns) {
16786 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("dns")-1, HTTP_G->request.datashare.dns TSRMLS_CC);
16787 + }
16788 + if (HTTP_G->request.datashare.ssl) {
16789 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("ssl")-1, HTTP_G->request.datashare.ssl TSRMLS_CC);
16790 + }
16791 + if (HTTP_G->request.datashare.connect) {
16792 + zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("connect")-1, HTTP_G->request.datashare.connect TSRMLS_CC);
16793 + }
16794 + }
16795 + return this_ptr;
16796 +}
16797 +
16798 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
16799 +
16800 +/*
16801 + * Local variables:
16802 + * tab-width: 4
16803 + * c-basic-offset: 4
16804 + * End:
16805 + * vim600: noet sw=4 ts=4 fdm=marker
16806 + * vim<600: noet sw=4 ts=4
16807 + */
16808 +
16809 --- /dev/null
16810 +++ b/ext/http/http_requestpool_object.c
16811 @@ -0,0 +1,471 @@
16812 +/*
16813 + +--------------------------------------------------------------------+
16814 + | PECL :: http |
16815 + +--------------------------------------------------------------------+
16816 + | Redistribution and use in source and binary forms, with or without |
16817 + | modification, are permitted provided that the conditions mentioned |
16818 + | in the accompanying LICENSE file are met. |
16819 + +--------------------------------------------------------------------+
16820 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
16821 + +--------------------------------------------------------------------+
16822 +*/
16823 +
16824 +/* $Id: http_requestpool_object.c 323304 2012-02-17 21:13:24Z mike $ */
16825 +
16826 +#define HTTP_WANT_CURL
16827 +#include "php_http.h"
16828 +
16829 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
16830 +
16831 +#include "zend_interfaces.h"
16832 +
16833 +#include "php_http_api.h"
16834 +#include "php_http_exception_object.h"
16835 +#include "php_http_request_api.h"
16836 +#include "php_http_request_object.h"
16837 +#include "php_http_request_pool_api.h"
16838 +#include "php_http_requestpool_object.h"
16839 +
16840 +#if defined(HAVE_SPL) && !defined(WONKY)
16841 +/* SPL doesn't install its headers */
16842 +extern PHPAPI zend_class_entry *spl_ce_Countable;
16843 +#endif
16844 +
16845 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestPool, method, 0, req_args)
16846 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestPool, method, 0)
16847 +#define HTTP_REQPOOL_ME(method, visibility) PHP_ME(HttpRequestPool, method, HTTP_ARGS(HttpRequestPool, method), visibility)
16848 +
16849 +HTTP_EMPTY_ARGS(__construct);
16850 +
16851 +HTTP_EMPTY_ARGS(__destruct);
16852 +HTTP_EMPTY_ARGS(reset);
16853 +
16854 +HTTP_BEGIN_ARGS(attach, 1)
16855 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16856 +HTTP_END_ARGS;
16857 +
16858 +HTTP_BEGIN_ARGS(detach, 1)
16859 + HTTP_ARG_OBJ(HttpRequest, request, 0)
16860 +HTTP_END_ARGS;
16861 +
16862 +HTTP_EMPTY_ARGS(send);
16863 +HTTP_EMPTY_ARGS(socketPerform);
16864 +HTTP_BEGIN_ARGS(socketSelect, 0)
16865 + HTTP_ARG_VAL(timeout, 0)
16866 +HTTP_END_ARGS;
16867 +
16868 +HTTP_EMPTY_ARGS(valid);
16869 +HTTP_EMPTY_ARGS(current);
16870 +HTTP_EMPTY_ARGS(key);
16871 +HTTP_EMPTY_ARGS(next);
16872 +HTTP_EMPTY_ARGS(rewind);
16873 +
16874 +HTTP_EMPTY_ARGS(count);
16875 +
16876 +HTTP_EMPTY_ARGS(getAttachedRequests);
16877 +HTTP_EMPTY_ARGS(getFinishedRequests);
16878 +
16879 +HTTP_BEGIN_ARGS(enablePipelining, 0)
16880 + HTTP_ARG_VAL(enable, 0)
16881 +HTTP_END_ARGS;
16882 +
16883 +HTTP_BEGIN_ARGS(enableEvents, 0)
16884 + HTTP_ARG_VAL(enable, 0)
16885 +HTTP_END_ARGS;
16886 +
16887 +zend_class_entry *http_requestpool_object_ce;
16888 +zend_function_entry http_requestpool_object_fe[] = {
16889 + HTTP_REQPOOL_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
16890 + HTTP_REQPOOL_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
16891 + HTTP_REQPOOL_ME(attach, ZEND_ACC_PUBLIC)
16892 + HTTP_REQPOOL_ME(detach, ZEND_ACC_PUBLIC)
16893 + HTTP_REQPOOL_ME(send, ZEND_ACC_PUBLIC)
16894 + HTTP_REQPOOL_ME(reset, ZEND_ACC_PUBLIC)
16895 +
16896 + HTTP_REQPOOL_ME(socketPerform, ZEND_ACC_PROTECTED)
16897 + HTTP_REQPOOL_ME(socketSelect, ZEND_ACC_PROTECTED)
16898 +
16899 + /* implements Iterator */
16900 + HTTP_REQPOOL_ME(valid, ZEND_ACC_PUBLIC)
16901 + HTTP_REQPOOL_ME(current, ZEND_ACC_PUBLIC)
16902 + HTTP_REQPOOL_ME(key, ZEND_ACC_PUBLIC)
16903 + HTTP_REQPOOL_ME(next, ZEND_ACC_PUBLIC)
16904 + HTTP_REQPOOL_ME(rewind, ZEND_ACC_PUBLIC)
16905 +
16906 + /* implmenents Countable */
16907 + HTTP_REQPOOL_ME(count, ZEND_ACC_PUBLIC)
16908 +
16909 + HTTP_REQPOOL_ME(getAttachedRequests, ZEND_ACC_PUBLIC)
16910 + HTTP_REQPOOL_ME(getFinishedRequests, ZEND_ACC_PUBLIC)
16911 +
16912 + HTTP_REQPOOL_ME(enablePipelining, ZEND_ACC_PUBLIC)
16913 + HTTP_REQPOOL_ME(enableEvents, ZEND_ACC_PUBLIC)
16914 +
16915 + EMPTY_FUNCTION_ENTRY
16916 +};
16917 +static zend_object_handlers http_requestpool_object_handlers;
16918 +
16919 +PHP_MINIT_FUNCTION(http_requestpool_object)
16920 +{
16921 + HTTP_REGISTER_CLASS_EX(HttpRequestPool, http_requestpool_object, NULL, 0);
16922 + http_requestpool_object_handlers.clone_obj = NULL;
16923 +
16924 +#if defined(HAVE_SPL) && !defined(WONKY)
16925 + zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 2, spl_ce_Countable, zend_ce_iterator);
16926 +#else
16927 + zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 1, zend_ce_iterator);
16928 +#endif
16929 +
16930 + return SUCCESS;
16931 +}
16932 +
16933 +zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC)
16934 +{
16935 + zend_object_value ov;
16936 + http_requestpool_object *o;
16937 +
16938 + o = ecalloc(1, sizeof(http_requestpool_object));
16939 + o->zo.ce = ce;
16940 +
16941 + http_request_pool_init(&o->pool);
16942 +
16943 +#ifdef ZEND_ENGINE_2_4
16944 + zend_object_std_init(o, ce TSRMLS_CC);
16945 + object_properties_init(o, ce);
16946 +#else
16947 + ALLOC_HASHTABLE(OBJ_PROP(o));
16948 + zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
16949 + zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
16950 +#endif
16951 +
16952 + ov.handle = putObject(http_requestpool_object, o);
16953 + ov.handlers = &http_requestpool_object_handlers;
16954 +
16955 + return ov;
16956 +}
16957 +
16958 +void _http_requestpool_object_free(zend_object *object TSRMLS_DC)
16959 +{
16960 + http_requestpool_object *o = (http_requestpool_object *) object;
16961 +
16962 + http_request_pool_dtor(&o->pool);
16963 + freeObject(o);
16964 +}
16965 +
16966 +#define http_requestpool_object_llist2array _http_requestpool_object_llist2array
16967 +static void _http_requestpool_object_llist2array(zval **req, zval *array TSRMLS_DC)
16968 +{
16969 + ZVAL_ADDREF(*req);
16970 + add_next_index_zval(array, *req);
16971 +}
16972 +
16973 +/* ### USERLAND ### */
16974 +
16975 +/* {{{ proto void HttpRequestPool::__construct([HttpRequest request[, ...]])
16976 + Creates a new HttpRequestPool object instance. */
16977 +PHP_METHOD(HttpRequestPool, __construct)
16978 +{
16979 + int argc = ZEND_NUM_ARGS();
16980 + zval ***argv = safe_emalloc(argc, sizeof(zval *), 0);
16981 + getObject(http_requestpool_object, obj);
16982 +
16983 + SET_EH_THROW_HTTP();
16984 + if (SUCCESS == zend_get_parameters_array_ex(argc, argv)) {
16985 + int i;
16986 +
16987 + for (i = 0; i < argc; ++i) {
16988 + if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), http_request_object_ce TSRMLS_CC)) {
16989 + http_request_pool_attach(&obj->pool, *(argv[i]));
16990 + }
16991 + }
16992 + }
16993 + efree(argv);
16994 + http_final(HTTP_EX_CE(request_pool));
16995 + SET_EH_NORMAL();
16996 +}
16997 +/* }}} */
16998 +
16999 +/* {{{ proto void HttpRequestPool::__destruct()
17000 + Clean up HttpRequestPool object. */
17001 +PHP_METHOD(HttpRequestPool, __destruct)
17002 +{
17003 + getObject(http_requestpool_object, obj);
17004 +
17005 + NO_ARGS;
17006 +
17007 + http_request_pool_detach_all(&obj->pool);
17008 +}
17009 +/* }}} */
17010 +
17011 +/* {{{ proto void HttpRequestPool::reset()
17012 + Detach all attached HttpRequest objects. */
17013 +PHP_METHOD(HttpRequestPool, reset)
17014 +{
17015 + getObject(http_requestpool_object, obj);
17016 +
17017 + NO_ARGS;
17018 +
17019 + obj->iterator.pos = 0;
17020 + http_request_pool_detach_all(&obj->pool);
17021 +}
17022 +
17023 +/* {{{ proto bool HttpRequestPool::attach(HttpRequest request)
17024 + Attach an HttpRequest object to this HttpRequestPool. WARNING: set all options prior attaching! */
17025 +PHP_METHOD(HttpRequestPool, attach)
17026 +{
17027 + zval *request;
17028 + STATUS status = FAILURE;
17029 + getObject(http_requestpool_object, obj);
17030 +
17031 + SET_EH_THROW_HTTP();
17032 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
17033 + if (obj->iterator.pos > 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles)) {
17034 + http_error(HE_THROW, HTTP_E_REQUEST_POOL, "Cannot attach to the HttpRequestPool while the iterator is active");
17035 + } else {
17036 + status = http_request_pool_attach(&obj->pool, request);
17037 + }
17038 + }
17039 + SET_EH_NORMAL();
17040 + RETURN_SUCCESS(status);
17041 +}
17042 +/* }}} */
17043 +
17044 +/* {{{ proto bool HttpRequestPool::detach(HttpRequest request)
17045 + Detach an HttpRequest object from this HttpRequestPool. */
17046 +PHP_METHOD(HttpRequestPool, detach)
17047 +{
17048 + zval *request;
17049 + STATUS status = FAILURE;
17050 + getObject(http_requestpool_object, obj);
17051 +
17052 + SET_EH_THROW_HTTP();
17053 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) {
17054 + obj->iterator.pos = -1;
17055 + status = http_request_pool_detach(&obj->pool, request);
17056 + }
17057 + SET_EH_NORMAL();
17058 + RETURN_SUCCESS(status);
17059 +}
17060 +/* }}} */
17061 +
17062 +/* {{{ proto bool HttpRequestPool::send()
17063 + Send all attached HttpRequest objects in parallel. */
17064 +PHP_METHOD(HttpRequestPool, send)
17065 +{
17066 + STATUS status;
17067 + getObject(http_requestpool_object, obj);
17068 +
17069 + NO_ARGS;
17070 +
17071 + SET_EH_THROW_HTTP();
17072 + status = http_request_pool_send(&obj->pool);
17073 + SET_EH_NORMAL();
17074 +
17075 + /* rethrow as HttpRequestPoolException */
17076 + http_final(HTTP_EX_CE(request_pool));
17077 +
17078 + RETURN_SUCCESS(status);
17079 +}
17080 +/* }}} */
17081 +
17082 +/* {{{ proto protected bool HttpRequestPool::socketPerform()
17083 + Returns TRUE until each request has finished its transaction. */
17084 +PHP_METHOD(HttpRequestPool, socketPerform)
17085 +{
17086 + getObject(http_requestpool_object, obj);
17087 +
17088 + NO_ARGS;
17089 +
17090 + if (0 < http_request_pool_perform(&obj->pool)) {
17091 + RETURN_TRUE;
17092 + } else {
17093 + RETURN_FALSE;
17094 + }
17095 +}
17096 +/* }}} */
17097 +
17098 +/* {{{ proto protected bool HttpRequestPool::socketSelect([double timeout]) */
17099 +PHP_METHOD(HttpRequestPool, socketSelect)
17100 +{
17101 + double timeout = 0;
17102 + struct timeval custom_timeout, *custom_timeout_ptr = NULL;
17103 + getObject(http_requestpool_object, obj);
17104 +
17105 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|d", &timeout)) {
17106 + RETURN_FALSE;
17107 + }
17108 + if (ZEND_NUM_ARGS() && timeout > 0) {
17109 + custom_timeout.tv_sec = (time_t) timeout;
17110 + custom_timeout.tv_usec = HTTP_USEC(timeout) % HTTP_MCROSEC;
17111 + custom_timeout_ptr = &custom_timeout;
17112 + }
17113 +
17114 + RETURN_SUCCESS(http_request_pool_select_ex(&obj->pool, custom_timeout_ptr));
17115 +}
17116 +/* }}} */
17117 +
17118 +/* {{{ proto bool HttpRequestPool::valid()
17119 + Implements Iterator::valid(). */
17120 +PHP_METHOD(HttpRequestPool, valid)
17121 +{
17122 + NO_ARGS;
17123 +
17124 + if (return_value_used) {
17125 + getObject(http_requestpool_object, obj);
17126 + RETURN_BOOL(obj->iterator.pos >= 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles));
17127 + }
17128 +}
17129 +/* }}} */
17130 +
17131 +/* {{{ proto HttpRequest HttpRequestPool::current()
17132 + Implements Iterator::current(). */
17133 +PHP_METHOD(HttpRequestPool, current)
17134 +{
17135 + NO_ARGS;
17136 +
17137 + if (return_value_used) {
17138 + long pos = 0;
17139 + zval **current = NULL;
17140 + zend_llist_position lpos;
17141 + getObject(http_requestpool_object, obj);
17142 +
17143 + if (obj->iterator.pos < zend_llist_count(&obj->pool.handles)) {
17144 + for ( current = zend_llist_get_first_ex(&obj->pool.handles, &lpos);
17145 + current && obj->iterator.pos != pos++;
17146 + current = zend_llist_get_next_ex(&obj->pool.handles, &lpos));
17147 + if (current) {
17148 + RETURN_OBJECT(*current, 1);
17149 + }
17150 + }
17151 + RETURN_NULL();
17152 + }
17153 +}
17154 +/* }}} */
17155 +
17156 +/* {{{ proto int HttpRequestPool::key()
17157 + Implements Iterator::key(). */
17158 +PHP_METHOD(HttpRequestPool, key)
17159 +{
17160 + NO_ARGS;
17161 +
17162 + if (return_value_used) {
17163 + getObject(http_requestpool_object, obj);
17164 + RETURN_LONG(obj->iterator.pos);
17165 + }
17166 +}
17167 +/* }}} */
17168 +
17169 +/* {{{ proto void HttpRequestPool::next()
17170 + Implements Iterator::next(). */
17171 +PHP_METHOD(HttpRequestPool, next)
17172 +{
17173 + NO_ARGS {
17174 + getObject(http_requestpool_object, obj);
17175 + ++(obj->iterator.pos);
17176 + }
17177 +}
17178 +/* }}} */
17179 +
17180 +/* {{{ proto void HttpRequestPool::rewind()
17181 + Implements Iterator::rewind(). */
17182 +PHP_METHOD(HttpRequestPool, rewind)
17183 +{
17184 + NO_ARGS {
17185 + getObject(http_requestpool_object, obj);
17186 + obj->iterator.pos = 0;
17187 + }
17188 +}
17189 +/* }}} */
17190 +
17191 +/* {{{ proto int HttpRequestPool::count()
17192 + Implements Countable::count(). */
17193 +PHP_METHOD(HttpRequestPool, count)
17194 +{
17195 + NO_ARGS {
17196 + getObject(http_requestpool_object, obj);
17197 + RETURN_LONG((long) zend_llist_count(&obj->pool.handles));
17198 + }
17199 +}
17200 +/* }}} */
17201 +
17202 +/* {{{ proto array HttpRequestPool::getAttachedRequests()
17203 + Get attached HttpRequest objects. */
17204 +PHP_METHOD(HttpRequestPool, getAttachedRequests)
17205 +{
17206 + getObject(http_requestpool_object, obj);
17207 +
17208 + NO_ARGS;
17209 +
17210 + array_init(return_value);
17211 + zend_llist_apply_with_argument(&obj->pool.handles,
17212 + (llist_apply_with_arg_func_t) http_requestpool_object_llist2array,
17213 + return_value TSRMLS_CC);
17214 +}
17215 +/* }}} */
17216 +
17217 +/* {{{ proto array HttpRequestPool::getFinishedRequests()
17218 + Get attached HttpRequest objects that already have finished their work. */
17219 +PHP_METHOD(HttpRequestPool, getFinishedRequests)
17220 +{
17221 + getObject(http_requestpool_object, obj);
17222 +
17223 + NO_ARGS;
17224 +
17225 + array_init(return_value);
17226 + zend_llist_apply_with_argument(&obj->pool.finished,
17227 + (llist_apply_with_arg_func_t) http_requestpool_object_llist2array,
17228 + return_value TSRMLS_CC);
17229 +}
17230 +/* }}} */
17231 +
17232 +/* {{{ proto bool HttpRequestPool::enablePipelining([bool enable = true])
17233 + Enables pipelining support for all attached requests if support in libcurl is given. */
17234 +PHP_METHOD(HttpRequestPool, enablePipelining)
17235 +{
17236 + zend_bool enable = 1;
17237 +#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0)
17238 + getObject(http_requestpool_object, obj);
17239 +#endif
17240 +
17241 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) {
17242 + RETURN_FALSE;
17243 + }
17244 +#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0)
17245 + if (CURLM_OK == curl_multi_setopt(obj->pool.ch, CURLMOPT_PIPELINING, (long) enable)) {
17246 + RETURN_TRUE;
17247 + }
17248 +#endif
17249 + RETURN_FALSE;
17250 +}
17251 +/* }}} */
17252 +
17253 +/* {{{ proto bool HttpRequestPool::enableEvents([bool enable = true])
17254 + Enables event-driven I/O if support in libcurl is given. */
17255 +PHP_METHOD(HttpRequestPool, enableEvents)
17256 +{
17257 + zend_bool enable = 1;
17258 +#if defined(HTTP_HAVE_EVENT)
17259 + getObject(http_requestpool_object, obj);
17260 +#endif
17261 +
17262 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) {
17263 +#if defined(HTTP_HAVE_EVENT)
17264 + obj->pool.useevents = enable;
17265 + RETURN_TRUE;
17266 +#endif
17267 + }
17268 + RETURN_FALSE;
17269 +}
17270 +/* }}} */
17271 +
17272 +#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */
17273 +
17274 +/*
17275 + * Local variables:
17276 + * tab-width: 4
17277 + * c-basic-offset: 4
17278 + * End:
17279 + * vim600: noet sw=4 ts=4 fdm=marker
17280 + * vim<600: noet sw=4 ts=4
17281 + */
17282 +
17283 --- /dev/null
17284 +++ b/ext/http/http_response_object.c
17285 @@ -0,0 +1,927 @@
17286 +/*
17287 + +--------------------------------------------------------------------+
17288 + | PECL :: http |
17289 + +--------------------------------------------------------------------+
17290 + | Redistribution and use in source and binary forms, with or without |
17291 + | modification, are permitted provided that the conditions mentioned |
17292 + | in the accompanying LICENSE file are met. |
17293 + +--------------------------------------------------------------------+
17294 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
17295 + +--------------------------------------------------------------------+
17296 +*/
17297 +
17298 +/* $Id: http_response_object.c 323304 2012-02-17 21:13:24Z mike $ */
17299 +
17300 +#define HTTP_WANT_SAPI
17301 +#define HTTP_WANT_MAGIC
17302 +#include "php_http.h"
17303 +
17304 +/* broken static properties in PHP 5.0 */
17305 +#if defined(ZEND_ENGINE_2) && !defined(WONKY)
17306 +
17307 +#include "php_ini.h"
17308 +
17309 +#include "php_http_api.h"
17310 +#include "php_http_cache_api.h"
17311 +#include "php_http_exception_object.h"
17312 +#include "php_http_headers_api.h"
17313 +#include "php_http_response_object.h"
17314 +#include "php_http_send_api.h"
17315 +
17316 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpResponse, method, 0, req_args)
17317 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpResponse, method, 0)
17318 +#define HTTP_RESPONSE_ME(method, visibility) PHP_ME(HttpResponse, method, HTTP_ARGS(HttpResponse, method), visibility|ZEND_ACC_STATIC)
17319 +#define HTTP_RESPONSE_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpResponse, method))
17320 +
17321 +HTTP_BEGIN_ARGS(setHeader, 1)
17322 + HTTP_ARG_VAL(name, 0)
17323 + HTTP_ARG_VAL(value, 0)
17324 + HTTP_ARG_VAL(replace, 0)
17325 +HTTP_END_ARGS;
17326 +
17327 +HTTP_BEGIN_ARGS(getHeader, 0)
17328 + HTTP_ARG_VAL(name, 0)
17329 +HTTP_END_ARGS;
17330 +
17331 +HTTP_EMPTY_ARGS(getETag);
17332 +HTTP_BEGIN_ARGS(setETag, 1)
17333 + HTTP_ARG_VAL(etag, 0)
17334 +HTTP_END_ARGS;
17335 +
17336 +HTTP_EMPTY_ARGS(getLastModified);
17337 +HTTP_BEGIN_ARGS(setLastModified, 1)
17338 + HTTP_ARG_VAL(timestamp, 0)
17339 +HTTP_END_ARGS;
17340 +
17341 +HTTP_EMPTY_ARGS(getCache);
17342 +HTTP_BEGIN_ARGS(setCache, 1)
17343 + HTTP_ARG_VAL(cache, 0)
17344 +HTTP_END_ARGS;
17345 +
17346 +HTTP_EMPTY_ARGS(getGzip);
17347 +HTTP_BEGIN_ARGS(setGzip, 1)
17348 + HTTP_ARG_VAL(gzip, 0)
17349 +HTTP_END_ARGS;
17350 +
17351 +HTTP_EMPTY_ARGS(getCacheControl);
17352 +HTTP_BEGIN_ARGS(setCacheControl, 1)
17353 + HTTP_ARG_VAL(cache_control, 0)
17354 + HTTP_ARG_VAL(max_age, 0)
17355 + HTTP_ARG_VAL(must_revalidate, 0)
17356 +HTTP_END_ARGS;
17357 +
17358 +HTTP_EMPTY_ARGS(getContentType);
17359 +HTTP_BEGIN_ARGS(setContentType, 1)
17360 + HTTP_ARG_VAL(content_type, 0)
17361 +HTTP_END_ARGS;
17362 +
17363 +HTTP_BEGIN_ARGS(guessContentType, 1)
17364 + HTTP_ARG_VAL(magic_file, 0)
17365 + HTTP_ARG_VAL(magic_mode, 0)
17366 +HTTP_END_ARGS;
17367 +
17368 +HTTP_EMPTY_ARGS(getContentDisposition);
17369 +HTTP_BEGIN_ARGS(setContentDisposition, 1)
17370 + HTTP_ARG_VAL(filename, 0)
17371 + HTTP_ARG_VAL(send_inline, 0)
17372 +HTTP_END_ARGS;
17373 +
17374 +HTTP_EMPTY_ARGS(getThrottleDelay);
17375 +HTTP_BEGIN_ARGS(setThrottleDelay, 1)
17376 + HTTP_ARG_VAL(seconds, 0)
17377 +HTTP_END_ARGS;
17378 +
17379 +HTTP_EMPTY_ARGS(getBufferSize);
17380 +HTTP_BEGIN_ARGS(setBufferSize, 1)
17381 + HTTP_ARG_VAL(bytes, 0)
17382 +HTTP_END_ARGS;
17383 +
17384 +HTTP_EMPTY_ARGS(getData);
17385 +HTTP_BEGIN_ARGS(setData, 1)
17386 + HTTP_ARG_VAL(data, 0)
17387 +HTTP_END_ARGS;
17388 +
17389 +HTTP_EMPTY_ARGS(getStream);
17390 +HTTP_BEGIN_ARGS(setStream, 1)
17391 + HTTP_ARG_VAL(stream, 0)
17392 +HTTP_END_ARGS;
17393 +
17394 +HTTP_EMPTY_ARGS(getFile);
17395 +HTTP_BEGIN_ARGS(setFile, 1)
17396 + HTTP_ARG_VAL(filepath, 0)
17397 +HTTP_END_ARGS;
17398 +
17399 +HTTP_BEGIN_ARGS(send, 0)
17400 + HTTP_ARG_VAL(clean_ob, 0)
17401 +HTTP_END_ARGS;
17402 +
17403 +HTTP_EMPTY_ARGS(capture);
17404 +
17405 +HTTP_BEGIN_ARGS(redirect, 0)
17406 + HTTP_ARG_VAL(url, 0)
17407 + HTTP_ARG_VAL(params, 0)
17408 + HTTP_ARG_VAL(session, 0)
17409 + HTTP_ARG_VAL(permanent, 0)
17410 +HTTP_END_ARGS;
17411 +
17412 +HTTP_BEGIN_ARGS(status, 1)
17413 + HTTP_ARG_VAL(code, 0)
17414 +HTTP_END_ARGS;
17415 +
17416 +HTTP_EMPTY_ARGS(getRequestHeaders);
17417 +HTTP_EMPTY_ARGS(getRequestBody);
17418 +HTTP_EMPTY_ARGS(getRequestBodyStream);
17419 +
17420 +#define THIS_CE http_response_object_ce
17421 +zend_class_entry *http_response_object_ce;
17422 +zend_function_entry http_response_object_fe[] = {
17423 +
17424 + HTTP_RESPONSE_ME(setHeader, ZEND_ACC_PUBLIC)
17425 + HTTP_RESPONSE_ME(getHeader, ZEND_ACC_PUBLIC)
17426 +
17427 + HTTP_RESPONSE_ME(setETag, ZEND_ACC_PUBLIC)
17428 + HTTP_RESPONSE_ME(getETag, ZEND_ACC_PUBLIC)
17429 +
17430 + HTTP_RESPONSE_ME(setLastModified, ZEND_ACC_PUBLIC)
17431 + HTTP_RESPONSE_ME(getLastModified, ZEND_ACC_PUBLIC)
17432 +
17433 + HTTP_RESPONSE_ME(setContentDisposition, ZEND_ACC_PUBLIC)
17434 + HTTP_RESPONSE_ME(getContentDisposition, ZEND_ACC_PUBLIC)
17435 +
17436 + HTTP_RESPONSE_ME(setContentType, ZEND_ACC_PUBLIC)
17437 + HTTP_RESPONSE_ME(getContentType, ZEND_ACC_PUBLIC)
17438 +
17439 + HTTP_RESPONSE_ME(guessContentType, ZEND_ACC_PUBLIC)
17440 +
17441 + HTTP_RESPONSE_ME(setCache, ZEND_ACC_PUBLIC)
17442 + HTTP_RESPONSE_ME(getCache, ZEND_ACC_PUBLIC)
17443 +
17444 + HTTP_RESPONSE_ME(setCacheControl, ZEND_ACC_PUBLIC)
17445 + HTTP_RESPONSE_ME(getCacheControl, ZEND_ACC_PUBLIC)
17446 +
17447 + HTTP_RESPONSE_ME(setGzip, ZEND_ACC_PUBLIC)
17448 + HTTP_RESPONSE_ME(getGzip, ZEND_ACC_PUBLIC)
17449 +
17450 + HTTP_RESPONSE_ME(setThrottleDelay, ZEND_ACC_PUBLIC)
17451 + HTTP_RESPONSE_ME(getThrottleDelay, ZEND_ACC_PUBLIC)
17452 +
17453 + HTTP_RESPONSE_ME(setBufferSize, ZEND_ACC_PUBLIC)
17454 + HTTP_RESPONSE_ME(getBufferSize, ZEND_ACC_PUBLIC)
17455 +
17456 + HTTP_RESPONSE_ME(setData, ZEND_ACC_PUBLIC)
17457 + HTTP_RESPONSE_ME(getData, ZEND_ACC_PUBLIC)
17458 +
17459 + HTTP_RESPONSE_ME(setFile, ZEND_ACC_PUBLIC)
17460 + HTTP_RESPONSE_ME(getFile, ZEND_ACC_PUBLIC)
17461 +
17462 + HTTP_RESPONSE_ME(setStream, ZEND_ACC_PUBLIC)
17463 + HTTP_RESPONSE_ME(getStream, ZEND_ACC_PUBLIC)
17464 +
17465 + HTTP_RESPONSE_ME(send, ZEND_ACC_PUBLIC)
17466 + HTTP_RESPONSE_ME(capture, ZEND_ACC_PUBLIC)
17467 +
17468 + HTTP_RESPONSE_ALIAS(redirect, http_redirect)
17469 + HTTP_RESPONSE_ALIAS(status, http_send_status)
17470 + HTTP_RESPONSE_ALIAS(getRequestHeaders, http_get_request_headers)
17471 + HTTP_RESPONSE_ALIAS(getRequestBody, http_get_request_body)
17472 + HTTP_RESPONSE_ALIAS(getRequestBodyStream, http_get_request_body_stream)
17473 +
17474 + EMPTY_FUNCTION_ENTRY
17475 +};
17476 +
17477 +PHP_MINIT_FUNCTION(http_response_object)
17478 +{
17479 + HTTP_REGISTER_CLASS(HttpResponse, http_response_object, NULL, 0);
17480 +
17481 + zend_declare_property_bool(THIS_CE, ZEND_STRS("sent")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17482 + zend_declare_property_bool(THIS_CE, ZEND_STRS("catch")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17483 + zend_declare_property_long(THIS_CE, ZEND_STRS("mode")-1, -1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17484 + zend_declare_property_long(THIS_CE, ZEND_STRS("stream")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17485 + zend_declare_property_null(THIS_CE, ZEND_STRS("file")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17486 + zend_declare_property_null(THIS_CE, ZEND_STRS("data")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC);
17487 + zend_declare_property_bool(THIS_CE, ZEND_STRS("cache")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17488 + zend_declare_property_bool(THIS_CE, ZEND_STRS("gzip")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17489 + zend_declare_property_null(THIS_CE, ZEND_STRS("eTag")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17490 + zend_declare_property_long(THIS_CE, ZEND_STRS("lastModified")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17491 + zend_declare_property_null(THIS_CE, ZEND_STRS("cacheControl")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17492 + zend_declare_property_null(THIS_CE, ZEND_STRS("contentType")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17493 + zend_declare_property_null(THIS_CE, ZEND_STRS("contentDisposition")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17494 + zend_declare_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17495 + zend_declare_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, 0.0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC);
17496 +
17497 +#ifndef WONKY
17498 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT")-1, HTTP_REDIRECT TSRMLS_CC);
17499 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PERM")-1, HTTP_REDIRECT_PERM TSRMLS_CC);
17500 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_FOUND")-1, HTTP_REDIRECT_FOUND TSRMLS_CC);
17501 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_POST")-1, HTTP_REDIRECT_POST TSRMLS_CC);
17502 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PROXY")-1, HTTP_REDIRECT_PROXY TSRMLS_CC);
17503 + zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_TEMP")-1, HTTP_REDIRECT_TEMP TSRMLS_CC);
17504 +#endif /* WONKY */
17505 +
17506 + return SUCCESS;
17507 +}
17508 +
17509 +/* ### USERLAND ### */
17510 +
17511 +/* {{{ proto static bool HttpResponse::setHeader(string name[, mixed value[, bool replace = true]])
17512 + Send an HTTP header. */
17513 +PHP_METHOD(HttpResponse, setHeader)
17514 +{
17515 + zend_bool replace = 1;
17516 + char *name;
17517 + int name_len = 0;
17518 + zval *value = NULL;
17519 +
17520 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/!b", &name, &name_len, &value, &replace)) {
17521 + RETURN_FALSE;
17522 + }
17523 + if (SG(headers_sent)) {
17524 + http_error(HE_WARNING, HTTP_E_HEADER, "Cannot add another header when headers have already been sent");
17525 + RETURN_FALSE;
17526 + }
17527 + if (!name_len) {
17528 + http_error(HE_WARNING, HTTP_E_HEADER, "Cannot send anonymous headers");
17529 + RETURN_FALSE;
17530 + }
17531 + http_send_header_zval_ex(name, name_len, &value, replace);
17532 + RETURN_TRUE;
17533 +}
17534 +/* }}} */
17535 +
17536 +/* {{{ proto static mixed HttpResponse::getHeader([string name])
17537 + Get header(s) about to be sent. */
17538 +PHP_METHOD(HttpResponse, getHeader)
17539 +{
17540 + char *name = NULL;
17541 + int name_len = 0;
17542 +
17543 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len)) {
17544 + RETURN_FALSE;
17545 + }
17546 +
17547 + if (name && name_len) {
17548 + zval **header;
17549 + HashTable headers_ht;
17550 +
17551 + zend_hash_init(&headers_ht, sizeof(zval *), NULL, ZVAL_PTR_DTOR, 0);
17552 + if ( (SUCCESS == http_get_response_headers(&headers_ht)) &&
17553 + (SUCCESS == zend_hash_find(&headers_ht, name, name_len + 1, (void *) &header))) {
17554 + RETVAL_ZVAL(*header, 1, 0);
17555 + } else {
17556 + RETVAL_NULL();
17557 + }
17558 + zend_hash_destroy(&headers_ht);
17559 + } else {
17560 + array_init(return_value);
17561 + http_get_response_headers(Z_ARRVAL_P(return_value));
17562 + }
17563 +}
17564 +/* }}} */
17565 +
17566 +/* {{{ proto static bool HttpResponse::setCache(bool cache)
17567 + Whether it should be attempted to cache the entity. */
17568 +PHP_METHOD(HttpResponse, setCache)
17569 +{
17570 + zend_bool do_cache = 0;
17571 +
17572 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
17573 + RETURN_FALSE;
17574 + }
17575 +
17576 + RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("cache")-1, do_cache TSRMLS_CC));
17577 +}
17578 +/* }}} */
17579 +
17580 +/* {{{ proto static bool HttpResponse::getCache()
17581 + Get current caching setting. */
17582 +PHP_METHOD(HttpResponse, getCache)
17583 +{
17584 + NO_ARGS;
17585 +
17586 + if (return_value_used) {
17587 + zval *cache = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17588 + RETVAL_ZVAL(cache, 1, 1);
17589 + }
17590 +}
17591 +/* }}}*/
17592 +
17593 +/* {{{ proto static bool HttpResponse::setGzip(bool gzip)
17594 + Enable on-thy-fly gzipping of the sent entity. */
17595 +PHP_METHOD(HttpResponse, setGzip)
17596 +{
17597 + zend_bool do_gzip = 0;
17598 +
17599 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
17600 + RETURN_FALSE;
17601 + }
17602 +
17603 + RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("gzip")-1, do_gzip TSRMLS_CC));
17604 +}
17605 +/* }}} */
17606 +
17607 +/* {{{ proto static bool HttpResponse::getGzip()
17608 + Get current gzipping setting. */
17609 +PHP_METHOD(HttpResponse, getGzip)
17610 +{
17611 + NO_ARGS;
17612 +
17613 + if (return_value_used) {
17614 + zval *gzip = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17615 + RETVAL_ZVAL(gzip, 1, 1);
17616 + }
17617 +}
17618 +/* }}} */
17619 +
17620 +/* {{{ proto static bool HttpResponse::setCacheControl(string control[, int max_age = 0[, bool must_revalidate = true]])
17621 + 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. */
17622 +PHP_METHOD(HttpResponse, setCacheControl)
17623 +{
17624 + char *ccontrol, *cctl;
17625 + int cc_len;
17626 + long max_age = 0;
17627 + zend_bool must_revalidate = 1;
17628 +
17629 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &ccontrol, &cc_len, &max_age, &must_revalidate)) {
17630 + RETURN_FALSE;
17631 + }
17632 +
17633 + if (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache")) {
17634 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
17635 + RETURN_FALSE;
17636 + } else {
17637 + size_t cctl_len = spprintf(&cctl, 0, "%s,%s max-age=%ld", ccontrol, must_revalidate?" must-revalidate,":"", max_age);
17638 + RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("cacheControl")-1, cctl, cctl_len TSRMLS_CC));
17639 + efree(cctl);
17640 + }
17641 +}
17642 +/* }}} */
17643 +
17644 +/* {{{ proto static string HttpResponse::getCacheControl()
17645 + Get current Cache-Control header setting. */
17646 +PHP_METHOD(HttpResponse, getCacheControl)
17647 +{
17648 + NO_ARGS;
17649 +
17650 + if (return_value_used) {
17651 + zval *cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17652 + RETVAL_ZVAL(cctl, 1, 1);
17653 + }
17654 +}
17655 +/* }}} */
17656 +
17657 +/* {{{ proto static bool HttpResponse::setContentType(string content_type)
17658 + Set the content-type of the sent entity. */
17659 +PHP_METHOD(HttpResponse, setContentType)
17660 +{
17661 + char *ctype;
17662 + int ctype_len;
17663 +
17664 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
17665 + RETURN_FALSE;
17666 + }
17667 +
17668 + HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE);
17669 + RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentType")-1, ctype, ctype_len TSRMLS_CC));
17670 +}
17671 +/* }}} */
17672 +
17673 +/* {{{ proto static string HttpResponse::getContentType()
17674 + Get current Content-Type header setting. */
17675 +PHP_METHOD(HttpResponse, getContentType)
17676 +{
17677 + NO_ARGS;
17678 +
17679 + if (return_value_used) {
17680 + zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17681 + RETVAL_ZVAL(ctype, 1, 1);
17682 + }
17683 +}
17684 +/* }}} */
17685 +
17686 +/* {{{ proto static string HttpResponse::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
17687 + Attempts to guess the content type of supplied payload through libmagic. */
17688 +PHP_METHOD(HttpResponse, guessContentType)
17689 +{
17690 +#ifdef HTTP_HAVE_MAGIC
17691 + char *magic_file, *ct = NULL;
17692 + int magic_file_len;
17693 + long magic_mode = MAGIC_MIME;
17694 +
17695 + RETVAL_FALSE;
17696 + SET_EH_THROW_HTTP();
17697 + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
17698 + switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
17699 + case SEND_DATA:
17700 + {
17701 + zval *data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
17702 + ct = http_guess_content_type(magic_file, magic_mode, Z_STRVAL_P(data), Z_STRLEN_P(data), SEND_DATA);
17703 + break;
17704 + }
17705 +
17706 + case SEND_RSRC:
17707 + {
17708 + php_stream *s;
17709 + zval *z = *zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
17710 + z->type = IS_RESOURCE;
17711 + php_stream_from_zval(s, &z);
17712 + ct = http_guess_content_type(magic_file, magic_mode, s, 0, SEND_RSRC);
17713 + break;
17714 + }
17715 +
17716 + default:
17717 + 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);
17718 + break;
17719 + }
17720 + if (ct) {
17721 + zend_update_static_property_string(THIS_CE, ZEND_STRS("contentType")-1, ct TSRMLS_CC);
17722 + RETVAL_STRING(ct, 0);
17723 + }
17724 + }
17725 + SET_EH_NORMAL();
17726 +#else
17727 + http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
17728 + RETURN_FALSE;
17729 +#endif
17730 +}
17731 +/* }}} */
17732 +
17733 +/* {{{ proto static bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
17734 + Set the Content-Disposition. */
17735 +PHP_METHOD(HttpResponse, setContentDisposition)
17736 +{
17737 + char *file, *cd;
17738 + int file_len;
17739 + size_t cd_len;
17740 + zend_bool send_inline = 0;
17741 +
17742 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &send_inline)) {
17743 + RETURN_FALSE;
17744 + }
17745 +
17746 + cd_len = spprintf(&cd, 0, "%s; filename=\"%s\"", send_inline ? "inline" : "attachment", file);
17747 + RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentDisposition")-1, cd, cd_len TSRMLS_CC));
17748 + efree(cd);
17749 +}
17750 +/* }}} */
17751 +
17752 +/* {{{ proto static string HttpResponse::getContentDisposition()
17753 + Get current Content-Disposition setting. */
17754 +PHP_METHOD(HttpResponse, getContentDisposition)
17755 +{
17756 + NO_ARGS;
17757 +
17758 + if (return_value_used) {
17759 + zval *cdisp = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17760 + RETVAL_ZVAL(cdisp, 1, 1);
17761 + }
17762 +}
17763 +/* }}} */
17764 +
17765 +/* {{{ proto static bool HttpResponse::setETag(string etag)
17766 + Set a custom ETag. Use this only if you know what you're doing. */
17767 +PHP_METHOD(HttpResponse, setETag)
17768 +{
17769 + char *etag;
17770 + int etag_len;
17771 +
17772 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
17773 + RETURN_FALSE;
17774 + }
17775 +
17776 + RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("eTag")-1, etag, etag_len TSRMLS_CC));
17777 +}
17778 +/* }}} */
17779 +
17780 +/* {{{ proto static string HttpResponse::getETag()
17781 + Get calculated or previously set custom ETag. */
17782 +PHP_METHOD(HttpResponse, getETag)
17783 +{
17784 + NO_ARGS;
17785 +
17786 + if (return_value_used) {
17787 + zval *etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17788 + RETVAL_ZVAL(etag, 1, 1);
17789 + }
17790 +}
17791 +/* }}} */
17792 +
17793 +/* {{{ proto static bool HttpResponse::setLastModified(int timestamp)
17794 + Set a custom Last-Modified date. */
17795 +PHP_METHOD(HttpResponse, setLastModified)
17796 +{
17797 + long lm;
17798 +
17799 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lm)) {
17800 + RETURN_FALSE;
17801 + }
17802 +
17803 + RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, lm TSRMLS_CC));
17804 +}
17805 +/* }}} */
17806 +
17807 +/* {{{ proto static int HttpResponse::getLastModified()
17808 + Get calculated or previously set custom Last-Modified date. */
17809 +PHP_METHOD(HttpResponse, getLastModified)
17810 +{
17811 + NO_ARGS;
17812 +
17813 + if (return_value_used) {
17814 + zval *lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17815 + RETVAL_ZVAL(lmod, 1, 1);
17816 + }
17817 +}
17818 +/* }}} */
17819 +
17820 +/* {{{ proto static bool HttpResponse::setThrottleDelay(double seconds)
17821 + Sets the throttle delay for use with HttpResponse::setBufferSize(). */
17822 +PHP_METHOD(HttpResponse, setThrottleDelay)
17823 +{
17824 + double seconds;
17825 +
17826 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) {
17827 + RETURN_FALSE;
17828 + }
17829 + RETURN_SUCCESS(zend_update_static_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, seconds TSRMLS_CC));
17830 +}
17831 +/* }}} */
17832 +
17833 +/* {{{ proto static double HttpResponse::getThrottleDelay()
17834 + Get the current throttle delay. */
17835 +PHP_METHOD(HttpResponse, getThrottleDelay)
17836 +{
17837 + NO_ARGS;
17838 +
17839 + if (return_value_used) {
17840 + zval *tdel = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17841 + RETVAL_ZVAL(tdel, 1, 1);
17842 + }
17843 +}
17844 +/* }}} */
17845 +
17846 +/* {{{ proto static bool HttpResponse::setBufferSize(int bytes)
17847 + Sets the send buffer size for use with HttpResponse::setThrottleDelay(). */
17848 +PHP_METHOD(HttpResponse, setBufferSize)
17849 +{
17850 + long bytes;
17851 +
17852 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) {
17853 + RETURN_FALSE;
17854 + }
17855 + RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, bytes TSRMLS_CC));
17856 +}
17857 +/* }}} */
17858 +
17859 +/* {{{ proto static int HttpResponse::getBufferSize()
17860 + Get current buffer size. */
17861 +PHP_METHOD(HttpResponse, getBufferSize)
17862 +{
17863 + NO_ARGS;
17864 +
17865 + if (return_value_used) {
17866 + zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17867 + RETVAL_ZVAL(bsize, 1, 1);
17868 + }
17869 +}
17870 +/* }}} */
17871 +
17872 +/* {{{ proto static bool HttpResponse::setData(mixed data)
17873 + Set the data to be sent. */
17874 +PHP_METHOD(HttpResponse, setData)
17875 +{
17876 + char *etag;
17877 + zval *the_data;
17878 +
17879 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) {
17880 + RETURN_FALSE;
17881 + }
17882 + if (Z_TYPE_P(the_data) != IS_STRING) {
17883 + convert_to_string(the_data);
17884 + }
17885 +
17886 + if ( (SUCCESS != zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC)) ||
17887 + (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_DATA TSRMLS_CC))) {
17888 + RETURN_FALSE;
17889 + }
17890 +
17891 + zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_data, SEND_DATA) TSRMLS_CC);
17892 + if ((etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA))) {
17893 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
17894 + efree(etag);
17895 + }
17896 +
17897 + RETURN_TRUE;
17898 +}
17899 +/* }}} */
17900 +
17901 +/* {{{ proto static string HttpResponse::getData()
17902 + Get the previously set data to be sent. */
17903 +PHP_METHOD(HttpResponse, getData)
17904 +{
17905 + NO_ARGS;
17906 +
17907 + if (return_value_used) {
17908 + zval *the_data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
17909 +
17910 + RETURN_ZVAL(the_data, 1, 0);
17911 + }
17912 +}
17913 +/* }}} */
17914 +
17915 +/* {{{ proto static bool HttpResponse::setStream(resource stream)
17916 + Set the resource to be sent. */
17917 +PHP_METHOD(HttpResponse, setStream)
17918 +{
17919 + char *etag;
17920 + zval *the_stream;
17921 + php_stream *the_real_stream;
17922 + php_stream_statbuf ssb;
17923 +
17924 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
17925 + RETURN_FALSE;
17926 + }
17927 +
17928 + php_stream_from_zval(the_real_stream, &the_stream);
17929 + if (php_stream_stat(the_real_stream, &ssb)) {
17930 + RETURN_FALSE;
17931 + }
17932 +
17933 + if ( (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("stream")-1, Z_LVAL_P(the_stream) TSRMLS_CC)) ||
17934 + (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_RSRC TSRMLS_CC))) {
17935 + RETURN_FALSE;
17936 + }
17937 + zend_list_addref(Z_LVAL_P(the_stream));
17938 +
17939 + zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_real_stream, SEND_RSRC) TSRMLS_CC);
17940 + if ((etag = http_etag(the_real_stream, 0, SEND_RSRC))) {
17941 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
17942 + efree(etag);
17943 + }
17944 +
17945 + RETURN_TRUE;
17946 +}
17947 +/* }}} */
17948 +
17949 +/* {{{ proto static resource HttpResponse::getStream()
17950 + Get the previously set resource to be sent. */
17951 +PHP_METHOD(HttpResponse, getStream)
17952 +{
17953 + NO_ARGS;
17954 +
17955 + if (return_value_used) {
17956 + zval *stream = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
17957 + RETVAL_RESOURCE(Z_LVAL_P(stream));
17958 + zval_ptr_dtor(&stream);
17959 + }
17960 +}
17961 +/* }}} */
17962 +
17963 +/* {{{ proto static bool HttpResponse::setFile(string file)
17964 + Set the file to be sent. */
17965 +PHP_METHOD(HttpResponse, setFile)
17966 +{
17967 + char *the_file, *etag;
17968 + int file_len;
17969 + php_stream_statbuf ssb;
17970 +
17971 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &the_file, &file_len)) {
17972 + RETURN_FALSE;
17973 + }
17974 +
17975 + if (php_stream_stat_path(the_file, &ssb)) {
17976 + RETURN_FALSE;
17977 + }
17978 +
17979 + if ( (SUCCESS != zend_update_static_property_stringl(THIS_CE, ZEND_STRS("file")-1, the_file, file_len TSRMLS_CC)) ||
17980 + (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, -1 TSRMLS_CC))) {
17981 + RETURN_FALSE;
17982 + }
17983 +
17984 + zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_file, -1) TSRMLS_CC);
17985 + if ((etag = http_etag(the_file, 0, -1))) {
17986 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
17987 + efree(etag);
17988 + }
17989 +
17990 + RETURN_TRUE;
17991 +}
17992 +/* }}} */
17993 +
17994 +/* {{{ proto static string HttpResponse::getFile()
17995 + Get the previously set file to be sent. */
17996 +PHP_METHOD(HttpResponse, getFile)
17997 +{
17998 + NO_ARGS;
17999 +
18000 + if (return_value_used) {
18001 + zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18002 + RETVAL_ZVAL(file, 1, 1);
18003 + }
18004 +}
18005 +/* }}} */
18006 +
18007 +/* {{{ proto static bool HttpResponse::send([bool clean_ob = true])
18008 + Finally send the entity. */
18009 +PHP_METHOD(HttpResponse, send)
18010 +{
18011 + zval *sent;
18012 + zend_bool clean_ob = 1;
18013 +
18014 + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) {
18015 + RETURN_FALSE;
18016 + }
18017 +
18018 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
18019 +
18020 + sent = *zend_std_get_static_property(THIS_CE, ZEND_STRS("sent")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC);
18021 + if (Z_LVAL_P(sent)) {
18022 + http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, response has already been sent");
18023 + RETURN_FALSE;
18024 + } else {
18025 + Z_LVAL_P(sent) = 1;
18026 + }
18027 +
18028 + /* capture mode */
18029 + if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("catch")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
18030 + zval *zetag, *the_data;
18031 +
18032 + MAKE_STD_ZVAL(the_data);
18033 +#ifdef PHP_OUTPUT_NEWAPI
18034 + php_output_get_contents(the_data TSRMLS_CC);
18035 +#else
18036 + php_ob_get_buffer(the_data TSRMLS_CC);
18037 +#endif
18038 + zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC);
18039 + ZVAL_LONG(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC), SEND_DATA);
18040 +
18041 + zetag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18042 + if (!Z_STRLEN_P(zetag)) {
18043 + char *etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA);
18044 + if (etag) {
18045 + zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC);
18046 + efree(etag);
18047 + }
18048 + }
18049 + zval_ptr_dtor(&the_data);
18050 + zval_ptr_dtor(&zetag);
18051 +
18052 + clean_ob = 1;
18053 + }
18054 +
18055 + if (clean_ob) {
18056 + /* interrupt on-the-fly etag generation */
18057 + HTTP_G->etag.started = 0;
18058 + /* discard previous output buffers */
18059 +#ifdef PHP_OUTPUT_NEWAPI
18060 + php_output_discard_all(TSRMLS_C);
18061 +#else
18062 + php_end_ob_buffers(0 TSRMLS_CC);
18063 +#endif
18064 + }
18065 +
18066 + /* caching */
18067 + if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
18068 + zval *cctl, *etag, *lmod;
18069 +
18070 + lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18071 + etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18072 + cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18073 +
18074 + if (Z_LVAL_P(lmod) || Z_STRLEN_P(etag)) {
18075 + if (Z_STRLEN_P(cctl)) {
18076 + http_send_cache_control(Z_STRVAL_P(cctl), Z_STRLEN_P(cctl));
18077 + } else {
18078 + http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
18079 + }
18080 + if (Z_STRLEN_P(etag)) {
18081 + http_send_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag));
18082 + }
18083 + if (Z_LVAL_P(lmod)) {
18084 + http_send_last_modified(Z_LVAL_P(lmod));
18085 + }
18086 + }
18087 +
18088 + zval_ptr_dtor(&etag);
18089 + zval_ptr_dtor(&lmod);
18090 + zval_ptr_dtor(&cctl);
18091 + }
18092 +
18093 + /* content type */
18094 + {
18095 + zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18096 + if (Z_STRLEN_P(ctype)) {
18097 + http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
18098 + } else {
18099 + char *ctypes = INI_STR("default_mimetype");
18100 + size_t ctlen = ctypes ? strlen(ctypes) : 0;
18101 +
18102 + if (ctlen) {
18103 + http_send_content_type(ctypes, ctlen);
18104 + } else {
18105 + http_send_content_type("application/x-octetstream", lenof("application/x-octetstream"));
18106 + }
18107 + }
18108 + zval_ptr_dtor(&ctype);
18109 + }
18110 +
18111 + /* content disposition */
18112 + {
18113 + zval *cd = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18114 + if (Z_STRLEN_P(cd)) {
18115 + http_send_header_ex("Content-Disposition", lenof("Content-Disposition"), Z_STRVAL_P(cd), Z_STRLEN_P(cd), 1, NULL);
18116 + }
18117 + zval_ptr_dtor(&cd);
18118 + }
18119 +
18120 + /* throttling */
18121 + {
18122 + zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18123 + zval *delay = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18124 + HTTP_G->send.buffer_size = Z_LVAL_P(bsize);
18125 + HTTP_G->send.throttle_delay = Z_DVAL_P(delay);
18126 + zval_ptr_dtor(&bsize);
18127 + zval_ptr_dtor(&delay);
18128 + }
18129 +
18130 + /* gzip */
18131 + 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));
18132 +
18133 + /* send */
18134 + switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) {
18135 + case SEND_DATA:
18136 + {
18137 + zval *zdata = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18138 + RETVAL_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
18139 + zval_ptr_dtor(&zdata);
18140 + return;
18141 + }
18142 +
18143 + case SEND_RSRC:
18144 + {
18145 + php_stream *the_real_stream;
18146 + 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)));
18147 + the_stream->type = IS_RESOURCE;
18148 + php_stream_from_zval(the_real_stream, &the_stream);
18149 + RETVAL_SUCCESS(http_send_stream(the_real_stream));
18150 + zval_ptr_dtor(&the_stream);
18151 + return;
18152 + }
18153 +
18154 + default:
18155 + {
18156 + zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)));
18157 + RETVAL_SUCCESS(http_send_file(Z_STRVAL_P(file)));
18158 + zval_ptr_dtor(&file);
18159 + return;
18160 + }
18161 + }
18162 +}
18163 +/* }}} */
18164 +
18165 +/* {{{ proto static void HttpResponse::capture()
18166 + Capture script output.
18167 + */
18168 +PHP_METHOD(HttpResponse, capture)
18169 +{
18170 + NO_ARGS;
18171 +
18172 + HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
18173 +
18174 + zend_update_static_property_long(THIS_CE, ZEND_STRS("catch")-1, 1 TSRMLS_CC);
18175 +#ifdef PHP_OUTPUT_NEWAPI
18176 + php_output_discard_all(TSRMLS_C);
18177 + php_output_start_default(TSRMLS_C);
18178 +#else
18179 + php_end_ob_buffers(0 TSRMLS_CC);
18180 + php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC);
18181 +#endif
18182 +
18183 + /* register shutdown function */
18184 + {
18185 + zval func, retval, arg, *argp[1];
18186 +
18187 + INIT_PZVAL(&arg);
18188 + INIT_PZVAL(&func);
18189 + INIT_PZVAL(&retval);
18190 + ZVAL_STRINGL(&func, "register_shutdown_function", lenof("register_shutdown_function"), 0);
18191 +
18192 + array_init(&arg);
18193 + add_next_index_stringl(&arg, "HttpResponse", lenof("HttpResponse"), 1);
18194 + add_next_index_stringl(&arg, "send", lenof("send"), 1);
18195 + argp[0] = &arg;
18196 + call_user_function(EG(function_table), NULL, &func, &retval, 1, argp TSRMLS_CC);
18197 + zval_dtor(&arg);
18198 + }
18199 +}
18200 +/* }}} */
18201 +
18202 +#endif /* ZEND_ENGINE_2 && !WONKY */
18203 +
18204 +/*
18205 + * Local variables:
18206 + * tab-width: 4
18207 + * c-basic-offset: 4
18208 + * End:
18209 + * vim600: noet sw=4 ts=4 fdm=marker
18210 + * vim<600: noet sw=4 ts=4
18211 + */
18212 +
18213 --- /dev/null
18214 +++ b/ext/http/http_send_api.c
18215 @@ -0,0 +1,611 @@
18216 +/*
18217 + +--------------------------------------------------------------------+
18218 + | PECL :: http |
18219 + +--------------------------------------------------------------------+
18220 + | Redistribution and use in source and binary forms, with or without |
18221 + | modification, are permitted provided that the conditions mentioned |
18222 + | in the accompanying LICENSE file are met. |
18223 + +--------------------------------------------------------------------+
18224 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
18225 + +--------------------------------------------------------------------+
18226 +*/
18227 +
18228 +/* $Id: http_send_api.c 312028 2011-06-10 22:03:12Z felipe $ */
18229 +
18230 +#define HTTP_WANT_SAPI
18231 +#define HTTP_WANT_ZLIB
18232 +#define HTTP_WANT_MAGIC
18233 +#include "php_http.h"
18234 +
18235 +#include "php_streams.h"
18236 +
18237 +#include "php_http_api.h"
18238 +#include "php_http_cache_api.h"
18239 +#include "php_http_date_api.h"
18240 +#include "php_http_encoding_api.h"
18241 +#include "php_http_headers_api.h"
18242 +#include "php_http_send_api.h"
18243 +
18244 +/* {{{ http_flush() */
18245 +#define http_flush(d, l) _http_flush(NULL, (d), (l) TSRMLS_CC)
18246 +static inline void _http_flush(void *nothing, const char *data, size_t data_len TSRMLS_DC)
18247 +{
18248 + PHPWRITE(data, data_len);
18249 + /* we really only need to flush when throttling is enabled,
18250 + because we push the data as fast as possible anyway if not */
18251 + if (HTTP_G->send.throttle_delay >= HTTP_DIFFSEC) {
18252 +#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50399)
18253 + php_output_end_all(TSRMLS_C);
18254 +#else
18255 + if (OG(ob_nesting_level)) {
18256 + php_end_ob_buffer(1, 1 TSRMLS_CC);
18257 + }
18258 + if (!OG(implicit_flush)) {
18259 + sapi_flush(TSRMLS_C);
18260 + }
18261 +#endif
18262 + http_sleep(HTTP_G->send.throttle_delay);
18263 + }
18264 +}
18265 +/* }}} */
18266 +
18267 +/* {{{ http_send_response_start */
18268 +#define http_send_response_start(b, cl) _http_send_response_start((b), (cl) TSRMLS_CC)
18269 +static inline void _http_send_response_start(void **buffer, size_t content_length TSRMLS_DC)
18270 +{
18271 + int encoding;
18272 +
18273 + if ((encoding = http_encoding_response_start(content_length, 0))) {
18274 +#ifdef HTTP_HAVE_ZLIB
18275 + *((http_encoding_stream **) buffer) = http_encoding_deflate_stream_init(NULL,
18276 + (encoding == HTTP_ENCODING_GZIP) ?
18277 + HTTP_DEFLATE_TYPE_GZIP : HTTP_DEFLATE_TYPE_ZLIB);
18278 +#endif
18279 + }
18280 + /* flush headers */
18281 + sapi_flush(TSRMLS_C);
18282 +}
18283 +/* }}} */
18284 +
18285 +/* {{{ http_send_response_data_plain */
18286 +#define http_send_response_data_plain(b, d, dl) _http_send_response_data_plain((b), (d), (dl) TSRMLS_CC)
18287 +static inline void _http_send_response_data_plain(void **buffer, const char *data, size_t data_len TSRMLS_DC)
18288 +{
18289 + if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) {
18290 +#ifdef HTTP_HAVE_ZLIB
18291 + char *encoded;
18292 + size_t encoded_len;
18293 + http_encoding_stream *s = *((http_encoding_stream **) buffer);
18294 +
18295 + http_encoding_deflate_stream_update(s, data, data_len, &encoded, &encoded_len);
18296 + if (HTTP_G->send.buffer_size) {
18297 + phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC);
18298 + } else {
18299 + http_flush(encoded, encoded_len);
18300 + }
18301 + efree(encoded);
18302 +#else
18303 + http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug");
18304 +#endif
18305 + } else if (HTTP_G->send.buffer_size) {
18306 + phpstr_chunked_output((phpstr **) buffer, data, data_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC);
18307 + } else {
18308 + http_flush(data, data_len);
18309 + }
18310 +}
18311 +/* }}} */
18312 +
18313 +/* {{{ http_send_response_data_fetch */
18314 +#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)
18315 +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)
18316 +{
18317 + long bsz, got, len = end - begin;
18318 +
18319 + if (!(bsz = HTTP_G->send.buffer_size)) {
18320 + bsz = HTTP_SENDBUF_SIZE;
18321 + }
18322 +
18323 + switch (mode) {
18324 + case SEND_RSRC: {
18325 + php_stream *s = (php_stream *) data;
18326 + if (SUCCESS == php_stream_seek(s, begin, SEEK_SET)) {
18327 + char *buf = emalloc(bsz);
18328 +
18329 + while (len > 0) {
18330 + got = php_stream_read(s, buf, MIN(len, bsz));
18331 + http_send_response_data_plain(buffer, buf, got);
18332 + len -= got;
18333 + }
18334 +
18335 + efree(buf);
18336 + }
18337 + break;
18338 + }
18339 + case SEND_DATA: {
18340 + const char *buf = ((const char *) data) + begin;
18341 + while (len > 0) {
18342 + got = MIN(len, bsz);
18343 + http_send_response_data_plain(buffer, buf, got);
18344 + len -= got;
18345 + buf += got;
18346 + }
18347 + break;
18348 + }
18349 + EMPTY_SWITCH_DEFAULT_CASE();
18350 + }
18351 +}
18352 +/* }}} */
18353 +
18354 +/* {{{ http_send_response_finish */
18355 +#define http_send_response_finish(b) _http_send_response_finish((b) TSRMLS_CC)
18356 +static inline void _http_send_response_finish(void **buffer TSRMLS_DC)
18357 +{
18358 + if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) {
18359 +#ifdef HTTP_HAVE_ZLIB
18360 + char *encoded = NULL;
18361 + size_t encoded_len = 0;
18362 + http_encoding_stream *s = *((http_encoding_stream **) buffer);
18363 +
18364 + http_encoding_deflate_stream_finish(s, &encoded, &encoded_len);
18365 + if (HTTP_G->send.buffer_size) {
18366 + phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, 0, _http_flush, NULL TSRMLS_CC);
18367 + } else {
18368 + http_flush(encoded, encoded_len);
18369 + }
18370 + http_encoding_deflate_stream_free(&s);
18371 + STR_FREE(encoded);
18372 +#else
18373 + http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug");
18374 +#endif
18375 + } else if (HTTP_G->send.buffer_size) {
18376 + phpstr_chunked_output((phpstr **) buffer, NULL, 0, 0, _http_flush, NULL TSRMLS_CC);
18377 + }
18378 +}
18379 +/* }}} */
18380 +
18381 +/* {{{ */
18382 +PHP_MINIT_FUNCTION(http_send)
18383 +{
18384 + HTTP_LONG_CONSTANT("HTTP_REDIRECT", HTTP_REDIRECT);
18385 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_PERM", HTTP_REDIRECT_PERM);
18386 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_FOUND", HTTP_REDIRECT_FOUND);
18387 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_POST", HTTP_REDIRECT_POST);
18388 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_PROXY", HTTP_REDIRECT_PROXY);
18389 + HTTP_LONG_CONSTANT("HTTP_REDIRECT_TEMP", HTTP_REDIRECT_TEMP);
18390 +
18391 + return SUCCESS;
18392 +}
18393 +/* }}} */
18394 +
18395 +/* {{{ http_find_header */
18396 +typedef struct {
18397 + const char *h;
18398 + size_t l;
18399 +} http_response_header_t;
18400 +
18401 +static int http_find_header(void *data, void *arg)
18402 +{
18403 + http_response_header_t *h = arg;
18404 + sapi_header_struct *s = data;
18405 +
18406 + return (!strncasecmp(s->header, h->h, h->l)) && s->header[h->l] == ':';
18407 +}
18408 +/* }}} */
18409 +
18410 +/* {{{ void http_hide_header(char *) */
18411 +PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC)
18412 +{
18413 + http_response_header_t h = {name, name_len};
18414 + zend_llist_del_element(&SG(sapi_headers).headers, (void *) &h, http_find_header);
18415 +}
18416 +/* }}} */
18417 +
18418 +/* {{{ void http_send_header_zval(char*, zval **, zend_bool) */
18419 +PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC)
18420 +{
18421 + if (!val || !*val || Z_TYPE_PP(val) == IS_NULL || (Z_TYPE_PP(val) == IS_STRING && !Z_STRLEN_PP(val))) {
18422 + http_hide_header_ex(name, name_len);
18423 + } else if (Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT) {
18424 + zend_bool first = replace;
18425 + zval **data_ptr;
18426 + HashPosition pos;
18427 +
18428 + FOREACH_HASH_VAL(pos, HASH_OF(*val), data_ptr) {
18429 + zval *data = http_zsep(IS_STRING, *data_ptr);
18430 +
18431 + http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), first, NULL);
18432 + zval_ptr_dtor(&data);
18433 + first = 0;
18434 + }
18435 + } else {
18436 + zval *data = http_zsep(IS_STRING, *val);
18437 +
18438 + http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), replace, NULL);
18439 + zval_ptr_dtor(&data);
18440 + }
18441 +}
18442 +/* }}} */
18443 +
18444 +/* {{{ STATUS http_send_header(char *, char *, zend_bool) */
18445 +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)
18446 +{
18447 + STATUS ret;
18448 +
18449 + if (value && value_len) {
18450 + size_t header_len = sizeof(": ") + name_len + value_len + 1;
18451 + char *header = emalloc(header_len + 1);
18452 +
18453 + header[header_len] = '\0';
18454 + header_len = snprintf(header, header_len, "%s: %s", name, value);
18455 + ret = http_send_header_string_ex(header, header_len, replace);
18456 + if (sent_header) {
18457 + *sent_header = header;
18458 + } else {
18459 + efree(header);
18460 + }
18461 + } else {
18462 + http_hide_header_ex(name, name_len);
18463 + ret = SUCCESS;
18464 + }
18465 + return ret;
18466 +}
18467 +/* }}} */
18468 +
18469 +/* {{{ STATUS http_send_status_header(int, char *) */
18470 +PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC)
18471 +{
18472 + STATUS ret;
18473 + sapi_header_line h = {(char *) header, header_len, status};
18474 + if (SUCCESS != (ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, &h TSRMLS_CC))) {
18475 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status);
18476 + }
18477 + return ret;
18478 +}
18479 +/* }}} */
18480 +
18481 +/* {{{ STATUS http_send_last_modified(int) */
18482 +PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC)
18483 +{
18484 + STATUS ret;
18485 + char *date = http_date(t);
18486 +
18487 + if (!date) {
18488 + return FAILURE;
18489 + }
18490 +
18491 + ret = http_send_header_ex("Last-Modified", lenof("Last-Modified"), date, strlen(date), 1, sent_header);
18492 + efree(date);
18493 +
18494 + /* remember */
18495 + HTTP_G->send.last_modified = t;
18496 +
18497 + return ret;
18498 +}
18499 +/* }}} */
18500 +
18501 +/* {{{ STATUS http_send_etag(char *, size_t) */
18502 +PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC)
18503 +{
18504 + STATUS status;
18505 + char *etag_header;
18506 + size_t etag_header_len;
18507 +
18508 + if (!etag_len){
18509 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G->send.unquoted_etag);
18510 + return FAILURE;
18511 + }
18512 +
18513 + etag_header_len = spprintf(&etag_header, 0, "ETag: \"%s\"", etag);
18514 + status = http_send_header_string_ex(etag_header, etag_header_len, 1);
18515 +
18516 + /* remember */
18517 + STR_SET(HTTP_G->send.unquoted_etag, estrndup(etag, etag_len));
18518 +
18519 + if (sent_header) {
18520 + *sent_header = etag_header;
18521 + } else {
18522 + efree(etag_header);
18523 + }
18524 +
18525 + return status;
18526 +}
18527 +/* }}} */
18528 +
18529 +/* {{{ STATUS http_send_content_type(char *, size_t) */
18530 +PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC)
18531 +{
18532 + HTTP_CHECK_CONTENT_TYPE(content_type, return FAILURE);
18533 +
18534 + /* remember for multiple ranges */
18535 + STR_FREE(HTTP_G->send.content_type);
18536 + HTTP_G->send.content_type = estrndup(content_type, ct_len);
18537 +
18538 + return http_send_header_ex("Content-Type", lenof("Content-Type"), content_type, ct_len, 1, NULL);
18539 +}
18540 +/* }}} */
18541 +
18542 +/* {{{ STATUS http_send_content_disposition(char *, size_t, zend_bool) */
18543 +PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC)
18544 +{
18545 + STATUS status;
18546 + char *cd_header;
18547 +
18548 + if (send_inline) {
18549 + cd_header = ecalloc(1, sizeof("Content-Disposition: inline; filename=\"\"") + f_len);
18550 + sprintf(cd_header, "Content-Disposition: inline; filename=\"%s\"", filename);
18551 + } else {
18552 + cd_header = ecalloc(1, sizeof("Content-Disposition: attachment; filename=\"\"") + f_len);
18553 + sprintf(cd_header, "Content-Disposition: attachment; filename=\"%s\"", filename);
18554 + }
18555 +
18556 + status = http_send_header_string(cd_header);
18557 + efree(cd_header);
18558 + return status;
18559 +}
18560 +/* }}} */
18561 +
18562 +/* {{{ STATUS http_send(void *, size_t, http_send_mode) */
18563 +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)
18564 +{
18565 + void *s = NULL;
18566 + HashTable ranges;
18567 + http_range_status range_status;
18568 +
18569 + if (!data_ptr) {
18570 + return FAILURE;
18571 + }
18572 + if (!data_size) {
18573 + return SUCCESS;
18574 + }
18575 +
18576 + /* enable partial dl and resume */
18577 + http_send_header_string("Accept-Ranges: bytes");
18578 +
18579 + zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0);
18580 + range_status = http_get_request_ranges(&ranges, data_size);
18581 +
18582 + switch (range_status) {
18583 + case RANGE_ERR:
18584 + {
18585 + zend_hash_destroy(&ranges);
18586 + http_send_status(416);
18587 + return FAILURE;
18588 + }
18589 + case RANGE_OK:
18590 + {
18591 + /* Range Request - only send ranges if entity hasn't changed */
18592 + if ( http_got_server_var("HTTP_IF_RANGE") &&
18593 + !http_match_etag("HTTP_IF_RANGE", HTTP_G->send.unquoted_etag) &&
18594 + !http_match_last_modified("HTTP_IF_RANGE", HTTP_G->send.last_modified)) {
18595 + /* fallthrough to send full entity with 200 Ok */
18596 + no_cache = 1;
18597 + } else if ( !http_match_etag_ex("HTTP_IF_MATCH", HTTP_G->send.unquoted_etag, 0) ||
18598 + !http_match_last_modified_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G->send.last_modified, 0) ||
18599 + !http_match_last_modified_ex("HTTP_UNLESS_MODIFIED_SINCE", HTTP_G->send.last_modified, 0)) {
18600 + /* 412 Precondition failed */
18601 + zend_hash_destroy(&ranges);
18602 + http_send_status(412);
18603 + return FAILURE;
18604 + } else if (zend_hash_num_elements(&ranges) == 1) {
18605 + /* single range */
18606 + zval **range, **begin, **end;
18607 +
18608 + if ( SUCCESS != zend_hash_index_find(&ranges, 0, (void *) &range) ||
18609 + SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) ||
18610 + SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) {
18611 + /* this should never happen */
18612 + zend_hash_destroy(&ranges);
18613 + http_send_status(500);
18614 + return FAILURE;
18615 + } else {
18616 + phpstr header;
18617 +
18618 + phpstr_init(&header);
18619 + phpstr_appendf(&header, "Content-Range: bytes %ld-%ld/%zu", Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size);
18620 + phpstr_fix(&header);
18621 + http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
18622 + phpstr_dtor(&header);
18623 + http_send_response_start(&s, Z_LVAL_PP(end)-Z_LVAL_PP(begin)+1);
18624 + http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1);
18625 + http_send_response_finish(&s);
18626 + zend_hash_destroy(&ranges);
18627 + return SUCCESS;
18628 + }
18629 + } else {
18630 + /* multi range */
18631 + HashPosition pos;
18632 + zval **range, **begin, **end;
18633 + const char *content_type = HTTP_G->send.content_type;
18634 + char boundary_str[32];
18635 + size_t boundary_len;
18636 + phpstr header, preface;
18637 +
18638 + boundary_len = http_boundary(boundary_str, sizeof(boundary_str));
18639 + phpstr_init(&header);
18640 + phpstr_appendf(&header, "Content-Type: multipart/byteranges; boundary=%s", boundary_str);
18641 + phpstr_fix(&header);
18642 + http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1);
18643 + phpstr_dtor(&header);
18644 + http_send_response_start(&s, 0);
18645 +
18646 + if (!content_type) {
18647 + content_type = "application/x-octetstream";
18648 + }
18649 +
18650 + phpstr_init(&preface);
18651 + FOREACH_HASH_VAL(pos, &ranges, range) {
18652 + if ( SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) &&
18653 + SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) {
18654 +
18655 +#define HTTP_RANGE_PREFACE \
18656 + HTTP_CRLF "--%s" \
18657 + HTTP_CRLF "Content-Type: %s" \
18658 + HTTP_CRLF "Content-Range: bytes %ld-%ld/%zu" \
18659 + HTTP_CRLF HTTP_CRLF
18660 +
18661 + phpstr_appendf(&preface, HTTP_RANGE_PREFACE, boundary_str, content_type, Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size);
18662 + phpstr_fix(&preface);
18663 + http_send_response_data_plain(&s, PHPSTR_VAL(&preface), PHPSTR_LEN(&preface));
18664 + phpstr_reset(&preface);
18665 + http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1);
18666 + }
18667 + }
18668 + phpstr_dtor(&preface);
18669 +
18670 + http_send_response_data_plain(&s, HTTP_CRLF "--", lenof(HTTP_CRLF "--"));
18671 + http_send_response_data_plain(&s, boundary_str, boundary_len);
18672 + http_send_response_data_plain(&s, "--", lenof("--"));
18673 +
18674 + http_send_response_finish(&s);
18675 + zend_hash_destroy(&ranges);
18676 + return SUCCESS;
18677 + }
18678 + }
18679 + case RANGE_NO:
18680 + {
18681 + zend_hash_destroy(&ranges);
18682 +
18683 + /* send 304 Not Modified if etag matches - DON'T return on ETag generation failure */
18684 + if (!no_cache && (http_interrupt_ob_etaghandler() || (HTTP_G->send.unquoted_etag != NULL))) {
18685 + char *etag = NULL;
18686 +
18687 + if (HTTP_G->send.unquoted_etag) {
18688 + etag = estrdup(HTTP_G->send.unquoted_etag);
18689 + }
18690 +
18691 + if (etag || (etag = http_etag(data_ptr, data_size, data_mode))) {
18692 + char *sent_header = NULL;
18693 +
18694 + http_send_etag_ex(etag, strlen(etag), &sent_header);
18695 + if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
18696 + return http_exit_ex(304, sent_header, NULL, 0);
18697 + } else {
18698 + STR_FREE(sent_header);
18699 + /* no caching for Last-Modified if ETags really don't match */
18700 + no_cache = http_got_server_var("HTTP_IF_NONE_MATCH");
18701 + }
18702 + efree(etag);
18703 + }
18704 + }
18705 +
18706 + /* send 304 Not Modified if last modified matches */
18707 + if (!no_cache && HTTP_G->send.last_modified && http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G->send.last_modified)) {
18708 + char *sent_header = NULL;
18709 + http_send_last_modified_ex(HTTP_G->send.last_modified, &sent_header);
18710 + return http_exit_ex(304, sent_header, NULL, 0);
18711 + }
18712 +
18713 + /* send full response */
18714 + http_send_response_start(&s, data_size);
18715 + http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, 0, data_size);
18716 + http_send_response_finish(&s);
18717 + return SUCCESS;
18718 + }
18719 + }
18720 + return FAILURE;
18721 +}
18722 +/* }}} */
18723 +
18724 +/* {{{ STATUS http_send_stream(php_stream *) */
18725 +PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file, zend_bool close_stream, zend_bool no_cache TSRMLS_DC)
18726 +{
18727 + STATUS status;
18728 + php_stream_statbuf ssb;
18729 + int orig_flags;
18730 +
18731 + if ((!file) || php_stream_stat(file, &ssb)) {
18732 + char *defct = sapi_get_default_content_type(TSRMLS_C);
18733 +
18734 + http_hide_header("Content-Disposition");
18735 + http_send_content_type(defct, strlen(defct));
18736 + http_error(HE_WARNING, HTTP_E_RESPONSE, "File not found; stat failed");
18737 + STR_FREE(defct);
18738 +
18739 + if (HTTP_G->send.not_found_404) {
18740 + http_exit_ex(404, NULL, estrdup("File not found\n"), 0);
18741 + }
18742 + return FAILURE;
18743 + }
18744 +
18745 + orig_flags = file->flags;
18746 + file->flags |= PHP_STREAM_FLAG_NO_BUFFER;
18747 + status = http_send_ex(file, ssb.sb.st_size, SEND_RSRC, no_cache);
18748 + file->flags = orig_flags;
18749 +
18750 + if (close_stream) {
18751 + php_stream_close(file);
18752 + }
18753 +
18754 + return status;
18755 +}
18756 +/* }}} */
18757 +
18758 +/* {{{ char *http_guess_content_type(char *magic_file, long magic_mode, void *data, size_t size, http_send_mode mode) */
18759 +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)
18760 +{
18761 + char *ct = NULL;
18762 +
18763 +#ifdef HTTP_HAVE_MAGIC
18764 + struct magic_set *magic = NULL;
18765 +
18766 + HTTP_CHECK_OPEN_BASEDIR(magicfile, return NULL);
18767 +
18768 + if (!data_ptr) {
18769 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Supplied payload is empty");
18770 + } else if (!(magic = magic_open(magicmode &~ MAGIC_MIME))) {
18771 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid magic mode: %ld", magicmode);
18772 + } else if (-1 == magic_load(magic, magicfile)) {
18773 + http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to load magic database '%s' (%s)", magicfile, magic_error(magic));
18774 + } else {
18775 + const char *ctype = NULL;
18776 +
18777 + magic_setflags(magic, magicmode);
18778 +
18779 + switch (data_mode) {
18780 + case SEND_RSRC:
18781 + {
18782 + char *buffer;
18783 + size_t b_len;
18784 +
18785 + b_len = php_stream_copy_to_mem(data_ptr, &buffer, 65536, 0);
18786 + ctype = magic_buffer(magic, buffer, b_len);
18787 + efree(buffer);
18788 + break;
18789 + }
18790 +
18791 + case SEND_DATA:
18792 + ctype = magic_buffer(magic, data_ptr, data_len);
18793 + break;
18794 +
18795 + default:
18796 + HTTP_CHECK_OPEN_BASEDIR(data_ptr, magic_close(magic); return NULL);
18797 + ctype = magic_file(magic, data_ptr);
18798 + break;
18799 + }
18800 +
18801 + if (ctype) {
18802 + ct = estrdup(ctype);
18803 + } else {
18804 + http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to guess Content-Type: %s", magic_error(magic));
18805 + }
18806 + }
18807 + if (magic) {
18808 + magic_close(magic);
18809 + }
18810 +#else
18811 + http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
18812 +#endif
18813 +
18814 + return ct;
18815 +}
18816 +/* }}} */
18817 +
18818 +/*
18819 + * Local variables:
18820 + * tab-width: 4
18821 + * c-basic-offset: 4
18822 + * End:
18823 + * vim600: sw=4 ts=4 fdm=marker
18824 + * vim<600: sw=4 ts=4
18825 + */
18826 +
18827 --- /dev/null
18828 +++ b/ext/http/http_url_api.c
18829 @@ -0,0 +1,482 @@
18830 +/*
18831 + +--------------------------------------------------------------------+
18832 + | PECL :: http |
18833 + +--------------------------------------------------------------------+
18834 + | Redistribution and use in source and binary forms, with or without |
18835 + | modification, are permitted provided that the conditions mentioned |
18836 + | in the accompanying LICENSE file are met. |
18837 + +--------------------------------------------------------------------+
18838 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
18839 + +--------------------------------------------------------------------+
18840 +*/
18841 +
18842 +/* $Id: http_url_api.c 292841 2009-12-31 08:48:57Z mike $ */
18843 +
18844 +#define HTTP_WANT_SAPI
18845 +#define HTTP_WANT_NETDB
18846 +#include "php_http.h"
18847 +
18848 +#include "zend_ini.h"
18849 +#include "php_output.h"
18850 +#include "ext/standard/php_string.h"
18851 +
18852 +#include "php_http_api.h"
18853 +#include "php_http_querystring_api.h"
18854 +#include "php_http_url_api.h"
18855 +
18856 +static inline char *localhostname(void)
18857 +{
18858 + char hostname[1024] = {0};
18859 +
18860 +#ifdef PHP_WIN32
18861 + if (SUCCESS == gethostname(hostname, lenof(hostname))) {
18862 + return estrdup(hostname);
18863 + }
18864 +#elif defined(HAVE_GETHOSTNAME)
18865 + if (SUCCESS == gethostname(hostname, lenof(hostname))) {
18866 +# if defined(HAVE_GETDOMAINNAME)
18867 + size_t hlen = strlen(hostname);
18868 + if (hlen <= lenof(hostname) - lenof("(none)")) {
18869 + hostname[hlen++] = '.';
18870 + if (SUCCESS == getdomainname(&hostname[hlen], lenof(hostname) - hlen)) {
18871 + if (!strcmp(&hostname[hlen], "(none)")) {
18872 + hostname[hlen - 1] = '\0';
18873 + }
18874 + return estrdup(hostname);
18875 + }
18876 + }
18877 +# endif
18878 + if (strcmp(hostname, "(none)")) {
18879 + return estrdup(hostname);
18880 + }
18881 + }
18882 +#endif
18883 + return estrndup("localhost", lenof("localhost"));
18884 +}
18885 +
18886 +PHP_MINIT_FUNCTION(http_url)
18887 +{
18888 + HTTP_LONG_CONSTANT("HTTP_URL_REPLACE", HTTP_URL_REPLACE);
18889 + HTTP_LONG_CONSTANT("HTTP_URL_JOIN_PATH", HTTP_URL_JOIN_PATH);
18890 + HTTP_LONG_CONSTANT("HTTP_URL_JOIN_QUERY", HTTP_URL_JOIN_QUERY);
18891 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_USER", HTTP_URL_STRIP_USER);
18892 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PASS", HTTP_URL_STRIP_PASS);
18893 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_AUTH", HTTP_URL_STRIP_AUTH);
18894 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PORT", HTTP_URL_STRIP_PORT);
18895 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PATH", HTTP_URL_STRIP_PATH);
18896 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_QUERY", HTTP_URL_STRIP_QUERY);
18897 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_FRAGMENT", HTTP_URL_STRIP_FRAGMENT);
18898 + HTTP_LONG_CONSTANT("HTTP_URL_STRIP_ALL", HTTP_URL_STRIP_ALL);
18899 + HTTP_LONG_CONSTANT("HTTP_URL_FROM_ENV", HTTP_URL_FROM_ENV);
18900 + return SUCCESS;
18901 +}
18902 +
18903 +PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC)
18904 +{
18905 + char *abs = NULL;
18906 + php_url *purl = NULL;
18907 +
18908 + if (url) {
18909 + purl = php_url_parse(abs = estrdup(url));
18910 + STR_SET(abs, NULL);
18911 + if (!purl) {
18912 + http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", url);
18913 + return NULL;
18914 + }
18915 + }
18916 +
18917 + http_build_url(flags, purl, NULL, NULL, &abs, NULL);
18918 +
18919 + if (purl) {
18920 + php_url_free(purl);
18921 + }
18922 +
18923 + return abs;
18924 +}
18925 +
18926 +/* {{{ void http_build_url(int flags, const php_url *, const php_url *, php_url **, char **, size_t *) */
18927 +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)
18928 +{
18929 +#if defined(HAVE_GETSERVBYPORT) || defined(HAVE_GETSERVBYNAME)
18930 + struct servent *se;
18931 +#endif
18932 + php_url *url = ecalloc(1, sizeof(php_url));
18933 +
18934 +#define __URLSET(u,n) \
18935 + ((u)&&(u)->n)
18936 +#define __URLCPY(n) \
18937 + url->n = __URLSET(new_url,n) ? estrdup(new_url->n) : (__URLSET(old_url,n) ? estrdup(old_url->n) : NULL)
18938 +
18939 + if (!(flags & HTTP_URL_STRIP_PORT)) {
18940 + url->port = __URLSET(new_url, port) ? new_url->port : ((old_url) ? old_url->port : 0);
18941 + }
18942 + if (!(flags & HTTP_URL_STRIP_USER)) {
18943 + __URLCPY(user);
18944 + }
18945 + if (!(flags & HTTP_URL_STRIP_PASS)) {
18946 + __URLCPY(pass);
18947 + }
18948 +
18949 + __URLCPY(scheme);
18950 + __URLCPY(host);
18951 +
18952 + if (!(flags & HTTP_URL_STRIP_PATH)) {
18953 + if ((flags & HTTP_URL_JOIN_PATH) && __URLSET(old_url, path) && __URLSET(new_url, path) && *new_url->path != '/') {
18954 + size_t old_path_len = strlen(old_url->path), new_path_len = strlen(new_url->path);
18955 +
18956 + url->path = ecalloc(1, old_path_len + new_path_len + 1 + 1);
18957 +
18958 + strcat(url->path, old_url->path);
18959 + if (url->path[old_path_len - 1] != '/') {
18960 + php_dirname(url->path, old_path_len);
18961 + strcat(url->path, "/");
18962 + }
18963 + strcat(url->path, new_url->path);
18964 + } else {
18965 + __URLCPY(path);
18966 + }
18967 + }
18968 + if (!(flags & HTTP_URL_STRIP_QUERY)) {
18969 + if ((flags & HTTP_URL_JOIN_QUERY) && __URLSET(new_url, query) && __URLSET(old_url, query)) {
18970 + zval qarr, qstr;
18971 +
18972 + INIT_PZVAL(&qstr);
18973 + INIT_PZVAL(&qarr);
18974 + array_init(&qarr);
18975 +
18976 + ZVAL_STRING(&qstr, old_url->query, 0);
18977 + http_querystring_modify(&qarr, &qstr);
18978 + ZVAL_STRING(&qstr, new_url->query, 0);
18979 + http_querystring_modify(&qarr, &qstr);
18980 +
18981 + ZVAL_NULL(&qstr);
18982 + http_querystring_update(&qarr, &qstr);
18983 + url->query = Z_STRVAL(qstr);
18984 + zval_dtor(&qarr);
18985 + } else {
18986 + __URLCPY(query);
18987 + }
18988 + }
18989 + if (!(flags & HTTP_URL_STRIP_FRAGMENT)) {
18990 + __URLCPY(fragment);
18991 + }
18992 +
18993 + if (!url->scheme) {
18994 + if (flags & HTTP_URL_FROM_ENV) {
18995 + zval *https = http_get_server_var("HTTPS", 1);
18996 + if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) {
18997 + url->scheme = estrndup("https", lenof("https"));
18998 + } else switch (url->port) {
18999 + case 443:
19000 + url->scheme = estrndup("https", lenof("https"));
19001 + break;
19002 +
19003 +#ifndef HAVE_GETSERVBYPORT
19004 + default:
19005 +#endif
19006 + case 80:
19007 + case 0:
19008 + url->scheme = estrndup("http", lenof("http"));
19009 + break;
19010 +
19011 +#ifdef HAVE_GETSERVBYPORT
19012 + default:
19013 + if ((se = getservbyport(htons(url->port), "tcp")) && se->s_name) {
19014 + url->scheme = estrdup(se->s_name);
19015 + } else {
19016 + url->scheme = estrndup("http", lenof("http"));
19017 + }
19018 + break;
19019 +#endif
19020 + }
19021 + } else {
19022 + url->scheme = estrndup("http", lenof("http"));
19023 + }
19024 + }
19025 +
19026 + if (!url->host) {
19027 + if (flags & HTTP_URL_FROM_ENV) {
19028 + zval *zhost;
19029 +
19030 + if ((((zhost = http_get_server_var("HTTP_HOST", 1)) ||
19031 + (zhost = http_get_server_var("SERVER_NAME", 1)))) && Z_STRLEN_P(zhost)) {
19032 + url->host = estrndup(Z_STRVAL_P(zhost), Z_STRLEN_P(zhost));
19033 + } else {
19034 + url->host = localhostname();
19035 + }
19036 + } else {
19037 + url->host = estrndup("localhost", lenof("localhost"));
19038 + }
19039 + }
19040 +
19041 + if (!url->path) {
19042 + if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) {
19043 + const char *q = strchr(SG(request_info).request_uri, '?');
19044 +
19045 + if (q) {
19046 + url->path = estrndup(SG(request_info).request_uri, q - SG(request_info).request_uri);
19047 + } else {
19048 + url->path = estrdup(SG(request_info).request_uri);
19049 + }
19050 + } else {
19051 + url->path = estrndup("/", 1);
19052 + }
19053 + } else if (url->path[0] != '/') {
19054 + if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) {
19055 + size_t ulen = strlen(SG(request_info).request_uri);
19056 + size_t plen = strlen(url->path);
19057 + char *path;
19058 +
19059 + if (SG(request_info).request_uri[ulen-1] != '/') {
19060 + for (--ulen; ulen && SG(request_info).request_uri[ulen - 1] != '/'; --ulen);
19061 + }
19062 +
19063 + path = emalloc(ulen + plen + 1);
19064 + memcpy(path, SG(request_info).request_uri, ulen);
19065 + memcpy(path + ulen, url->path, plen);
19066 + path[ulen + plen] = '\0';
19067 + STR_SET(url->path, path);
19068 + } else {
19069 + size_t plen = strlen(url->path);
19070 + char *path = emalloc(plen + 1 + 1);
19071 +
19072 + path[0] = '/';
19073 + memcpy(&path[1], url->path, plen + 1);
19074 + STR_SET(url->path, path);
19075 + }
19076 + }
19077 + /* replace directory references if path is not a single slash */
19078 + if (url->path[0] && (url->path[0] != '/' || url->path[1])) {
19079 + char *ptr, *end = url->path + strlen(url->path) + 1;
19080 +
19081 + for (ptr = strstr(url->path, "/."); ptr; ptr = strstr(ptr, "/.")) {
19082 + switch (ptr[2]) {
19083 + case '\0':
19084 + ptr[1] = '\0';
19085 + break;
19086 +
19087 + case '/':
19088 + memmove(&ptr[1], &ptr[3], end - &ptr[3]);
19089 + break;
19090 +
19091 + case '.':
19092 + if (ptr[3] == '/') {
19093 + char *pos = &ptr[4];
19094 + while (ptr != url->path) {
19095 + if (*--ptr == '/') {
19096 + break;
19097 + }
19098 + }
19099 + memmove(&ptr[1], pos, end - pos);
19100 + break;
19101 + } else if (!ptr[3]) {
19102 + /* .. at the end */
19103 + ptr[1] = '\0';
19104 + }
19105 + /* fallthrough */
19106 +
19107 + default:
19108 + /* something else */
19109 + ++ptr;
19110 + break;
19111 + }
19112 + }
19113 + }
19114 +
19115 + if (url->port) {
19116 + if ( ((url->port == 80) && !strcmp(url->scheme, "http"))
19117 + || ((url->port ==443) && !strcmp(url->scheme, "https"))
19118 +#ifdef HAVE_GETSERVBYNAME
19119 + || ((se = getservbyname(url->scheme, "tcp")) && se->s_port &&
19120 + (url->port == ntohs(se->s_port)))
19121 +#endif
19122 + ) {
19123 + url->port = 0;
19124 + }
19125 + }
19126 +
19127 + if (url_str) {
19128 + size_t len;
19129 +
19130 + *url_str = emalloc(HTTP_URL_MAXLEN + 1);
19131 +
19132 + **url_str = '\0';
19133 + strlcat(*url_str, url->scheme, HTTP_URL_MAXLEN);
19134 + strlcat(*url_str, "://", HTTP_URL_MAXLEN);
19135 +
19136 + if (url->user && *url->user) {
19137 + strlcat(*url_str, url->user, HTTP_URL_MAXLEN);
19138 + if (url->pass && *url->pass) {
19139 + strlcat(*url_str, ":", HTTP_URL_MAXLEN);
19140 + strlcat(*url_str, url->pass, HTTP_URL_MAXLEN);
19141 + }
19142 + strlcat(*url_str, "@", HTTP_URL_MAXLEN);
19143 + }
19144 +
19145 + strlcat(*url_str, url->host, HTTP_URL_MAXLEN);
19146 +
19147 + if (url->port) {
19148 + char port_str[8];
19149 +
19150 + snprintf(port_str, sizeof(port_str), "%d", (int) url->port);
19151 + strlcat(*url_str, ":", HTTP_URL_MAXLEN);
19152 + strlcat(*url_str, port_str, HTTP_URL_MAXLEN);
19153 + }
19154 +
19155 + strlcat(*url_str, url->path, HTTP_URL_MAXLEN);
19156 +
19157 + if (url->query && *url->query) {
19158 + strlcat(*url_str, "?", HTTP_URL_MAXLEN);
19159 + strlcat(*url_str, url->query, HTTP_URL_MAXLEN);
19160 + }
19161 +
19162 + if (url->fragment && *url->fragment) {
19163 + strlcat(*url_str, "#", HTTP_URL_MAXLEN);
19164 + strlcat(*url_str, url->fragment, HTTP_URL_MAXLEN);
19165 + }
19166 +
19167 + if (HTTP_URL_MAXLEN == (len = strlen(*url_str))) {
19168 + http_error(HE_NOTICE, HTTP_E_URL, "Length of URL exceeds HTTP_URL_MAXLEN");
19169 + }
19170 + if (url_len) {
19171 + *url_len = len;
19172 + }
19173 + }
19174 +
19175 + if (url_ptr) {
19176 + *url_ptr = url;
19177 + } else {
19178 + php_url_free(url);
19179 + }
19180 +}
19181 +/* }}} */
19182 +
19183 +/* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
19184 +PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep,
19185 + char *pre_encoded_data, size_t pre_encoded_len,
19186 + char **encoded_data, size_t *encoded_len TSRMLS_DC)
19187 +{
19188 + char *arg_sep;
19189 + size_t arg_sep_len;
19190 + phpstr *qstr = phpstr_new();
19191 +
19192 + if (override_argsep || !(arg_sep_len = strlen(arg_sep = INI_STR("arg_separator.output")))) {
19193 + arg_sep = HTTP_URL_ARGSEP;
19194 + arg_sep_len = lenof(HTTP_URL_ARGSEP);
19195 + }
19196 +
19197 + if (pre_encoded_len && pre_encoded_data) {
19198 + phpstr_append(qstr, pre_encoded_data, pre_encoded_len);
19199 + }
19200 +
19201 + if (SUCCESS != http_urlencode_hash_recursive(hash, qstr, arg_sep, arg_sep_len, NULL, 0)) {
19202 + phpstr_free(&qstr);
19203 + return FAILURE;
19204 + }
19205 +
19206 + phpstr_data(qstr, encoded_data, encoded_len);
19207 + phpstr_free(&qstr);
19208 +
19209 + return SUCCESS;
19210 +}
19211 +/* }}} */
19212 +
19213 +/* {{{ http_urlencode_hash_recursive */
19214 +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)
19215 +{
19216 + HashKey key = initHashKey(0);
19217 + zval **data = NULL;
19218 + HashPosition pos;
19219 +
19220 + if (!ht || !str) {
19221 + http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters");
19222 + return FAILURE;
19223 + }
19224 + if (ht->nApplyCount > 0) {
19225 + return SUCCESS;
19226 + }
19227 +
19228 + FOREACH_HASH_KEYVAL(pos, ht, key, data) {
19229 + char *encoded_key;
19230 + int encoded_len;
19231 + phpstr new_prefix;
19232 +
19233 + if (!data || !*data) {
19234 + phpstr_dtor(str);
19235 + return FAILURE;
19236 + }
19237 +
19238 + if (key.type == HASH_KEY_IS_STRING) {
19239 + if (!*key.str) {
19240 + /* only public properties */
19241 + continue;
19242 + }
19243 + if (key.len && key.str[key.len - 1] == '\0') {
19244 + --key.len;
19245 + }
19246 + encoded_key = php_url_encode(key.str, key.len, &encoded_len);
19247 + } else {
19248 + encoded_len = spprintf(&encoded_key, 0, "%ld", key.num);
19249 + }
19250 +
19251 + {
19252 + phpstr_init(&new_prefix);
19253 + if (prefix && prefix_len) {
19254 + phpstr_append(&new_prefix, prefix, prefix_len);
19255 + phpstr_appends(&new_prefix, "%5B");
19256 + }
19257 +
19258 + phpstr_append(&new_prefix, encoded_key, encoded_len);
19259 + efree(encoded_key);
19260 +
19261 + if (prefix && prefix_len) {
19262 + phpstr_appends(&new_prefix, "%5D");
19263 + }
19264 + phpstr_fix(&new_prefix);
19265 + }
19266 +
19267 + if (Z_TYPE_PP(data) == IS_ARRAY || Z_TYPE_PP(data) == IS_OBJECT) {
19268 + STATUS status;
19269 + ++ht->nApplyCount;
19270 + status = http_urlencode_hash_recursive(HASH_OF(*data), str, arg_sep, arg_sep_len, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
19271 + --ht->nApplyCount;
19272 + if (SUCCESS != status) {
19273 + phpstr_dtor(&new_prefix);
19274 + phpstr_dtor(str);
19275 + return FAILURE;
19276 + }
19277 + } else {
19278 + zval *val = http_zsep(IS_STRING, *data);
19279 +
19280 + if (PHPSTR_LEN(str)) {
19281 + phpstr_append(str, arg_sep, arg_sep_len);
19282 + }
19283 + phpstr_append(str, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
19284 + phpstr_appends(str, "=");
19285 +
19286 + if (Z_STRLEN_P(val) && Z_STRVAL_P(val)) {
19287 + char *encoded_val;
19288 + int encoded_len;
19289 +
19290 + encoded_val = php_url_encode(Z_STRVAL_P(val), Z_STRLEN_P(val), &encoded_len);
19291 + phpstr_append(str, encoded_val, encoded_len);
19292 + efree(encoded_val);
19293 + }
19294 +
19295 + zval_ptr_dtor(&val);
19296 + }
19297 + phpstr_dtor(&new_prefix);
19298 + }
19299 + return SUCCESS;
19300 +}
19301 +/* }}} */
19302 +
19303 +/*
19304 + * Local variables:
19305 + * tab-width: 4
19306 + * c-basic-offset: 4
19307 + * End:
19308 + * vim600: noet sw=4 ts=4 fdm=marker
19309 + * vim<600: noet sw=4 ts=4
19310 + */
19311 +
19312 --- /dev/null
19313 +++ b/ext/http/http_util_object.c
19314 @@ -0,0 +1,158 @@
19315 +/*
19316 + +--------------------------------------------------------------------+
19317 + | PECL :: http |
19318 + +--------------------------------------------------------------------+
19319 + | Redistribution and use in source and binary forms, with or without |
19320 + | modification, are permitted provided that the conditions mentioned |
19321 + | in the accompanying LICENSE file are met. |
19322 + +--------------------------------------------------------------------+
19323 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
19324 + +--------------------------------------------------------------------+
19325 +*/
19326 +
19327 +/* $Id: http_util_object.c 292841 2009-12-31 08:48:57Z mike $ */
19328 +
19329 +#include "php_http.h"
19330 +
19331 +#ifdef ZEND_ENGINE_2
19332 +
19333 +#include "ext/standard/php_http.h"
19334 +
19335 +#include "php_http_util_object.h"
19336 +
19337 +#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpUtil, method, 0, req_args)
19338 +#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpUtil, method, 0)
19339 +
19340 +#define HTTP_UTIL_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpUtil, method))
19341 +
19342 +HTTP_BEGIN_ARGS(date, 0)
19343 + HTTP_ARG_VAL(timestamp, 0)
19344 +HTTP_END_ARGS;
19345 +
19346 +HTTP_BEGIN_ARGS(buildStr, 1)
19347 + HTTP_ARG_VAL(query, 0)
19348 + HTTP_ARG_VAL(prefix, 0)
19349 + HTTP_ARG_VAL(arg_sep, 0)
19350 +HTTP_END_ARGS;
19351 +
19352 +HTTP_BEGIN_ARGS(buildUrl, 1)
19353 + HTTP_ARG_VAL(url, 0)
19354 + HTTP_ARG_VAL(parts, 0)
19355 + HTTP_ARG_VAL(flags, 0)
19356 + HTTP_ARG_VAL(composed, 1)
19357 +HTTP_END_ARGS;
19358 +
19359 +HTTP_BEGIN_ARGS(negotiateLanguage, 1)
19360 + HTTP_ARG_VAL(supported, 0)
19361 + HTTP_ARG_VAL(result, 1)
19362 +HTTP_END_ARGS;
19363 +
19364 +HTTP_BEGIN_ARGS(negotiateCharset, 1)
19365 + HTTP_ARG_VAL(supported, 0)
19366 + HTTP_ARG_VAL(result, 1)
19367 +HTTP_END_ARGS;
19368 +
19369 +HTTP_BEGIN_ARGS(negotiateContentType, 1)
19370 + HTTP_ARG_VAL(supported, 0)
19371 + HTTP_ARG_VAL(result, 1)
19372 +HTTP_END_ARGS;
19373 +
19374 +HTTP_BEGIN_ARGS(matchModified, 1)
19375 + HTTP_ARG_VAL(last_modified, 0)
19376 + HTTP_ARG_VAL(for_range, 0)
19377 +HTTP_END_ARGS;
19378 +
19379 +HTTP_BEGIN_ARGS(matchEtag, 1)
19380 + HTTP_ARG_VAL(plain_etag, 0)
19381 + HTTP_ARG_VAL(for_range, 0)
19382 +HTTP_END_ARGS;
19383 +
19384 +HTTP_BEGIN_ARGS(matchRequestHeader, 2)
19385 + HTTP_ARG_VAL(header_name, 0)
19386 + HTTP_ARG_VAL(header_value, 0)
19387 + HTTP_ARG_VAL(case_sensitive, 0)
19388 +HTTP_END_ARGS;
19389 +
19390 +HTTP_BEGIN_ARGS(parseMessage, 1)
19391 + HTTP_ARG_VAL(message_string, 0)
19392 +HTTP_END_ARGS;
19393 +
19394 +HTTP_BEGIN_ARGS(parseHeaders, 1)
19395 + HTTP_ARG_VAL(headers_string, 0)
19396 +HTTP_END_ARGS;
19397 +
19398 +HTTP_BEGIN_ARGS(parseCookie, 1)
19399 + HTTP_ARG_VAL(cookie_string, 0)
19400 +HTTP_END_ARGS;
19401 +
19402 +HTTP_BEGIN_ARGS(buildCookie, 1)
19403 + HTTP_ARG_VAL(cookie_array, 0)
19404 +HTTP_END_ARGS;
19405 +
19406 +HTTP_BEGIN_ARGS(parseParams, 1)
19407 + HTTP_ARG_VAL(param_string, 0)
19408 + HTTP_ARG_VAL(flags, 0)
19409 +HTTP_END_ARGS;
19410 +
19411 +HTTP_BEGIN_ARGS(chunkedDecode, 1)
19412 + HTTP_ARG_VAL(encoded_string, 0)
19413 +HTTP_END_ARGS;
19414 +
19415 +#ifdef HTTP_HAVE_ZLIB
19416 +HTTP_BEGIN_ARGS(deflate, 1)
19417 + HTTP_ARG_VAL(plain, 0)
19418 + HTTP_ARG_VAL(flags, 0)
19419 +HTTP_END_ARGS;
19420 +
19421 +HTTP_BEGIN_ARGS(inflate, 1)
19422 + HTTP_ARG_VAL(encoded, 0)
19423 +HTTP_END_ARGS;
19424 +#endif
19425 +
19426 +HTTP_BEGIN_ARGS(support, 0)
19427 + HTTP_ARG_VAL(feature, 0)
19428 +HTTP_END_ARGS;
19429 +
19430 +zend_class_entry *http_util_object_ce;
19431 +zend_function_entry http_util_object_fe[] = {
19432 + HTTP_UTIL_ALIAS(date, http_date)
19433 + HTTP_UTIL_ALIAS(buildUrl, http_build_url)
19434 + HTTP_UTIL_ALIAS(buildStr, http_build_str)
19435 + HTTP_UTIL_ALIAS(negotiateLanguage, http_negotiate_language)
19436 + HTTP_UTIL_ALIAS(negotiateCharset, http_negotiate_charset)
19437 + HTTP_UTIL_ALIAS(negotiateContentType, http_negotiate_content_type)
19438 + HTTP_UTIL_ALIAS(matchModified, http_match_modified)
19439 + HTTP_UTIL_ALIAS(matchEtag, http_match_etag)
19440 + HTTP_UTIL_ALIAS(matchRequestHeader, http_match_request_header)
19441 + HTTP_UTIL_ALIAS(parseMessage, http_parse_message)
19442 + HTTP_UTIL_ALIAS(parseHeaders, http_parse_headers)
19443 + HTTP_UTIL_ALIAS(parseCookie, http_parse_cookie)
19444 + HTTP_UTIL_ALIAS(buildCookie, http_build_cookie)
19445 + HTTP_UTIL_ALIAS(parseParams, http_parse_params)
19446 + HTTP_UTIL_ALIAS(chunkedDecode, http_chunked_decode)
19447 +#ifdef HTTP_HAVE_ZLIB
19448 + HTTP_UTIL_ALIAS(deflate, http_deflate)
19449 + HTTP_UTIL_ALIAS(inflate, http_inflate)
19450 +#endif /* HTTP_HAVE_ZLIB */
19451 + HTTP_UTIL_ALIAS(support, http_support)
19452 +
19453 + EMPTY_FUNCTION_ENTRY
19454 +};
19455 +
19456 +PHP_MINIT_FUNCTION(http_util_object)
19457 +{
19458 + HTTP_REGISTER_CLASS(HttpUtil, http_util_object, NULL, 0);
19459 + return SUCCESS;
19460 +}
19461 +
19462 +#endif /* ZEND_ENGINE_2 */
19463 +
19464 +/*
19465 + * Local variables:
19466 + * tab-width: 4
19467 + * c-basic-offset: 4
19468 + * End:
19469 + * vim600: noet sw=4 ts=4 fdm=marker
19470 + * vim<600: noet sw=4 ts=4
19471 + */
19472 +
19473 --- /dev/null
19474 +++ b/ext/http/lib/BigGet.php
19475 @@ -0,0 +1,213 @@
19476 +<?php
19477 +
19478 +/**
19479 + * BigGet - download big files efficiently
19480 + * $Id: BigGet.php 220502 2006-09-25 08:27:32Z mike $
19481 + *
19482 + * @copyright Michael Wallner, <mike@iworks.at>
19483 + * @license BSD, revised
19484 + * @version $Revision: 220502 $
19485 + */
19486 +class BigGet extends HttpRequestPool
19487 +{
19488 + /**
19489 + * File split size
19490 + */
19491 + const SIZE = 1048576;
19492 +
19493 + /**
19494 + * Parallel Request count
19495 + */
19496 + const RMAX = 5;
19497 +
19498 + /**
19499 + * Whether to output debug messages
19500 + *
19501 + * @var bool
19502 + */
19503 + public $dbg = false;
19504 +
19505 + /**
19506 + * URL
19507 + *
19508 + * @var string
19509 + */
19510 + private $url;
19511 +
19512 + /**
19513 + * Temp file prefix
19514 + *
19515 + * @var string
19516 + */
19517 + private $tmp;
19518 +
19519 + /**
19520 + * Size of requested resource
19521 + *
19522 + * @var int
19523 + */
19524 + private $size;
19525 +
19526 + /**
19527 + * Whether the requests have been sent
19528 + *
19529 + * @var bool
19530 + */
19531 + private $sent = false;
19532 +
19533 + /**
19534 + * Request counter
19535 + *
19536 + * @var int
19537 + */
19538 + private $count = 0;
19539 +
19540 + /**
19541 + * Static constructor
19542 + *
19543 + * @param string $url
19544 + * @param string $tmp
19545 + * @return BigGet
19546 + * @throws Exception
19547 + */
19548 + public static function url($url, $tmp = '/tmp')
19549 + {
19550 + $head = new HttpRequest($url, HttpRequest::METH_HEAD);
19551 + $headers = $head->send()->getHeaders();
19552 +
19553 + if (200 != $head->getResponseCode()) {
19554 + throw new HttpException("Did not receive '200 Ok' from HEAD $url");
19555 + }
19556 + if (!isset($headers['Accept-Ranges'])) {
19557 + throw new HttpException("Did not receive an Accept-Ranges header from HEAD $url");
19558 + }
19559 + if (!isset($headers['Content-Length'])) {
19560 + throw new HttpException("Did not receive a Content-Length header from HEAD $url");
19561 + }
19562 +
19563 + $bigget = new BigGet;
19564 + $bigget->url = $url;
19565 + $bigget->tmp = tempnam($tmp, 'BigGet.');
19566 + $bigget->size = $headers['Content-Length'];
19567 + return $bigget;
19568 + }
19569 +
19570 + /**
19571 + * Save the resource to a file
19572 + *
19573 + * @param string $file
19574 + * @return bool
19575 + * @throws Exception
19576 + */
19577 + public function saveTo($file)
19578 + {
19579 + $this->sent or $this->send();
19580 +
19581 + if ($w = fopen($this->tmp, 'wb')) {
19582 +
19583 + $this->dbg && print "\nCopying temp files to $file ...\n";
19584 +
19585 + foreach (glob($this->tmp .".????") as $tmp) {
19586 +
19587 + $this->dbg && print "\t$tmp\n";
19588 +
19589 + if ($r = fopen($tmp, 'rb')) {
19590 + stream_copy_to_stream($r, $w);
19591 + fclose($r);
19592 + }
19593 + unlink($tmp);
19594 + }
19595 + fclose($w);
19596 + rename($this->tmp, $file);
19597 +
19598 + $this->dbg && print "\nDone.\n";
19599 +
19600 + return true;
19601 + }
19602 + return false;
19603 + }
19604 +
19605 + /**
19606 + * Overrides HttpRequestPool::send()
19607 + *
19608 + * @return void
19609 + * @throws Exception
19610 + */
19611 + public function send()
19612 + {
19613 + $this->sent = true;
19614 +
19615 + // use max RMAX simultanous requests with a req size of SIZE
19616 + while ($this->count < self::RMAX && -1 != $offset = $this->getRangeOffset()) {
19617 + $this->attachNew($offset);
19618 + }
19619 +
19620 + while ($this->socketPerform()) {
19621 + if (!$this->socketSelect()) {
19622 + throw new HttpSocketException;
19623 + }
19624 + }
19625 + }
19626 +
19627 + /**
19628 + * Overrides HttpRequestPool::socketPerform()
19629 + *
19630 + * @return bool
19631 + */
19632 + protected function socketPerform()
19633 + {
19634 + $rs = parent::socketPerform();
19635 +
19636 + foreach ($this->getFinishedRequests() as $r) {
19637 + $this->detach($r);
19638 +
19639 + if (206 != $rc = $r->getResponseCode()) {
19640 + throw new HttpException("Unexpected response code: $rc");
19641 + }
19642 +
19643 + file_put_contents(sprintf("%s.%04d", $this->tmp, $r->id), $r->getResponseBody());
19644 +
19645 + if (-1 != $offset = $this->getRangeOffset()) {
19646 + $this->attachNew($offset);
19647 + }
19648 + }
19649 +
19650 + return $rs;
19651 + }
19652 +
19653 + private function attachNew($offset)
19654 + {
19655 + $stop = min($this->count * self::SIZE + self::SIZE, $this->size) - 1;
19656 +
19657 + $this->dbg && print "Attaching new request to get range: $offset-$stop\n";
19658 +
19659 + $req = new BigGetRequest(
19660 + $this->url,
19661 + HttpRequest::METH_GET,
19662 + array(
19663 + 'headers' => array(
19664 + 'Range' => "bytes=$offset-$stop"
19665 + )
19666 + )
19667 + );
19668 + $this->attach($req);
19669 + $req->id = $this->count++;
19670 + }
19671 +
19672 + private function getRangeOffset()
19673 + {
19674 + return ($this->size >= $start = $this->count * self::SIZE) ? $start : -1;
19675 + }
19676 +}
19677 +
19678 +
19679 +/**
19680 + * BigGet request
19681 + * @ignore
19682 + */
19683 +class BigGetRequest extends HttpRequest
19684 +{
19685 + public $id;
19686 +}
19687 +
19688 +?>
19689 --- /dev/null
19690 +++ b/ext/http/lib/FeedAggregator.php
19691 @@ -0,0 +1,187 @@
19692 +<?php
19693 +
19694 +/**
19695 + * Simple Feed Aggregator
19696 + * $Id: FeedAggregator.php 208774 2006-03-06 16:07:19Z mike $
19697 + *
19698 + * @copyright Michael Wallner, <mike@iworks.at>
19699 + * @license BSD, revised
19700 + * @package pecl/http
19701 + * @version $Revision: 208774 $
19702 + */
19703 +class FeedAggregator
19704 +{
19705 + /**
19706 + * Cache directory
19707 + *
19708 + * @var string
19709 + */
19710 + public $directory;
19711 +
19712 + /**
19713 + * Feeds
19714 + *
19715 + * @var array
19716 + */
19717 + protected $feeds = array();
19718 +
19719 + /**
19720 + * Constructor
19721 + *
19722 + * @param string $directory
19723 + */
19724 + public function __construct($directory = 'feeds')
19725 + {
19726 + $this->setDirectory($directory);
19727 + }
19728 +
19729 + /**
19730 + * Set cache directory
19731 + *
19732 + * @param string $directory
19733 + */
19734 + public function setDirectory($directory)
19735 + {
19736 + $this->directory = $directory;
19737 + foreach (glob($this->directory .'/*.xml') as $feed) {
19738 + $this->feeds[basename($feed, '.xml')] = filemtime($feed);
19739 + }
19740 + }
19741 +
19742 + /**
19743 + * Strips all special chars
19744 + *
19745 + * @param string $url
19746 + * @return string
19747 + */
19748 + public function url2name($url)
19749 + {
19750 + return preg_replace('/[^\w\.-]+/', '_', $url);
19751 + }
19752 +
19753 + /**
19754 + * Checks if $url is a known feed
19755 + *
19756 + * @param string $url
19757 + * @return bool
19758 + */
19759 + public function hasFeed($url)
19760 + {
19761 + return isset($this->feeds[$this->url2name($url)]);
19762 + }
19763 +
19764 + /**
19765 + * Add an URL as feed
19766 + *
19767 + * @param string $url
19768 + * @return void
19769 + * @throws Exception
19770 + */
19771 + public function addFeed($url)
19772 + {
19773 + $r = $this->setupRequest($url);
19774 + $r->send();
19775 + $this->handleResponse($r);
19776 + }
19777 +
19778 + /**
19779 + * Add several URLs as feeds
19780 + *
19781 + * @param array $urls
19782 + * @return void
19783 + * @throws Exception
19784 + */
19785 + public function addFeeds(array $urls)
19786 + {
19787 + $pool = new HttpRequestPool;
19788 + foreach ($urls as $url) {
19789 + $pool->attach($r = $this->setupRequest($url));
19790 + }
19791 + $pool->send();
19792 +
19793 + foreach ($pool as $request) {
19794 + $this->handleResponse($request);
19795 + }
19796 + }
19797 +
19798 + /**
19799 + * Load a feed (from cache)
19800 + *
19801 + * @param string $url
19802 + * @return string
19803 + * @throws Exception
19804 + */
19805 + public function getFeed($url)
19806 + {
19807 + $this->addFeed($url);
19808 + return $this->loadFeed($this->url2name($url));
19809 + }
19810 +
19811 + /**
19812 + * Load several feeds (from cache)
19813 + *
19814 + * @param array $urls
19815 + * @return array
19816 + * @throws Exception
19817 + */
19818 + public function getFeeds(array $urls)
19819 + {
19820 + $feeds = array();
19821 + $this->addFeeds($urls);
19822 + foreach ($urls as $url) {
19823 + $feeds[] = $this->loadFeed($this->url2name($url));
19824 + }
19825 + return $feeds;
19826 + }
19827 +
19828 + protected function saveFeed($file, $contents)
19829 + {
19830 + if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) {
19831 + $this->feeds[$file] = time();
19832 + } else {
19833 + throw new Exception("Could not save feed contents to $file.xml");
19834 + }
19835 + }
19836 +
19837 + protected function loadFeed($file)
19838 + {
19839 + if (isset($this->feeds[$file])) {
19840 + if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) {
19841 + return $data;
19842 + } else {
19843 + throw new Exception("Could not load feed contents from $file.xml");
19844 + }
19845 + } else {
19846 + throw new Exception("Unknown feed/file $file.xml");
19847 + }
19848 + }
19849 +
19850 + protected function setupRequest($url, $escape = true)
19851 + {
19852 + $r = new HttpRequest($url);
19853 + $r->setOptions(array('redirect' => true));
19854 +
19855 + $file = $escape ? $this->url2name($url) : $url;
19856 +
19857 + if (isset($this->feeds[$file])) {
19858 + $r->setOptions(array('lastmodified' => $this->feeds[$file]));
19859 + }
19860 +
19861 + return $r;
19862 + }
19863 +
19864 + protected function handleResponse(HttpRequest $r)
19865 + {
19866 + if ($r->getResponseCode() != 304) {
19867 + if ($r->getResponseCode() != 200) {
19868 + throw new Exception("Unexpected response code ". $r->getResponseCode());
19869 + }
19870 + if (!strlen($body = $r->getResponseBody())) {
19871 + throw new Exception("Received empty feed from ". $r->getUrl());
19872 + }
19873 + $this->saveFeed($this->url2name($r->getUrl()), $body);
19874 + }
19875 + }
19876 +}
19877 +
19878 +?>
19879 --- /dev/null
19880 +++ b/ext/http/lib/PgLobStream.php
19881 @@ -0,0 +1,100 @@
19882 +<?php
19883 +
19884 +/**
19885 + * PostgreSQL LOB stream
19886 + * $Id: PgLobStream.php 210232 2006-03-27 17:41:25Z mike $
19887 + *
19888 + * Usage:
19889 + * <code>
19890 + * // GET /image.php?image=1234
19891 + * if (PgLobStream::$loId = (int) $_GET['image']) {
19892 + * if ($lob = fopen('pglob://dbname=database user=mike', 'r')) {
19893 + * HttpResponse::setContentType('image/jpeg');
19894 + * HttpResponse::setStream($lob);
19895 + * HttpResponse::send();
19896 + * }
19897 + * }
19898 + * </code>
19899 + *
19900 + * @copyright Michael Wallner, <mike@iworks.at>
19901 + * @license BSD, revised
19902 + * @package pecl/http
19903 + * @version $Revision: 210232 $
19904 + */
19905 +class PgLobStream
19906 +{
19907 + private $dbh;
19908 + private $loh;
19909 + private $lon;
19910 + private $size = 0;
19911 +
19912 + public static $loId;
19913 +
19914 + function stream_open($path, $mode)
19915 + {
19916 + $path = trim(parse_url($path, PHP_URL_HOST));
19917 +
19918 + if ($path) {
19919 + if ($this->dbh = pg_connect($path)) {
19920 + if (pg_query($this->dbh, 'BEGIN')) {
19921 + if (is_resource($this->loh = pg_lo_open($this->dbh, $this->lon = self::$loId, $mode))) {
19922 + pg_lo_seek($this->loh, 0, PGSQL_SEEK_END);
19923 + $this->size = (int) pg_lo_tell($this->loh);
19924 + pg_lo_seek($this->loh, 0, PGSQL_SEEK_SET);
19925 + return true;
19926 + }
19927 + }
19928 + }
19929 + }
19930 + return false;
19931 + }
19932 +
19933 + function stream_read($length)
19934 + {
19935 + return pg_lo_read($this->loh, $length);
19936 + }
19937 +
19938 + function stream_seek($offset, $whence = PGSQL_SEEK_SET)
19939 + {
19940 + return pg_lo_seek($this->loh, $offset, $whence);
19941 + }
19942 +
19943 + function stream_tell()
19944 + {
19945 + return pg_lo_tell($this->loh);
19946 + }
19947 +
19948 + function stream_eof()
19949 + {
19950 + return pg_lo_tell($this->loh) >= $this->size;
19951 + }
19952 +
19953 + function stream_flush()
19954 + {
19955 + return true;
19956 + }
19957 +
19958 + function stream_stat()
19959 + {
19960 + return array('size' => $this->size, 'ino' => $this->lon);
19961 + }
19962 +
19963 + function stream_write($data)
19964 + {
19965 + return pg_lo_write($this->loh, $data);
19966 + }
19967 +
19968 + function stream_close()
19969 + {
19970 + if (pg_lo_close($this->loh)) {
19971 + return pg_query($this->dbh, 'COMMIT');
19972 + } else {
19973 + pg_query($this->dbh, 'ROLLBACK');
19974 + return false;
19975 + }
19976 + }
19977 +}
19978 +
19979 +stream_register_wrapper('pglob', 'PgLobStream');
19980 +
19981 +?>
19982 --- /dev/null
19983 +++ b/ext/http/lib/XmlRpcClient.php
19984 @@ -0,0 +1,119 @@
19985 +<?php
19986 +
19987 +/**
19988 + * XMLRPC Client, very KISS
19989 + * $Id: XmlRpcClient.php 227268 2007-01-15 08:01:35Z mike $
19990 + *
19991 + * NOTE: requires ext/xmlrpc
19992 + *
19993 + * Usage:
19994 + * <code>
19995 + * <?php
19996 + * $rpc = new XmlRpcClient('http://mike:secret@example.com/cgi-bin/vpop-xmlrpc');
19997 + * $rpc->__request->setOptions(array('compress' => true));
19998 + * try {
19999 + * print_r($rpc->vpop->listdomain(array('domain' => 'example.com')));
20000 + * } catch (Exception $ex) {
20001 + * echo $ex;
20002 + * }
20003 + * ?>
20004 + * </code>
20005 + *
20006 + * @copyright Michael Wallner, <mike@iworks.at>
20007 + * @license BSD, revised
20008 + * @package pecl/http
20009 + * @version $Revision: 227268 $
20010 + */
20011 +class XmlRpcClient
20012 +{
20013 + /**
20014 + * RPC namespace
20015 + *
20016 + * @var string
20017 + */
20018 + public $__namespace;
20019 +
20020 + /**
20021 + * HttpRequest instance
20022 + *
20023 + * @var HttpRequest
20024 + */
20025 + public $__request;
20026 +
20027 + /**
20028 + * Client charset
20029 + *
20030 + * @var string
20031 + */
20032 + public $__encoding = "iso-8859-1";
20033 +
20034 + /**
20035 + * RPC options
20036 + *
20037 + * @var array
20038 + */
20039 + public $__options;
20040 +
20041 + /**
20042 + * Constructor
20043 + *
20044 + * @param string $url RPC endpoint
20045 + * @param string $namespace RPC namespace
20046 + * @param array $options HttpRequest options
20047 + */
20048 + public function __construct($url, $namespace = '', array $options = null)
20049 + {
20050 + $this->__request = new HttpRequest($url, HttpRequest::METH_POST, (array) $options);
20051 + $this->__namespace = $namespace;
20052 + }
20053 +
20054 + /**
20055 + * RPC method proxy
20056 + *
20057 + * @param string $method RPC method name
20058 + * @param array $params RPC method arguments
20059 + * @return mixed decoded RPC response
20060 + * @throws Exception
20061 + */
20062 + public function __call($method, array $params)
20063 + {
20064 + if (strlen($this->__namespace)) {
20065 + $method = $this->__namespace .'.'. $method;
20066 + }
20067 + $this->__request->setContentType("text/xml");
20068 + $this->__request->setRawPostData(
20069 + xmlrpc_encode_request($method, $params,
20070 + array("encoding" => $this->__encoding) + (array) $this->__options));
20071 + $response = $this->__request->send();
20072 + if ($response->getResponseCode() != 200) {
20073 + throw new Exception(
20074 + $response->getResponseStatus(),
20075 + $response->getResponseCode()
20076 + );
20077 + }
20078 +
20079 + $data = xmlrpc_decode($response->getBody(), $this->__encoding);
20080 + if (xmlrpc_is_fault($data)) {
20081 + throw new Exception(
20082 + (string) $data['faultString'],
20083 + (int) $data['faultCode']
20084 + );
20085 + }
20086 +
20087 + return $data;
20088 + }
20089 +
20090 + /**
20091 + * Returns self, where namespace is set to variable name
20092 + *
20093 + * @param string $ns
20094 + * @return XmlRpcRequest
20095 + */
20096 + public function __get($ns)
20097 + {
20098 + $this->__namespace = $ns;
20099 + return $this;
20100 + }
20101 +}
20102 +
20103 +?>
20104 --- /dev/null
20105 +++ b/ext/http/lib/XmlRpcServer.php
20106 @@ -0,0 +1,254 @@
20107 +<?php
20108 +
20109 +XmlRpcServer::setContentType("text/xml");
20110 +XmlRpcServer::capture();
20111 +
20112 +/**
20113 + * XMLRPC Server, very KISS
20114 + * $Id: XmlRpcServer.php 227268 2007-01-15 08:01:35Z mike $
20115 + *
20116 + * NOTE: requires ext/xmlrpc
20117 + *
20118 + * Usage:
20119 + * <code>
20120 + * <?php
20121 + * class Handler extends XmlRpcRequestHandlerStub {
20122 + * public function xmlrpcPing(array $values) {
20123 + * return true;
20124 + * }
20125 + * }
20126 + * try {
20127 + * XmlRpcServer::factory("namespace")->registerHandler(new Handler);
20128 + * XmlRpcServer::run();
20129 + * } catch (Exception $ex) {
20130 + * XmlRpcServer::error($ex->getCode(), $ex->getMessage());
20131 + * }
20132 + * </code>
20133 + *
20134 + * @copyright Michael Wallner, <mike@iworks.at>
20135 + * @license BSD, revised
20136 + * @package pecl/http
20137 + * @version $Revision: 227268 $
20138 + */
20139 +
20140 +class XmlRpcServer extends HttpResponse
20141 +{
20142 + /**
20143 + * Server charset
20144 + *
20145 + * @var string
20146 + */
20147 + public static $encoding = "iso-8859-1";
20148 +
20149 + /**
20150 + * RPC namespace
20151 + *
20152 + * @var string
20153 + */
20154 + public $namespace;
20155 +
20156 + /**
20157 + * RPC handler attached to this server instance
20158 + *
20159 + * @var XmlRpcRequestHandler
20160 + */
20161 + protected $handler;
20162 +
20163 + private static $xmlreq;
20164 + private static $xmlrpc;
20165 + private static $refcnt = 0;
20166 + private static $handle = array();
20167 +
20168 + /**
20169 + * Create a new XmlRpcServer instance
20170 + *
20171 + * @param string $namespace
20172 + * @param string $encoding
20173 + */
20174 + public function __construct($namespace)
20175 + {
20176 + $this->namespace = $namespace;
20177 + self::initialize();
20178 + }
20179 +
20180 + /**
20181 + * Destructor
20182 + */
20183 + public function __destruct()
20184 + {
20185 + if (self::$refcnt && !--self::$refcnt) {
20186 + xmlrpc_server_destroy(self::$xmlrpc);
20187 + }
20188 + }
20189 +
20190 + /**
20191 + * Static factory
20192 + *
20193 + * @param string $namespace
20194 + * @return XmlRpcServer
20195 + */
20196 + public static function factory($namespace)
20197 + {
20198 + return new XmlRpcServer($namespace);
20199 + }
20200 +
20201 + /**
20202 + * Run all servers and send response
20203 + *
20204 + * @param array $options
20205 + */
20206 + public static function run(array $options = null)
20207 + {
20208 + self::initialize(false, true);
20209 + self::setContentType("text/xml; charset=". self::$encoding);
20210 + echo xmlrpc_server_call_method(self::$xmlrpc, self::$xmlreq, null,
20211 + array("encoding" => self::$encoding) + (array) $options);
20212 + }
20213 +
20214 + /**
20215 + * Test hook; call instead of XmlRpcServer::run()
20216 + *
20217 + * @param string $method
20218 + * @param array $params
20219 + * @param array $request_options
20220 + * @param array $response_options
20221 + */
20222 + public static function test($method, array $params, array $request_options = null, array $response_options = null)
20223 + {
20224 + self::$xmlreq = xmlrpc_encode_request($method, $params, $request_options);
20225 + self::run($response_options);
20226 + }
20227 +
20228 + /**
20229 + * Optional XMLRPC error handler
20230 + *
20231 + * @param int $code
20232 + * @param string $msg
20233 + */
20234 + public static function error($code, $msg, array $options = null)
20235 + {
20236 + echo xmlrpc_encode(array("faultCode" => $code, "faultString" => $msg),
20237 + array("encoding" => self::$encoding) + (array) $options);
20238 + }
20239 +
20240 + /**
20241 + * Register a single method
20242 + *
20243 + * @param string $name
20244 + * @param mixed $callback
20245 + * @param mixed $dispatch
20246 + * @param array $spec
20247 + */
20248 + public function registerMethod($name, $callback, $dispatch = null, array $spec = null)
20249 + {
20250 + if (!is_callable($callback, false, $cb_name)) {
20251 + throw new Exception("$cb_name is not a valid callback");
20252 + }
20253 + if (isset($dispatch)) {
20254 + if (!is_callable($dispatch, false, $cb_name)) {
20255 + throw new Exception("$cb_name is not a valid callback");
20256 + }
20257 + xmlrpc_server_register_method(self::$xmlrpc, $name, $dispatch);
20258 + self::$handle[$name] = $callback;
20259 + } else {
20260 + xmlrpc_server_register_method(self::$xmlrpc, $name, $callback);
20261 + }
20262 +
20263 + if (isset($spec)) {
20264 + xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
20265 + }
20266 + }
20267 +
20268 + /**
20269 + * Register an XmlRpcRequestHandler for this server instance
20270 + *
20271 + * @param XmlRpcRequestHandler $handler
20272 + */
20273 + public function registerHandler(XmlRpcRequestHandler $handler)
20274 + {
20275 + $this->handler = $handler;
20276 +
20277 + foreach (get_class_methods($handler) as $method) {
20278 + if (!strncmp($method, "xmlrpc", 6)) {
20279 + $this->registerMethod(
20280 + $this->method($method, $handler->getNamespace()),
20281 + array($handler, $method), array($this, "dispatch"));
20282 + }
20283 + }
20284 +
20285 + $handler->getIntrospectionData($spec);
20286 + if (is_array($spec)) {
20287 + xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec);
20288 + }
20289 + }
20290 +
20291 + private function method($method, $namespace = null)
20292 + {
20293 + if (!strlen($namespace)) {
20294 + $namespace = strlen($this->namespace) ? $this->namespace : "xmlrpc";
20295 + }
20296 + return $namespace .".". strtolower($method[6]) . substr($method, 7);
20297 + }
20298 +
20299 + private function dispatch($method, array $params = null)
20300 + {
20301 + if (array_key_exists($method, self::$handle)) {
20302 + return call_user_func(self::$handle[$method], $params);
20303 + }
20304 + throw new Exception("Unknown XMLRPC method: $method");
20305 + }
20306 +
20307 + private static function initialize($server = true, $data = false)
20308 + {
20309 + if ($data) {
20310 + if (!self::$xmlreq && !(self::$xmlreq = http_get_request_body())) {
20311 + throw new Exception("Failed to fetch XMLRPC request body");
20312 + }
20313 + }
20314 + if ($server) {
20315 + if (!self::$xmlrpc && !(self::$xmlrpc = xmlrpc_server_create())) {
20316 + throw new Exception("Failed to initialize XMLRPC server");
20317 + }
20318 + ++self::$refcnt;
20319 + }
20320 + }
20321 +}
20322 +
20323 +/**
20324 + * XmlRpcRequestHandler
20325 + *
20326 + * Define XMLRPC methods with an "xmlrpc" prefix, eg:
20327 + * <code>
20328 + * class IntOp implements XmlRpcRequestHandler {
20329 + * public function getNamespace() {
20330 + * return "int";
20331 + * }
20332 + * public function getInstrospectionData(array &$spec = null) {
20333 + * }
20334 + * // XMLRPC method name: int.sumValues
20335 + * public function xmlrpcSumValues(array $values) {
20336 + * return array_sum($values);
20337 + * }
20338 + * }
20339 + * </code>
20340 + */
20341 +interface XmlRpcRequestHandler
20342 +{
20343 + public function getNamespace();
20344 + public function getIntrospectionData(array &$spec = null);
20345 +}
20346 +
20347 +/**
20348 + * XmlRpcRequestHandlerStub
20349 + */
20350 +abstract class XmlRpcRequestHandlerStub implements XmlRpcRequestHandler
20351 +{
20352 + public function getNamespace()
20353 + {
20354 + }
20355 + public function getIntrospectionData(array &$spec = null)
20356 + {
20357 + }
20358 +}
20359 +
20360 +?>
20361 --- /dev/null
20362 +++ b/ext/http/missing.c
20363 @@ -0,0 +1,74 @@
20364 +/*
20365 + +--------------------------------------------------------------------+
20366 + | PECL :: http |
20367 + +--------------------------------------------------------------------+
20368 + | Redistribution and use in source and binary forms, with or without |
20369 + | modification, are permitted provided that the conditions mentioned |
20370 + | in the accompanying LICENSE file are met. |
20371 + +--------------------------------------------------------------------+
20372 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20373 + +--------------------------------------------------------------------+
20374 +*/
20375 +
20376 +/* $Id: missing.c 292841 2009-12-31 08:48:57Z mike $ */
20377 +
20378 +#ifdef HAVE_CONFIG_H
20379 +# include "config.h"
20380 +#endif
20381 +
20382 +#include "php.h"
20383 +#include "missing.h"
20384 +
20385 +#ifdef WONKY
20386 +int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC)
20387 +{
20388 + zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS);
20389 + INIT_PZVAL(property);
20390 + ZVAL_DOUBLE(property, value);
20391 + return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
20392 +}
20393 +
20394 +void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC)
20395 +{
20396 + zval *tmp = ecalloc(1, sizeof(zval));
20397 + ZVAL_DOUBLE(tmp, value);
20398 + zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
20399 +}
20400 +
20401 +int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC)
20402 +{
20403 + zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS);
20404 + INIT_PZVAL(property);
20405 + ZVAL_BOOL(property, value);
20406 + return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
20407 +}
20408 +
20409 +void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC)
20410 +{
20411 + zval *tmp = ecalloc(1, sizeof(zval));
20412 + ZVAL_BOOL(tmp, value);
20413 + zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
20414 +}
20415 +
20416 +void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC)
20417 +{
20418 + zval *tmp;
20419 +
20420 + ALLOC_ZVAL(tmp);
20421 + tmp->is_ref = 0;
20422 + tmp->refcount = 0;
20423 + ZVAL_STRINGL(tmp, value, value_len, 1);
20424 + zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
20425 +}
20426 +
20427 +#endif
20428 +
20429 +/*
20430 + * Local variables:
20431 + * tab-width: 4
20432 + * c-basic-offset: 4
20433 + * End:
20434 + * vim600: noet sw=4 ts=4 fdm=marker
20435 + * vim<600: noet sw=4 ts=4
20436 + */
20437 +
20438 --- /dev/null
20439 +++ b/ext/http/missing.h
20440 @@ -0,0 +1,184 @@
20441 +/*
20442 + +--------------------------------------------------------------------+
20443 + | PECL :: http |
20444 + +--------------------------------------------------------------------+
20445 + | Redistribution and use in source and binary forms, with or without |
20446 + | modification, are permitted provided that the conditions mentioned |
20447 + | in the accompanying LICENSE file are met. |
20448 + +--------------------------------------------------------------------+
20449 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20450 + +--------------------------------------------------------------------+
20451 +*/
20452 +
20453 +/* $Id: missing.h 323304 2012-02-17 21:13:24Z mike $ */
20454 +
20455 +#ifndef PHP_HTTP_MISSING
20456 +#define PHP_HTTP_MISSING
20457 +
20458 +#include "php_version.h"
20459 +
20460 +#if ZEND_MODULE_API_NO >= 20100409
20461 +#define ZEND_ENGINE_2_4
20462 +#endif
20463 +
20464 +#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50399)
20465 +# define ZEND_LITERAL_KEY_DC , const zend_literal *_zend_literal_key
20466 +# define ZEND_LITERAL_KEY_CC , _zend_literal_key
20467 +# define ZEND_LITERAL_NIL_CC , NULL
20468 +# define HTTP_CHECK_OPEN_BASEDIR(file, act) \
20469 + if ((PG(open_basedir) && *PG(open_basedir))) \
20470 + { \
20471 + const char *tmp = file; \
20472 + \
20473 + if (!strncasecmp(tmp, "file:", lenof("file:"))) { \
20474 + tmp += lenof("file:"); \
20475 + while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \
20476 + } \
20477 + \
20478 + if ( (tmp != file || !strstr(file, "://")) && \
20479 + (!*tmp || php_check_open_basedir(tmp TSRMLS_CC))) { \
20480 + act; \
20481 + } \
20482 + }
20483 +
20484 +#else
20485 +# define ZEND_LITERAL_KEY_DC
20486 +# define ZEND_LITERAL_KEY_CC
20487 +# define ZEND_LITERAL_NIL_CC
20488 +# define HTTP_CHECK_OPEN_BASEDIR(file, act) \
20489 + if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) \
20490 + { \
20491 + const char *tmp = file; \
20492 + \
20493 + if (!strncasecmp(tmp, "file:", lenof("file:"))) { \
20494 + tmp += lenof("file:"); \
20495 + while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \
20496 + } \
20497 + \
20498 + if ( (tmp != file || !strstr(file, "://")) && \
20499 + (!*tmp || php_check_open_basedir(tmp TSRMLS_CC) || \
20500 + (PG(safe_mode) && !php_checkuid(tmp, "rb+", CHECKUID_CHECK_MODE_PARAM)))) { \
20501 + act; \
20502 + } \
20503 + }
20504 +
20505 +#endif
20506 +
20507 +#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3)
20508 +# define HTTP_ZAPI_HASH_TSRMLS_CC TSRMLS_CC
20509 +# define HTTP_ZAPI_HASH_TSRMLS_DC TSRMLS_DC
20510 +# define HTTP_ZAPI_CONST_CAST(t) (const t)
20511 +# define GLOBAL_ERROR_HANDLING EG(error_handling)
20512 +# define GLOBAL_EXCEPTION_CLASS EG(exception_class)
20513 +# define HTTP_IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp) TSRMLS_CC)
20514 +# define HTTP_STATIC_ARG_INFO
20515 +#else
20516 +# define HTTP_ZAPI_HASH_TSRMLS_CC
20517 +# define HTTP_ZAPI_HASH_TSRMLS_DC
20518 +# define HTTP_ZAPI_CONST_CAST(t) (t)
20519 +# define GLOBAL_ERROR_HANDLING PG(error_handling)
20520 +# define GLOBAL_EXCEPTION_CLASS PG(exception_class)
20521 +# define HTTP_IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp))
20522 +# define HTTP_STATIC_ARG_INFO static
20523 +#endif
20524 +
20525 +#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION == 0)
20526 +# define WONKY
20527 +#endif
20528 +
20529 +#ifndef pemalloc_rel
20530 +# define pemalloc_rel(size, persistent) ((persistent)?malloc(size):emalloc_rel(size))
20531 +#endif
20532 +
20533 +#ifndef ZEND_ACC_DEPRECATED
20534 +# define ZEND_ACC_DEPRECATED 0
20535 +#endif
20536 +
20537 +#if PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10
20538 +# define php_url_parse_ex(u, l) php_url_parse(u)
20539 +#endif
20540 +
20541 +#ifndef TSRMLS_FETCH_FROM_CTX
20542 +# ifdef ZTS
20543 +# define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
20544 +# else
20545 +# define TSRMLS_FETCH_FROM_CTX(ctx)
20546 +# endif
20547 +#endif
20548 +
20549 +#ifndef TSRMLS_SET_CTX
20550 +# ifdef ZTS
20551 +# define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
20552 +# else
20553 +# define TSRMLS_SET_CTX(ctx)
20554 +# endif
20555 +#endif
20556 +
20557 +#ifndef ZVAL_ADDREF
20558 +# define ZVAL_ADDREF Z_ADDREF_P
20559 +#endif
20560 +
20561 +#ifndef SEPARATE_ARG_IF_REF
20562 +#define SEPARATE_ARG_IF_REF(zv) \
20563 + if (PZVAL_IS_REF(zv)) { \
20564 + zval *ov = zv; \
20565 + ALLOC_INIT_ZVAL(zv); \
20566 + Z_TYPE_P(zv) = Z_TYPE_P(ov); \
20567 + zv->value = ov->value; \
20568 + zval_copy_ctor(zv); \
20569 + } else { \
20570 + ZVAL_ADDREF(zv); \
20571 + }
20572 +#endif
20573 +
20574 +#ifndef ZVAL_ZVAL
20575 +#define ZVAL_ZVAL(z, zv, copy, dtor) { \
20576 + int is_ref, refcount; \
20577 + is_ref = (z)->is_ref; \
20578 + refcount = (z)->refcount; \
20579 + *(z) = *(zv); \
20580 + if (copy) { \
20581 + zval_copy_ctor(z); \
20582 + } \
20583 + if (dtor) { \
20584 + if (!copy) { \
20585 + ZVAL_NULL(zv); \
20586 + } \
20587 + zval_ptr_dtor(&zv); \
20588 + } \
20589 + (z)->is_ref = is_ref; \
20590 + (z)->refcount = refcount; \
20591 + }
20592 +#endif
20593 +#ifndef RETVAL_ZVAL
20594 +# define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
20595 +#endif
20596 +#ifndef RETURN_ZVAL
20597 +# define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
20598 +#endif
20599 +
20600 +#ifndef ZEND_MN
20601 +# define ZEND_MN(name) ZEND_FN(name)
20602 +#endif
20603 +
20604 +#ifdef WONKY
20605 +extern int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC);
20606 +extern void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC);
20607 +
20608 +extern int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC);
20609 +extern void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC);
20610 +
20611 +extern void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC);
20612 +#endif
20613 +
20614 +#endif
20615 +
20616 +/*
20617 + * Local variables:
20618 + * tab-width: 4
20619 + * c-basic-offset: 4
20620 + * End:
20621 + * vim600: noet sw=4 ts=4 fdm=marker
20622 + * vim<600: noet sw=4 ts=4
20623 + */
20624 +
20625 --- /dev/null
20626 +++ b/ext/http/php_http.h
20627 @@ -0,0 +1,262 @@
20628 +/*
20629 + +--------------------------------------------------------------------+
20630 + | PECL :: http |
20631 + +--------------------------------------------------------------------+
20632 + | Redistribution and use in source and binary forms, with or without |
20633 + | modification, are permitted provided that the conditions mentioned |
20634 + | in the accompanying LICENSE file are met. |
20635 + +--------------------------------------------------------------------+
20636 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20637 + +--------------------------------------------------------------------+
20638 +*/
20639 +
20640 +/* $Id: php_http.h 324012 2012-03-08 08:44:32Z mike $ */
20641 +
20642 +#ifndef PHP_EXT_HTTP_H
20643 +#define PHP_EXT_HTTP_H
20644 +
20645 +#define PHP_HTTP_VERSION "1.7.4"
20646 +
20647 +#ifdef HAVE_CONFIG_H
20648 +# include "config.h"
20649 +#else
20650 +# ifndef PHP_WIN32
20651 +# include "php_config.h"
20652 +# endif
20653 +#endif
20654 +
20655 +#include "php.h"
20656 +#include "missing.h"
20657 +#include "php_http_std_defs.h"
20658 +#include "phpstr/phpstr.h"
20659 +
20660 +#ifdef HTTP_WANT_SAPI
20661 +# if PHP_API_VERSION > 20041225
20662 +# define HTTP_HAVE_SAPI_RTIME
20663 +# endif
20664 +# include "SAPI.h"
20665 +#endif
20666 +
20667 +#ifdef HTTP_WANT_NETDB
20668 +# ifdef PHP_WIN32
20669 +# define HTTP_HAVE_NETDB
20670 +# include <winsock2.h>
20671 +# elif defined(HAVE_NETDB_H)
20672 +# define HTTP_HAVE_NETDB
20673 +# include <netdb.h>
20674 +# ifdef HAVE_UNISTD_H
20675 +# include <unistd.h>
20676 +# endif
20677 +# endif
20678 +#endif
20679 +
20680 +#if defined(HTTP_WANT_CURL) && defined(HTTP_HAVE_CURL)
20681 +# ifdef PHP_WIN32
20682 +# include <winsock2.h>
20683 +# define CURL_STATICLIB
20684 +# endif
20685 +# include <curl/curl.h>
20686 +# define HTTP_CURL_VERSION(x, y, z) (LIBCURL_VERSION_NUM >= (((x)<<16) + ((y)<<8) + (z)))
20687 +#
20688 +# if defined(HTTP_WANT_EVENT) && defined(HTTP_HAVE_EVENT)
20689 +# include <event.h>
20690 +# endif
20691 +#endif
20692 +
20693 +#if defined(HTTP_WANT_MAGIC) && defined(HTTP_HAVE_MAGIC)
20694 +# if defined(PHP_WIN32) && !defined(USE_MAGIC_DLL) && !defined(USE_MAGIC_STATIC)
20695 +# define USE_MAGIC_STATIC
20696 +# endif
20697 +# include <magic.h>
20698 +#endif
20699 +
20700 +#if defined(HTTP_WANT_ZLIB) && defined(HTTP_HAVE_ZLIB)
20701 +# include <zlib.h>
20702 +#endif
20703 +
20704 +#include <ctype.h>
20705 +#define HTTP_IS_CTYPE(type, c) is##type((int) (unsigned char) (c))
20706 +#define HTTP_TO_CTYPE(type, c) to##type((int) (unsigned char) (c))
20707 +
20708 +extern zend_module_entry http_module_entry;
20709 +#define phpext_http_ptr &http_module_entry
20710 +
20711 +extern int http_module_number;
20712 +
20713 +ZEND_BEGIN_MODULE_GLOBALS(http)
20714 +
20715 + struct _http_globals_etag {
20716 + char *mode;
20717 + void *ctx;
20718 + zend_bool started;
20719 + } etag;
20720 +
20721 + struct _http_globals_log {
20722 + char *cache;
20723 + char *redirect;
20724 + char *not_found;
20725 + char *allowed_methods;
20726 + char *composite;
20727 + } log;
20728 +
20729 + struct _http_globals_send {
20730 + double throttle_delay;
20731 + size_t buffer_size;
20732 + char *content_type;
20733 + char *unquoted_etag;
20734 + time_t last_modified;
20735 + struct _http_globals_send_deflate {
20736 + zend_bool response;
20737 + zend_bool start_auto;
20738 + long start_flags;
20739 + int encoding;
20740 + void *stream;
20741 + } deflate;
20742 + struct _http_globals_send_inflate {
20743 + zend_bool start_auto;
20744 + long start_flags;
20745 + void *stream;
20746 + } inflate;
20747 + zend_bool not_found_404;
20748 + } send;
20749 +
20750 + struct _http_globals_request {
20751 + time_t time;
20752 + HashTable *headers;
20753 + struct _http_globals_request_methods {
20754 + HashTable registered;
20755 + char *allowed;
20756 + char *custom;
20757 + } methods;
20758 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL)
20759 + struct _http_globals_request_datashare {
20760 + zend_llist handles;
20761 + zend_bool cookie;
20762 + zend_bool dns;
20763 + zend_bool ssl;
20764 + zend_bool connect;
20765 + } datashare;
20766 +#endif
20767 +#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_EVENT)
20768 + struct _http_globals_request_pool {
20769 + struct _http_globals_request_pool_event {
20770 + void *base;
20771 + } event;
20772 + } pool;
20773 +#endif
20774 + } request;
20775 +
20776 + struct _http_globals_persistent {
20777 + struct _http_globals_persistent_handles {
20778 + ulong limit;
20779 + struct _http_globals_persistent_handles_ident {
20780 + ulong h;
20781 + char *s;
20782 + size_t l;
20783 + } ident;
20784 + } handles;
20785 + } persistent;
20786 +
20787 +#ifdef ZEND_ENGINE_2
20788 + zend_bool only_exceptions;
20789 +#endif
20790 +
20791 + zend_bool force_exit;
20792 + zend_bool read_post_data;
20793 + zval *server_var;
20794 +
20795 +ZEND_END_MODULE_GLOBALS(http)
20796 +
20797 +ZEND_EXTERN_MODULE_GLOBALS(http);
20798 +
20799 +#ifdef ZTS
20800 +# include "TSRM.h"
20801 +# define HTTP_G ((zend_http_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(http_globals_id)])
20802 +#else
20803 +# define HTTP_G (&http_globals)
20804 +#endif
20805 +
20806 +#if defined(HAVE_ICONV) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_ICONV))
20807 +# define HTTP_HAVE_ICONV
20808 +#endif
20809 +
20810 +#if defined(HAVE_PHP_SESSION) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_SESSION))
20811 +# define HTTP_HAVE_SESSION
20812 +#endif
20813 +
20814 +#if defined(HAVE_HASH_EXT) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_HASH)) && defined(HTTP_HAVE_PHP_HASH_H)
20815 +# define HTTP_HAVE_HASH
20816 +#endif
20817 +
20818 +#if defined(HAVE_SPL)
20819 +# define HTTP_HAVE_SPL
20820 +#endif
20821 +
20822 +PHP_FUNCTION(http_date);
20823 +PHP_FUNCTION(http_build_url);
20824 +PHP_FUNCTION(http_build_str);
20825 +PHP_FUNCTION(http_negotiate_language);
20826 +PHP_FUNCTION(http_negotiate_charset);
20827 +PHP_FUNCTION(http_negotiate_content_type);
20828 +PHP_FUNCTION(http_negotiate);
20829 +PHP_FUNCTION(http_redirect);
20830 +PHP_FUNCTION(http_throttle);
20831 +PHP_FUNCTION(http_send_status);
20832 +PHP_FUNCTION(http_send_last_modified);
20833 +PHP_FUNCTION(http_send_content_type);
20834 +PHP_FUNCTION(http_send_content_disposition);
20835 +PHP_FUNCTION(http_match_modified);
20836 +PHP_FUNCTION(http_match_etag);
20837 +PHP_FUNCTION(http_cache_last_modified);
20838 +PHP_FUNCTION(http_cache_etag);
20839 +PHP_FUNCTION(http_send_data);
20840 +PHP_FUNCTION(http_send_file);
20841 +PHP_FUNCTION(http_send_stream);
20842 +PHP_FUNCTION(http_chunked_decode);
20843 +PHP_FUNCTION(http_parse_message);
20844 +PHP_FUNCTION(http_parse_headers);
20845 +PHP_FUNCTION(http_parse_cookie);
20846 +PHP_FUNCTION(http_build_cookie);
20847 +PHP_FUNCTION(http_parse_params);
20848 +PHP_FUNCTION(http_get_request_headers);
20849 +PHP_FUNCTION(http_get_request_body);
20850 +PHP_FUNCTION(http_get_request_body_stream);
20851 +PHP_FUNCTION(http_match_request_header);
20852 +PHP_FUNCTION(http_persistent_handles_count);
20853 +PHP_FUNCTION(http_persistent_handles_clean);
20854 +PHP_FUNCTION(http_persistent_handles_ident);
20855 +#ifdef HTTP_HAVE_CURL
20856 +PHP_FUNCTION(http_get);
20857 +PHP_FUNCTION(http_head);
20858 +PHP_FUNCTION(http_post_data);
20859 +PHP_FUNCTION(http_post_fields);
20860 +PHP_FUNCTION(http_put_data);
20861 +PHP_FUNCTION(http_put_file);
20862 +PHP_FUNCTION(http_put_stream);
20863 +PHP_FUNCTION(http_request);
20864 +PHP_FUNCTION(http_request_body_encode);
20865 +#endif /* HTTP_HAVE_CURL */
20866 +PHP_FUNCTION(http_request_method_register);
20867 +PHP_FUNCTION(http_request_method_unregister);
20868 +PHP_FUNCTION(http_request_method_exists);
20869 +PHP_FUNCTION(http_request_method_name);
20870 +PHP_FUNCTION(ob_etaghandler);
20871 +#ifdef HTTP_HAVE_ZLIB
20872 +PHP_FUNCTION(http_deflate);
20873 +PHP_FUNCTION(http_inflate);
20874 +PHP_FUNCTION(ob_deflatehandler);
20875 +PHP_FUNCTION(ob_inflatehandler);
20876 +#endif
20877 +PHP_FUNCTION(http_support);
20878 +
20879 +#endif /* PHP_HTTP_H */
20880 +
20881 +/*
20882 + * Local variables:
20883 + * tab-width: 4
20884 + * c-basic-offset: 4
20885 + * End:
20886 + * vim600: noet sw=4 ts=4 fdm=marker
20887 + * vim<600: noet sw=4 ts=4
20888 + */
20889 +
20890 --- /dev/null
20891 +++ b/ext/http/php_http_api.h
20892 @@ -0,0 +1,326 @@
20893 +/*
20894 + +--------------------------------------------------------------------+
20895 + | PECL :: http |
20896 + +--------------------------------------------------------------------+
20897 + | Redistribution and use in source and binary forms, with or without |
20898 + | modification, are permitted provided that the conditions mentioned |
20899 + | in the accompanying LICENSE file are met. |
20900 + +--------------------------------------------------------------------+
20901 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
20902 + +--------------------------------------------------------------------+
20903 +*/
20904 +
20905 +/* $Id: php_http_api.h 323304 2012-02-17 21:13:24Z mike $ */
20906 +
20907 +#ifndef PHP_HTTP_API_H
20908 +#define PHP_HTTP_API_H
20909 +
20910 +#define HTTP_SUPPORT 0x01L
20911 +#define HTTP_SUPPORT_REQUESTS 0x02L
20912 +#define HTTP_SUPPORT_MAGICMIME 0x04L
20913 +#define HTTP_SUPPORT_ENCODINGS 0x08L
20914 +#define HTTP_SUPPORT_SSLREQUESTS 0x20L
20915 +#define HTTP_SUPPORT_PERSISTENCE 0x40L
20916 +#define HTTP_SUPPORT_EVENTS 0x80L
20917 +
20918 +#define HTTP_PARAMS_ALLOW_COMMA 0x01
20919 +#define HTTP_PARAMS_ALLOW_FAILURE 0x02
20920 +#define HTTP_PARAMS_RAISE_ERROR 0x04
20921 +#define HTTP_PARAMS_DEFAULT (HTTP_PARAMS_ALLOW_COMMA|HTTP_PARAMS_ALLOW_FAILURE|HTTP_PARAMS_RAISE_ERROR)
20922 +#define HTTP_PARAMS_COLON_SEPARATOR 0x10
20923 +
20924 +extern PHP_MINIT_FUNCTION(http_support);
20925 +
20926 +#define http_support(f) _http_support(f)
20927 +PHP_HTTP_API long _http_support(long feature);
20928 +
20929 +#define pretty_key(key, key_len, uctitle, xhyphen) _http_pretty_key(key, key_len, uctitle, xhyphen)
20930 +extern char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen);
20931 +
20932 +#define http_boundary(b, l) _http_boundary((b), (l) TSRMLS_CC)
20933 +extern size_t _http_boundary(char *buf, size_t len TSRMLS_DC);
20934 +
20935 +#define http_error(type, code, string) _http_error_ex(type, code, "%s", string)
20936 +#define http_error_ex _http_error_ex
20937 +extern void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...);
20938 +
20939 +
20940 +#ifdef ZEND_ENGINE_2
20941 +#define http_exception_wrap(o, n, ce) _http_exception_wrap((o), (n), (ce) TSRMLS_CC)
20942 +extern zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC);
20943 +
20944 +#define http_try \
20945 +{ \
20946 + zval *old_exception = EG(exception); \
20947 + EG(exception) = NULL;
20948 +#define http_catch(ex_ce) \
20949 + if (EG(exception) && old_exception) { \
20950 + EG(exception) = http_exception_wrap(old_exception, EG(exception), ex_ce); \
20951 + } \
20952 +}
20953 +#define http_final(ex_ce) \
20954 + if (EG(exception)) { \
20955 + EG(exception) = http_exception_wrap(EG(exception), NULL, ex_ce); \
20956 + }
20957 +
20958 +typedef zend_object_value (*http_object_new_t)(zend_class_entry *ce, void *, void ** TSRMLS_DC);
20959 +
20960 +#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)
20961 +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);
20962 +#endif /* ZEND_ENGINE_2 */
20963 +
20964 +
20965 +#define HTTP_CHECK_CURL_INIT(ch, init, action) \
20966 + if ((!(ch)) && (!((ch) = init))) { \
20967 + http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initialize curl"); \
20968 + action; \
20969 + }
20970 +#define HTTP_CHECK_CONTENT_TYPE(ct, action) \
20971 + if (!strchr((ct), '/')) { \
20972 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, \
20973 + "Content type \"%s\" does not seem to contain a primary and a secondary part", (ct)); \
20974 + action; \
20975 + }
20976 +#define HTTP_CHECK_MESSAGE_TYPE_RESPONSE(msg, action) \
20977 + if (!HTTP_MSG_TYPE(RESPONSE, (msg))) { \
20978 + http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_RESPONSE"); \
20979 + action; \
20980 + }
20981 +#define HTTP_CHECK_MESSAGE_TYPE_REQUEST(msg, action) \
20982 + if (!HTTP_MSG_TYPE(REQUEST, (msg))) { \
20983 + http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST"); \
20984 + action; \
20985 + }
20986 +#define HTTP_CHECK_GZIP_LEVEL(level, action) \
20987 + if (level < -1 || level > 9) { \
20988 + http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid compression level (-1 to 9): %d", level); \
20989 + action; \
20990 + }
20991 +#ifndef PHP_OUTPUT_NEWAPI
20992 +# define HTTP_GET_OUTPUT_START() \
20993 + char *output_start_filename = php_get_output_start_filename(TSRMLS_C); \
20994 + int output_start_lineno = php_get_output_start_lineno(TSRMLS_C)
20995 +#else
20996 +# define HTTP_GET_OUTPUT_START() \
20997 + char *output_start_filename = php_output_get_start_filename(TSRMLS_C); \
20998 + int output_start_lineno = php_output_get_start_lineno(TSRMLS_C)
20999 +#endif
21000 +#define HTTP_CHECK_HEADERS_SENT(action) \
21001 + if (SG(headers_sent) && !SG(request_info).no_headers) { \
21002 + HTTP_GET_OUTPUT_START(); \
21003 + if (output_start_filename) { \
21004 + http_error_ex(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent by (output started at %s:%d)", \
21005 + output_start_filename, output_start_lineno); \
21006 + } else { \
21007 + http_error(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent"); \
21008 + } \
21009 + action; \
21010 + }
21011 +
21012 +#define http_log(f, i, m) _http_log_ex((f), (i), (m) TSRMLS_CC)
21013 +extern void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC);
21014 +
21015 +#define http_exit(s, h) http_exit_ex((s), (h), NULL, 1)
21016 +#define http_exit_ex(s, h, b, e) _http_exit_ex((s), (h), (b), (e) TSRMLS_CC)
21017 +extern STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC);
21018 +
21019 +#define http_check_method(m) http_check_method_ex((m), HTTP_KNOWN_METHODS)
21020 +#define http_check_method_ex(m, a) _http_check_method_ex((m), (a))
21021 +extern STATUS _http_check_method_ex(const char *method, const char *methods);
21022 +
21023 +#define http_got_server_var(v) (NULL != http_get_server_var_ex((v), strlen(v), 1))
21024 +#define http_get_server_var(v, c) http_get_server_var_ex((v), strlen(v), (c))
21025 +#define http_get_server_var_ex(v, l, c) _http_get_server_var_ex((v), (l), (c) TSRMLS_CC)
21026 +PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC);
21027 +
21028 +#define http_get_request_body(b, l) _http_get_request_body_ex((b), (l), 1 TSRMLS_CC)
21029 +#define http_get_request_body_ex(b, l, d) _http_get_request_body_ex((b), (l), (d) TSRMLS_CC)
21030 +PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC);
21031 +
21032 +#define http_get_request_body_stream() _http_get_request_body_stream(TSRMLS_C)
21033 +PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D);
21034 +
21035 +
21036 +typedef void (*http_parse_params_callback)(void *cb_arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC);
21037 +
21038 +#define http_parse_params_default_callback _http_parse_params_default_callback
21039 +PHP_HTTP_API void _http_parse_params_default_callback(void *ht, const char *key, int keylen, const char *val, int vallen TSRMLS_DC);
21040 +
21041 +#define http_parse_params(s, f, ht) _http_parse_params_ex((s), (f), _http_parse_params_default_callback, (ht) TSRMLS_CC)
21042 +#define http_parse_params_ex(s, f, cb, a) _http_parse_params_ex((s), (f), (cb), (a) TSRMLS_CC)
21043 +PHP_HTTP_API STATUS _http_parse_params_ex(const char *params, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC);
21044 +
21045 +
21046 +#define http_sleep(s) _http_sleep(s)
21047 +static inline void _http_sleep(double s)
21048 +{
21049 +#define HTTP_DIFFSEC (0.001)
21050 +#define HTTP_MLLISEC (1000)
21051 +#define HTTP_MCROSEC (1000 * 1000)
21052 +#define HTTP_NANOSEC (1000 * 1000 * 1000)
21053 +#define HTTP_MSEC(s) ((long)(s * HTTP_MLLISEC))
21054 +#define HTTP_USEC(s) ((long)(s * HTTP_MCROSEC))
21055 +#define HTTP_NSEC(s) ((long)(s * HTTP_NANOSEC))
21056 +
21057 +#if defined(PHP_WIN32)
21058 + Sleep((DWORD) HTTP_MSEC(s));
21059 +#elif defined(HAVE_USLEEP)
21060 + usleep(HTTP_USEC(s));
21061 +#elif defined(HAVE_NANOSLEEP)
21062 + struct timespec req, rem;
21063 +
21064 + req.tv_sec = (time_t) s;
21065 + req.tv_nsec = HTTP_NSEC(s) % HTTP_NANOSEC;
21066 +
21067 + while (nanosleep(&req, &rem) && (errno == EINTR) && (HTTP_NSEC(rem.tv_sec) + rem.tv_nsec) > HTTP_NSEC(HTTP_DIFFSEC))) {
21068 + req.tv_sec = rem.tv_sec;
21069 + req.tv_nsec = rem.tv_nsec;
21070 + }
21071 +#else
21072 + struct timeval timeout;
21073 +
21074 + timeout.tv.sec = (time_t) s;
21075 + timeout.tv_usec = HTTP_USEC(s) % HTTP_MCROSEC;
21076 +
21077 + select(0, NULL, NULL, NULL, &timeout);
21078 +#endif
21079 +}
21080 +
21081 +#define http_locate_str _http_locate_str
21082 +static inline const char *_http_locate_str(const char *h, size_t h_len, const char *n, size_t n_len)
21083 +{
21084 + const char *p, *e;
21085 +
21086 + if (n_len && h_len) {
21087 + e = h + h_len;
21088 + do {
21089 + if (*h == *n) {
21090 + for (p = n; *p == h[p-n]; ++p) {
21091 + if (p == n+n_len-1) {
21092 + return h;
21093 + }
21094 + }
21095 + }
21096 + } while (h++ != e);
21097 + }
21098 +
21099 + return NULL;
21100 +}
21101 +
21102 +#define http_locate_body _http_locate_body
21103 +static inline const char *_http_locate_body(const char *message)
21104 +{
21105 + const char *body = NULL, *msg = message;
21106 +
21107 + while (*msg) {
21108 + if (*msg == '\n') {
21109 + if (*(msg+1) == '\n') {
21110 + body = msg + 2;
21111 + break;
21112 + } else if (*(msg+1) == '\r' && *(msg+2) == '\n') {
21113 + body = msg + 3;
21114 + break;
21115 + }
21116 + }
21117 + ++msg;
21118 + }
21119 + return body;
21120 +}
21121 +
21122 +#define http_locate_eol _http_locate_eol
21123 +static inline const char *_http_locate_eol(const char *line, int *eol_len)
21124 +{
21125 + const char *eol = strpbrk(line, "\r\n");
21126 +
21127 + if (eol_len) {
21128 + *eol_len = eol ? ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1) : 0;
21129 + }
21130 + return eol;
21131 +}
21132 +
21133 +#define http_zset(t, z) _http_zset((t), (z))
21134 +static inline zval *_http_zset(int type, zval *z)
21135 +{
21136 + if (Z_TYPE_P(z) != type) {
21137 + switch (type) {
21138 + case IS_NULL: convert_to_null(z); break;
21139 + case IS_BOOL: convert_to_boolean(z); break;
21140 + case IS_LONG: convert_to_long(z); break;
21141 + case IS_DOUBLE: convert_to_double(z); break;
21142 + case IS_STRING: convert_to_string(z); break;
21143 + case IS_ARRAY: convert_to_array(z); break;
21144 + case IS_OBJECT: convert_to_object(z); break;
21145 + }
21146 + }
21147 + return z;
21148 +}
21149 +#define http_zsep(t, z) _http_zsep_ex((t), (z), NULL)
21150 +#define http_zsep_ex(t, z, p) _http_zsep_ex((t), (z), (p))
21151 +static inline zval *_http_zsep_ex(int type, zval *z, zval **p) {
21152 + ZVAL_ADDREF(z);
21153 + if (Z_TYPE_P(z) != type) {
21154 + switch (type) {
21155 + case IS_NULL: convert_to_null_ex(&z); break;
21156 + case IS_BOOL: convert_to_boolean_ex(&z); break;
21157 + case IS_LONG: convert_to_long_ex(&z); break;
21158 + case IS_DOUBLE: convert_to_double_ex(&z); break;
21159 + case IS_STRING: convert_to_string_ex(&z); break;
21160 + case IS_ARRAY: convert_to_array_ex(&z); break;
21161 + case IS_OBJECT: convert_to_object_ex(&z); break;
21162 + }
21163 + } else {
21164 + SEPARATE_ZVAL_IF_NOT_REF(&z);
21165 + }
21166 + if (p) {
21167 + *p = z;
21168 + }
21169 + return z;
21170 +}
21171 +
21172 +typedef struct _HashKey {
21173 + char *str;
21174 + uint len;
21175 + ulong num;
21176 + uint dup:1;
21177 + uint type:31;
21178 +} HashKey;
21179 +#define initHashKey(dup) {NULL, 0, 0, (dup), 0}
21180 +
21181 +#define FOREACH_VAL(pos, array, val) FOREACH_HASH_VAL(pos, Z_ARRVAL_P(array), val)
21182 +#define FOREACH_HASH_VAL(pos, hash, val) \
21183 + for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
21184 + zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
21185 + zend_hash_move_forward_ex(hash, &pos))
21186 +
21187 +#define FOREACH_KEY(pos, array, key) FOREACH_HASH_KEY(pos, Z_ARRVAL_P(array), key)
21188 +#define FOREACH_HASH_KEY(pos, hash, _key) \
21189 + for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
21190 + ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT; \
21191 + zend_hash_move_forward_ex(hash, &pos)) \
21192 +
21193 +#define FOREACH_KEYVAL(pos, array, key, val) FOREACH_HASH_KEYVAL(pos, Z_ARRVAL_P(array), key, val)
21194 +#define FOREACH_HASH_KEYVAL(pos, hash, _key, val) \
21195 + for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \
21196 + ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT && \
21197 + zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \
21198 + zend_hash_move_forward_ex(hash, &pos))
21199 +
21200 +#define array_copy(src, dst) zend_hash_copy(dst, src, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *))
21201 +#define ARRAY_JOIN_STRONLY 1
21202 +#define ARRAY_JOIN_PRETTIFY 2
21203 +#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)
21204 +
21205 +extern int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
21206 +extern int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key);
21207 +
21208 +#endif
21209 +
21210 +/*
21211 + * Local variables:
21212 + * tab-width: 4
21213 + * c-basic-offset: 4
21214 + * End:
21215 + * vim600: noet sw=4 ts=4 fdm=marker
21216 + * vim<600: noet sw=4 ts=4
21217 + */
21218 +
21219 --- /dev/null
21220 +++ b/ext/http/php_http_cache_api.h
21221 @@ -0,0 +1,162 @@
21222 +/*
21223 + +--------------------------------------------------------------------+
21224 + | PECL :: http |
21225 + +--------------------------------------------------------------------+
21226 + | Redistribution and use in source and binary forms, with or without |
21227 + | modification, are permitted provided that the conditions mentioned |
21228 + | in the accompanying LICENSE file are met. |
21229 + +--------------------------------------------------------------------+
21230 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21231 + +--------------------------------------------------------------------+
21232 +*/
21233 +
21234 +/* $Id: php_http_cache_api.h 292841 2009-12-31 08:48:57Z mike $ */
21235 +
21236 +#ifndef PHP_HTTP_CACHE_API_H
21237 +#define PHP_HTTP_CACHE_API_H
21238 +
21239 +#include "php_http_send_api.h"
21240 +
21241 +#include "ext/standard/crc32.h"
21242 +#include "ext/standard/sha1.h"
21243 +#include "ext/standard/md5.h"
21244 +
21245 +#ifdef HTTP_HAVE_HASH
21246 +# include "php_hash.h"
21247 +#endif
21248 +
21249 +#define http_etag_digest(d, l) _http_etag_digest((d), (l))
21250 +static inline char *_http_etag_digest(const unsigned char *digest, int len)
21251 +{
21252 + static const char hexdigits[17] = "0123456789abcdef";
21253 + int i;
21254 + char *hex = emalloc(len * 2 + 1);
21255 + char *ptr = hex;
21256 +
21257 + for (i = 0; i < len; ++i) {
21258 + *ptr++ = hexdigits[digest[i] >> 4];
21259 + *ptr++ = hexdigits[digest[i] & 0xF];
21260 + }
21261 + *ptr = '\0';
21262 +
21263 + return hex;
21264 +}
21265 +
21266 +#define http_etag_init() _http_etag_init(TSRMLS_C)
21267 +static inline void *_http_etag_init(TSRMLS_D)
21268 +{
21269 + void *ctx = NULL;
21270 + char *mode = HTTP_G->etag.mode;
21271 +
21272 +#ifdef HTTP_HAVE_HASH
21273 + const php_hash_ops *eho = NULL;
21274 +
21275 + if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
21276 + ctx = emalloc(eho->context_size);
21277 + eho->hash_init(ctx);
21278 + } else
21279 +#endif
21280 + if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
21281 + ctx = emalloc(sizeof(uint));
21282 + *((uint *) ctx) = ~0;
21283 + } else if (mode && !strcasecmp(mode, "sha1")) {
21284 + PHP_SHA1Init(ctx = emalloc(sizeof(PHP_SHA1_CTX)));
21285 + } else {
21286 + PHP_MD5Init(ctx = emalloc(sizeof(PHP_MD5_CTX)));
21287 + }
21288 +
21289 + return ctx;
21290 +}
21291 +
21292 +#define http_etag_finish(c) _http_etag_finish((c) TSRMLS_CC)
21293 +static inline char *_http_etag_finish(void *ctx TSRMLS_DC)
21294 +{
21295 + unsigned char digest[128] = {0};
21296 + char *etag = NULL, *mode = HTTP_G->etag.mode;
21297 +
21298 +#ifdef HTTP_HAVE_HASH
21299 + const php_hash_ops *eho = NULL;
21300 +
21301 + if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
21302 + eho->hash_final(digest, ctx);
21303 + etag = http_etag_digest(digest, eho->digest_size);
21304 + } else
21305 +#endif
21306 + if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
21307 + *((uint *) ctx) = ~*((uint *) ctx);
21308 + etag = http_etag_digest((const unsigned char *) ctx, sizeof(uint));
21309 + } else if (mode && (!strcasecmp(mode, "sha1"))) {
21310 + PHP_SHA1Final(digest, ctx);
21311 + etag = http_etag_digest(digest, 20);
21312 + } else {
21313 + PHP_MD5Final(digest, ctx);
21314 + etag = http_etag_digest(digest, 16);
21315 + }
21316 + efree(ctx);
21317 +
21318 + return etag;
21319 +}
21320 +
21321 +#define http_etag_update(c, d, l) _http_etag_update((c), (d), (l) TSRMLS_CC)
21322 +static inline void _http_etag_update(void *ctx, const char *data_ptr, size_t data_len TSRMLS_DC)
21323 +{
21324 + char *mode = HTTP_G->etag.mode;
21325 +#ifdef HTTP_HAVE_HASH
21326 + const php_hash_ops *eho = NULL;
21327 +
21328 + if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
21329 + eho->hash_update(ctx, (const unsigned char *) data_ptr, data_len);
21330 + } else
21331 +#endif
21332 + if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
21333 + uint i, c = *((uint *) ctx);
21334 + for (i = 0; i < data_len; ++i) {
21335 + CRC32(c, data_ptr[i]);
21336 + }
21337 + *((uint *)ctx) = c;
21338 + } else if (mode && (!strcasecmp(mode, "sha1"))) {
21339 + PHP_SHA1Update(ctx, (const unsigned char *) data_ptr, data_len);
21340 + } else {
21341 + PHP_MD5Update(ctx, (const unsigned char *) data_ptr, data_len);
21342 + }
21343 +}
21344 +
21345 +#define http_ob_etaghandler(o, l, ho, hl, m) _http_ob_etaghandler((o), (l), (ho), (hl), (m) TSRMLS_CC)
21346 +extern void _http_ob_etaghandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC);
21347 +
21348 +#define http_etag(p, l, m) _http_etag((p), (l), (m) TSRMLS_CC)
21349 +PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC);
21350 +
21351 +#define http_last_modified(p, m) _http_last_modified((p), (m) TSRMLS_CC)
21352 +PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC);
21353 +
21354 +#define http_match_last_modified(entry, modified) _http_match_last_modified_ex((entry), (modified), 1 TSRMLS_CC)
21355 +#define http_match_last_modified_ex(entry, modified, ep) _http_match_last_modified_ex((entry), (modified), (ep) TSRMLS_CC)
21356 +PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC);
21357 +
21358 +#define http_match_etag(entry, etag) _http_match_etag_ex((entry), (etag), 1 TSRMLS_CC)
21359 +#define http_match_etag_ex(entry, etag, ep) _http_match_etag_ex((entry), (etag), (ep) TSRMLS_CC)
21360 +PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC);
21361 +
21362 +#define http_cache_last_modified(l, s, cc, ccl) _http_cache_last_modified((l), (s), (cc), (ccl) TSRMLS_CC)
21363 +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);
21364 +
21365 +#define http_cache_etag(e, el, cc, ccl) _http_cache_etag((e), (el), (cc), (ccl) TSRMLS_CC)
21366 +PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len, const char *cache_control, size_t cc_len TSRMLS_DC);
21367 +
21368 +#define http_start_ob_etaghandler() _http_start_ob_etaghandler(TSRMLS_C)
21369 +PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D);
21370 +#define http_interrupt_ob_etaghandler() _http_interrupt_ob_etaghandler(TSRMLS_C)
21371 +PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D);
21372 +
21373 +#endif
21374 +
21375 +/*
21376 + * Local variables:
21377 + * tab-width: 4
21378 + * c-basic-offset: 4
21379 + * End:
21380 + * vim600: noet sw=4 ts=4 fdm=marker
21381 + * vim<600: noet sw=4 ts=4
21382 + */
21383 +
21384 --- /dev/null
21385 +++ b/ext/http/php_http_cookie_api.h
21386 @@ -0,0 +1,86 @@
21387 +/*
21388 + +--------------------------------------------------------------------+
21389 + | PECL :: http |
21390 + +--------------------------------------------------------------------+
21391 + | Redistribution and use in source and binary forms, with or without |
21392 + | modification, are permitted provided that the conditions mentioned |
21393 + | in the accompanying LICENSE file are met. |
21394 + +--------------------------------------------------------------------+
21395 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21396 + +--------------------------------------------------------------------+
21397 +*/
21398 +
21399 +/* $Id: php_http_cookie_api.h 292841 2009-12-31 08:48:57Z mike $ */
21400 +
21401 +#ifndef PHP_HTTP_COOKIE_API_H
21402 +#define PHP_HTTP_COOKIE_API_H
21403 +
21404 +#define HTTP_COOKIE_SECURE 0x10L
21405 +#define HTTP_COOKIE_HTTPONLY 0x20L
21406 +
21407 +#define HTTP_COOKIE_PARSE_RAW 0x01L
21408 +
21409 +extern PHP_MINIT_FUNCTION(http_cookie);
21410 +
21411 +/*
21412 + generally a netscape cookie compliant struct, recognizing httpOnly attribute, too;
21413 + cookie params like those from rfc2109 and rfc2965 are just put into extras, if
21414 + one specifies them in allowed extras, else they're treated like cookies themself
21415 +*/
21416 +typedef struct _http_cookie_list_t {
21417 + HashTable cookies;
21418 + HashTable extras;
21419 + long flags;
21420 + char *path;
21421 + char *domain;
21422 + time_t expires;
21423 +} http_cookie_list;
21424 +
21425 +#define http_cookie_list_new() _http_cookie_list_init(NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
21426 +#define http_cookie_list_init(l) _http_cookie_list_init((l) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
21427 +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);
21428 +
21429 +#define http_cookie_list_dtor(l) _http_cookie_list_dtor((l) TSRMLS_CC)
21430 +PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC);
21431 +
21432 +#define http_cookie_list_free(l) _http_cookie_list_free((l) TSRMLS_CC)
21433 +PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC);
21434 +
21435 +#define http_cookie_list_has_cookie(list, name, name_len) zend_hash_exists(&(list)->cookies, (name), (name_len)+1)
21436 +#define http_cookie_list_has_extra(list, name, name_len) zend_hash_exists(&(list)->extras, (name), (name_len)+1)
21437 +
21438 +#define http_cookie_list_add_cookie(l, n, nl, v, vl) _http_cookie_list_add_cookie((l), (n), (nl), (v), (vl) TSRMLS_CC)
21439 +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);
21440 +
21441 +#define http_cookie_list_add_extra(l, n , nl, v, vl) _http_cookie_list_add_extra((l), (n), (nl), (v), (vl) TSRMLS_CC)
21442 +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);
21443 +
21444 +#define http_cookie_list_get_cookie(l, n, nl) _http_cookie_list_get_cookie((l), (n), (nl) TSRMLS_CC)
21445 +PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC);
21446 +
21447 +#define http_cookie_list_get_extra(l, n, nl) _http_cookie_list_get_extra((l), (n), (nl) TSRMLS_CC)
21448 +PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC);
21449 +
21450 +#define http_parse_cookie(s) _http_parse_cookie_ex(NULL, (s), 0, NULL TSRMLS_CC)
21451 +#define http_parse_cookie_ex(l, s, f, a) _http_parse_cookie_ex((l), (s), (f), (a) TSRMLS_CC)
21452 +PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list * list, const char *string, long flags, char **allowed_extras TSRMLS_DC);
21453 +
21454 +#define http_cookie_list_tostruct(l, s) _http_cookie_list_tostruct((l), (s) TSRMLS_CC)
21455 +PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC);
21456 +
21457 +#define http_cookie_list_fromstruct(l, s) _http_cookie_list_fromstruct((l), (s) TSRMLS_CC)
21458 +PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC);
21459 +
21460 +#define http_cookie_list_tostring(l, str, len) _http_cookie_list_tostring((l), (str), (len) TSRMLS_CC)
21461 +PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC);
21462 +
21463 +#endif
21464 +
21465 +/*
21466 + * Local variables:
21467 + * tab-width: 4
21468 + * c-basic-offset: 4
21469 + * End:
21470 + * vim600: noet sw=4 ts=4 fdm=marker
21471 + * vim<600: noet sw=4 ts=4
21472 + */
21473 --- /dev/null
21474 +++ b/ext/http/php_http_date_api.h
21475 @@ -0,0 +1,35 @@
21476 +/*
21477 + +--------------------------------------------------------------------+
21478 + | PECL :: http |
21479 + +--------------------------------------------------------------------+
21480 + | Redistribution and use in source and binary forms, with or without |
21481 + | modification, are permitted provided that the conditions mentioned |
21482 + | in the accompanying LICENSE file are met. |
21483 + +--------------------------------------------------------------------+
21484 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21485 + +--------------------------------------------------------------------+
21486 +*/
21487 +
21488 +/* $Id: php_http_date_api.h 292841 2009-12-31 08:48:57Z mike $ */
21489 +
21490 +#ifndef PHP_HTTP_DATE_API_H
21491 +#define PHP_HTTP_DATE_API_H
21492 +
21493 +#define http_date(t) _http_date((t) TSRMLS_CC)
21494 +PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC);
21495 +
21496 +#define http_parse_date(d) _http_parse_date_ex((d), 0 TSRMLS_CC)
21497 +#define http_parse_date_ex(d, s) _http_parse_date_ex((d), (s) TSRMLS_CC)
21498 +PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC);
21499 +
21500 +#endif
21501 +
21502 +/*
21503 + * Local variables:
21504 + * tab-width: 4
21505 + * c-basic-offset: 4
21506 + * End:
21507 + * vim600: noet sw=4 ts=4 fdm=marker
21508 + * vim<600: noet sw=4 ts=4
21509 + */
21510 +
21511 --- /dev/null
21512 +++ b/ext/http/php_http_deflatestream_object.h
21513 @@ -0,0 +1,57 @@
21514 +/*
21515 + +--------------------------------------------------------------------+
21516 + | PECL :: http |
21517 + +--------------------------------------------------------------------+
21518 + | Redistribution and use in source and binary forms, with or without |
21519 + | modification, are permitted provided that the conditions mentioned |
21520 + | in the accompanying LICENSE file are met. |
21521 + +--------------------------------------------------------------------+
21522 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21523 + +--------------------------------------------------------------------+
21524 +*/
21525 +
21526 +/* $Id: php_http_deflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */
21527 +
21528 +#ifndef PHP_HTTP_DEFLATESTREAM_OBJECT_H
21529 +#define PHP_HTTP_DEFLATESTREAM_OBJECT_H
21530 +#ifdef HTTP_HAVE_ZLIB
21531 +#ifdef ZEND_ENGINE_2
21532 +
21533 +typedef struct _http_deflatestream_object_t {
21534 + zend_object zo;
21535 + http_encoding_stream *stream;
21536 +} http_deflatestream_object;
21537 +
21538 +extern zend_class_entry *http_deflatestream_object_ce;
21539 +extern zend_function_entry http_deflatestream_object_fe[];
21540 +
21541 +extern PHP_MINIT_FUNCTION(http_deflatestream_object);
21542 +
21543 +#define http_deflatestream_object_new(ce) _http_deflatestream_object_new((ce) TSRMLS_CC)
21544 +extern zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC);
21545 +#define http_deflatestream_object_new_ex(ce, s, ptr) _http_deflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
21546 +extern zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC);
21547 +#define http_deflatestream_object_clone(zobj) _http_deflatestream_object_clone_obj(zobj TSRMLS_CC)
21548 +extern zend_object_value _http_deflatestream_object_clone_obj(zval *object TSRMLS_DC);
21549 +#define http_deflatestream_object_free(o) _http_deflatestream_object_free((o) TSRMLS_CC)
21550 +extern void _http_deflatestream_object_free(zend_object *object TSRMLS_DC);
21551 +
21552 +PHP_METHOD(HttpDeflateStream, __construct);
21553 +PHP_METHOD(HttpDeflateStream, factory);
21554 +PHP_METHOD(HttpDeflateStream, update);
21555 +PHP_METHOD(HttpDeflateStream, flush);
21556 +PHP_METHOD(HttpDeflateStream, finish);
21557 +
21558 +#endif
21559 +#endif
21560 +#endif
21561 +
21562 +/*
21563 + * Local variables:
21564 + * tab-width: 4
21565 + * c-basic-offset: 4
21566 + * End:
21567 + * vim600: noet sw=4 ts=4 fdm=marker
21568 + * vim<600: noet sw=4 ts=4
21569 + */
21570 +
21571 --- /dev/null
21572 +++ b/ext/http/php_http_encoding_api.h
21573 @@ -0,0 +1,192 @@
21574 +/*
21575 + +--------------------------------------------------------------------+
21576 + | PECL :: http |
21577 + +--------------------------------------------------------------------+
21578 + | Redistribution and use in source and binary forms, with or without |
21579 + | modification, are permitted provided that the conditions mentioned |
21580 + | in the accompanying LICENSE file are met. |
21581 + +--------------------------------------------------------------------+
21582 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21583 + +--------------------------------------------------------------------+
21584 +*/
21585 +
21586 +/* $Id: php_http_encoding_api.h 292841 2009-12-31 08:48:57Z mike $ */
21587 +
21588 +#ifndef PHP_HTTP_ENCODING_API_H
21589 +#define PHP_HTTP_ENCODING_API_H
21590 +
21591 +#define http_encoding_dechunk(e, el, d, dl) _http_encoding_dechunk((e), (el), (d), (dl) TSRMLS_CC)
21592 +PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC);
21593 +
21594 +#define http_encoding_response_start(cl, i) _http_encoding_response_start((cl), (i) TSRMLS_CC)
21595 +PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC);
21596 +
21597 +#ifdef HTTP_HAVE_ZLIB
21598 +
21599 +extern PHP_MINIT_FUNCTION(http_encoding);
21600 +extern PHP_RINIT_FUNCTION(http_encoding);
21601 +extern PHP_RSHUTDOWN_FUNCTION(http_encoding);
21602 +
21603 +typedef enum _http_encoding_type_t {
21604 + HTTP_ENCODING_NONE,
21605 + HTTP_ENCODING_GZIP,
21606 + HTTP_ENCODING_DEFLATE,
21607 +} http_encoding_type;
21608 +
21609 +#define HTTP_INFLATE_ROUNDS 100
21610 +
21611 +#define HTTP_DEFLATE_BUFFER_SIZE_GUESS(S) \
21612 + (((size_t) ((double) S * (double) 1.015)) + 10 + 8 + 4 + 1)
21613 +#define HTTP_INFLATE_BUFFER_SIZE_GUESS(S) \
21614 + (((S) + 1) << 3)
21615 +#define HTTP_INFLATE_BUFFER_SIZE_ALIGN(S) \
21616 + ((S) += (S) >> (3))
21617 +
21618 +#define HTTP_DEFLATE_BUFFER_SIZE 0x8000
21619 +#define HTTP_INFLATE_BUFFER_SIZE 0x1000
21620 +
21621 +#define HTTP_DEFLATE_LEVEL_DEF 0x00000000
21622 +#define HTTP_DEFLATE_LEVEL_MIN 0x00000001
21623 +#define HTTP_DEFLATE_LEVEL_MAX 0x00000009
21624 +#define HTTP_DEFLATE_TYPE_ZLIB 0x00000000
21625 +#define HTTP_DEFLATE_TYPE_GZIP 0x00000010
21626 +#define HTTP_DEFLATE_TYPE_RAW 0x00000020
21627 +#define HTTP_DEFLATE_STRATEGY_DEF 0x00000000
21628 +#define HTTP_DEFLATE_STRATEGY_FILT 0x00000100
21629 +#define HTTP_DEFLATE_STRATEGY_HUFF 0x00000200
21630 +#define HTTP_DEFLATE_STRATEGY_RLE 0x00000300
21631 +#define HTTP_DEFLATE_STRATEGY_FIXED 0x00000400
21632 +
21633 +#define HTTP_DEFLATE_LEVEL_SET(flags, level) \
21634 + switch (flags & 0xf) \
21635 + { \
21636 + default: \
21637 + if ((flags & 0xf) < 10) { \
21638 + level = flags & 0xf; \
21639 + break; \
21640 + } \
21641 + case HTTP_DEFLATE_LEVEL_DEF: \
21642 + level = Z_DEFAULT_COMPRESSION; \
21643 + break; \
21644 + }
21645 +
21646 +#define HTTP_DEFLATE_WBITS_SET(flags, wbits) \
21647 + switch (flags & 0xf0) \
21648 + { \
21649 + case HTTP_DEFLATE_TYPE_GZIP: \
21650 + wbits = HTTP_WINDOW_BITS_GZIP; \
21651 + break; \
21652 + case HTTP_DEFLATE_TYPE_RAW: \
21653 + wbits = HTTP_WINDOW_BITS_RAW; \
21654 + break; \
21655 + default: \
21656 + wbits = HTTP_WINDOW_BITS_ZLIB; \
21657 + break; \
21658 + }
21659 +
21660 +#define HTTP_INFLATE_WBITS_SET(flags, wbits) \
21661 + if (flags & HTTP_INFLATE_TYPE_RAW) { \
21662 + wbits = HTTP_WINDOW_BITS_RAW; \
21663 +} else { \
21664 + wbits = HTTP_WINDOW_BITS_ANY; \
21665 +}
21666 +
21667 +#define HTTP_DEFLATE_STRATEGY_SET(flags, strategy) \
21668 + switch (flags & 0xf00) \
21669 + { \
21670 + case HTTP_DEFLATE_STRATEGY_FILT: \
21671 + strategy = Z_FILTERED; \
21672 + break; \
21673 + case HTTP_DEFLATE_STRATEGY_HUFF: \
21674 + strategy = Z_HUFFMAN_ONLY; \
21675 + break; \
21676 + case HTTP_DEFLATE_STRATEGY_RLE: \
21677 + strategy = Z_RLE; \
21678 + break; \
21679 + case HTTP_DEFLATE_STRATEGY_FIXED: \
21680 + strategy = Z_FIXED; \
21681 + break; \
21682 + default: \
21683 + strategy = Z_DEFAULT_STRATEGY; \
21684 + break; \
21685 + }
21686 +
21687 +#define HTTP_WINDOW_BITS_ZLIB 0x0000000f
21688 +#define HTTP_WINDOW_BITS_GZIP 0x0000001f
21689 +#define HTTP_WINDOW_BITS_ANY 0x0000002f
21690 +#define HTTP_WINDOW_BITS_RAW -0x000000f
21691 +
21692 +#ifndef Z_FIXED
21693 +/* Z_FIXED does not exist prior 1.2.2.2 */
21694 +# define Z_FIXED 0
21695 +#endif
21696 +
21697 +#define HTTP_INFLATE_TYPE_ZLIB 0x00000000
21698 +#define HTTP_INFLATE_TYPE_GZIP 0x00000000
21699 +#define HTTP_INFLATE_TYPE_RAW 0x00000001
21700 +
21701 +#define HTTP_ENCODING_STREAM_FLUSH_NONE 0x00000000
21702 +#define HTTP_ENCODING_STREAM_FLUSH_SYNC 0x00100000
21703 +#define HTTP_ENCODING_STREAM_FLUSH_FULL 0x00200000
21704 +
21705 +#define HTTP_ENCODING_STREAM_FLUSH_FLAG(f) \
21706 + (((f) & HTTP_ENCODING_STREAM_FLUSH_FULL) ? Z_FULL_FLUSH : \
21707 + (((f) & HTTP_ENCODING_STREAM_FLUSH_SYNC) ? Z_SYNC_FLUSH : Z_NO_FLUSH))
21708 +
21709 +#define HTTP_ENCODING_STREAM_PERSISTENT 0x01000000
21710 +
21711 +typedef struct _http_encoding_stream_t {
21712 + z_stream stream;
21713 + int flags;
21714 + void *storage;
21715 +} http_encoding_stream;
21716 +
21717 +#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)
21718 +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);
21719 +#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)
21720 +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);
21721 +
21722 +#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)
21723 +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);
21724 +#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)
21725 +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);
21726 +#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)
21727 +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);
21728 +#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)
21729 +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);
21730 +#define http_encoding_deflate_stream_dtor(s) _http_encoding_deflate_stream_dtor((s) TSRMLS_CC)
21731 +PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
21732 +#define http_encoding_deflate_stream_free(s) _http_encoding_deflate_stream_free((s) TSRMLS_CC)
21733 +PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC);
21734 +
21735 +#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)
21736 +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);
21737 +#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)
21738 +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);
21739 +#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)
21740 +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);
21741 +#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)
21742 +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);
21743 +#define http_encoding_inflate_stream_dtor(s) _http_encoding_inflate_stream_dtor((s) TSRMLS_CC)
21744 +PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC);
21745 +#define http_encoding_inflate_stream_free(s) _http_encoding_inflate_stream_free((s) TSRMLS_CC)
21746 +PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC);
21747 +
21748 +#define http_ob_deflatehandler(o, ol, h, hl, m) _http_ob_deflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC)
21749 +extern void _http_ob_deflatehandler(char *, uint, char **, uint *, int TSRMLS_DC);
21750 +
21751 +#define http_ob_inflatehandler(o, ol, h, hl, m) _http_ob_inflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC)
21752 +extern void _http_ob_inflatehandler(char *, uint, char **, uint *, int TSRMLS_DC);
21753 +
21754 +#endif /* HTTP_HAVE_ZLIB */
21755 +
21756 +#endif
21757 +
21758 +/*
21759 + * Local variables:
21760 + * tab-width: 4
21761 + * c-basic-offset: 4
21762 + * End:
21763 + * vim600: noet sw=4 ts=4 fdm=marker
21764 + * vim<600: noet sw=4 ts=4
21765 + */
21766 --- /dev/null
21767 +++ b/ext/http/php_http_exception_object.h
21768 @@ -0,0 +1,60 @@
21769 +/*
21770 + +--------------------------------------------------------------------+
21771 + | PECL :: http |
21772 + +--------------------------------------------------------------------+
21773 + | Redistribution and use in source and binary forms, with or without |
21774 + | modification, are permitted provided that the conditions mentioned |
21775 + | in the accompanying LICENSE file are met. |
21776 + +--------------------------------------------------------------------+
21777 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21778 + +--------------------------------------------------------------------+
21779 +*/
21780 +
21781 +/* $Id: php_http_exception_object.h 292841 2009-12-31 08:48:57Z mike $ */
21782 +
21783 +#ifndef PHP_HTTP_EXCEPTION_OBJECT_H
21784 +#define PHP_HTTP_EXCEPTION_OBJECT_H
21785 +#ifdef ZEND_ENGINE_2
21786 +
21787 +#include "zend_exceptions.h"
21788 +
21789 +PHP_MINIT_FUNCTION(http_exception_object);
21790 +
21791 +#define HTTP_EX_DEF_CE http_exception_object_ce
21792 +#define HTTP_EX_CE(name) http_ ##name## _exception_object_ce
21793 +
21794 +extern zend_class_entry *http_exception_object_ce;
21795 +extern zend_class_entry *HTTP_EX_CE(runtime);
21796 +extern zend_class_entry *HTTP_EX_CE(header);
21797 +extern zend_class_entry *HTTP_EX_CE(malformed_headers);
21798 +extern zend_class_entry *HTTP_EX_CE(request_method);
21799 +extern zend_class_entry *HTTP_EX_CE(message_type);
21800 +extern zend_class_entry *HTTP_EX_CE(invalid_param);
21801 +extern zend_class_entry *HTTP_EX_CE(encoding);
21802 +extern zend_class_entry *HTTP_EX_CE(request);
21803 +extern zend_class_entry *HTTP_EX_CE(request_pool);
21804 +extern zend_class_entry *HTTP_EX_CE(socket);
21805 +extern zend_class_entry *HTTP_EX_CE(response);
21806 +extern zend_class_entry *HTTP_EX_CE(url);
21807 +extern zend_function_entry http_exception_object_fe[];
21808 +
21809 +#define http_exception_get_default _http_exception_get_default
21810 +extern zend_class_entry *_http_exception_get_default();
21811 +
21812 +#define http_exception_get_for_code(c) _http_exception_get_for_code(c)
21813 +extern zend_class_entry *_http_exception_get_for_code(long code);
21814 +
21815 +PHP_METHOD(HttpException, __toString);
21816 +
21817 +#endif
21818 +#endif
21819 +
21820 +/*
21821 + * Local variables:
21822 + * tab-width: 4
21823 + * c-basic-offset: 4
21824 + * End:
21825 + * vim600: noet sw=4 ts=4 fdm=marker
21826 + * vim<600: noet sw=4 ts=4
21827 + */
21828 +
21829 --- /dev/null
21830 +++ b/ext/http/php_http_filter_api.h
21831 @@ -0,0 +1,33 @@
21832 +/*
21833 + +--------------------------------------------------------------------+
21834 + | PECL :: http |
21835 + +--------------------------------------------------------------------+
21836 + | Redistribution and use in source and binary forms, with or without |
21837 + | modification, are permitted provided that the conditions mentioned |
21838 + | in the accompanying LICENSE file are met. |
21839 + +--------------------------------------------------------------------+
21840 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21841 + +--------------------------------------------------------------------+
21842 +*/
21843 +
21844 +/* $Id: php_http_filter_api.h 292841 2009-12-31 08:48:57Z mike $ */
21845 +
21846 +#ifndef PHP_HTTP_FILTER_API_H
21847 +#define PHP_HTTP_FILTER_API_H
21848 +#ifdef ZEND_ENGINE_2
21849 +
21850 +extern php_stream_filter_factory http_filter_factory;
21851 +PHP_MINIT_FUNCTION(http_filter);
21852 +
21853 +#endif
21854 +#endif
21855 +
21856 +/*
21857 + * Local variables:
21858 + * tab-width: 4
21859 + * c-basic-offset: 4
21860 + * End:
21861 + * vim600: noet sw=4 ts=4 fdm=marker
21862 + * vim<600: noet sw=4 ts=4
21863 + */
21864 +
21865 --- /dev/null
21866 +++ b/ext/http/php_http_headers_api.h
21867 @@ -0,0 +1,77 @@
21868 +/*
21869 + +--------------------------------------------------------------------+
21870 + | PECL :: http |
21871 + +--------------------------------------------------------------------+
21872 + | Redistribution and use in source and binary forms, with or without |
21873 + | modification, are permitted provided that the conditions mentioned |
21874 + | in the accompanying LICENSE file are met. |
21875 + +--------------------------------------------------------------------+
21876 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21877 + +--------------------------------------------------------------------+
21878 +*/
21879 +
21880 +/* $Id: php_http_headers_api.h 300300 2010-06-09 07:29:35Z mike $ */
21881 +
21882 +#ifndef PHP_HTTP_HEADERS_API_H
21883 +#define PHP_HTTP_HEADERS_API_H
21884 +
21885 +#include "php_http_info_api.h"
21886 +
21887 +typedef enum http_range_status_t {
21888 + RANGE_OK,
21889 + RANGE_NO,
21890 + RANGE_ERR
21891 +} http_range_status;
21892 +
21893 +#define http_parse_headers(h, a) _http_parse_headers_ex((h), Z_ARRVAL_P(a), 1, http_info_default_callback, NULL TSRMLS_CC)
21894 +#define http_parse_headers_ex(h, ht, p) _http_parse_headers_ex((h), (ht), (p), http_info_default_callback, NULL TSRMLS_CC)
21895 +#define http_parse_headers_cb(h, ht, p, f, d) _http_parse_headers_ex((h), (ht), (p), (f), (d) TSRMLS_CC)
21896 +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);
21897 +
21898 +typedef char *(*negotiate_func_t)(const char *test, double *quality, HashTable *supported TSRMLS_DC);
21899 +
21900 +#define http_negotiate_language_func _http_negotiate_language_func
21901 +extern char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
21902 +#define http_negotiate_content_type_func _http_negotiate_default_func
21903 +#define http_negotiate_encoding_func _http_negotiate_default_func
21904 +#define http_negotiate_charset_func _http_negotiate_default_func
21905 +#define http_negotiate_default_func _http_negotiate_default_func
21906 +extern char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC);
21907 +
21908 +#define http_negotiate_language(zsupported) http_negotiate_language_ex(Z_ARRVAL_P(zsupported))
21909 +#define http_negotiate_language_ex(supported) http_negotiate_q("HTTP_ACCEPT_LANGUAGE", (supported), http_negotiate_language_func)
21910 +#define http_negotiate_charset(zsupported) http_negotiate_charset_ex(Z_ARRVAL_P(zsupported))
21911 +#define http_negotiate_charset_ex(supported) http_negotiate_q("HTTP_ACCEPT_CHARSET", (supported), http_negotiate_charset_func)
21912 +#define http_negotiate_encoding(zsupported) http_negotiate_encoding_ex(Z_ARRVAL_P(zsupported))
21913 +#define http_negotiate_encoding_ex(supported) http_negotiate_q("HTTP_ACCEPT_ENCODING", (supported), http_negotiate_encoding_func)
21914 +#define http_negotiate_content_type(zsupported) http_negotiate_content_type_ex(Z_ARRVAL_P(zsupported))
21915 +#define http_negotiate_content_type_ex(supported) http_negotiate_q("HTTP_ACCEPT", (supported), http_negotiate_content_type_func)
21916 +#define http_negotiate_q(e, s, n) _http_negotiate_q((e), (s), (n) TSRMLS_CC)
21917 +PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC);
21918 +#define http_negotiate_z(z, s, n) _http_negotiate_z((z), (s), (n) TSRMLS_CC)
21919 +PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC);
21920 +
21921 +#define http_get_request_ranges(r, l) _http_get_request_ranges((r), (l) TSRMLS_CC)
21922 +PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC);
21923 +
21924 +#define http_get_request_headers(h) _http_get_request_headers((h) TSRMLS_CC)
21925 +PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC);
21926 +
21927 +#define http_get_response_headers(h) _http_get_response_headers((h) TSRMLS_CC)
21928 +PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC);
21929 +
21930 +#define http_match_request_header(h, v) http_match_request_header_ex((h), (v), 0)
21931 +#define http_match_request_header_ex(h, v, c) _http_match_request_header_ex((h), (v), (c) TSRMLS_CC)
21932 +PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC);
21933 +
21934 +#endif
21935 +
21936 +/*
21937 + * Local variables:
21938 + * tab-width: 4
21939 + * c-basic-offset: 4
21940 + * End:
21941 + * vim600: noet sw=4 ts=4 fdm=marker
21942 + * vim<600: noet sw=4 ts=4
21943 + */
21944 +
21945 --- /dev/null
21946 +++ b/ext/http/php_http_inflatestream_object.h
21947 @@ -0,0 +1,57 @@
21948 +/*
21949 + +--------------------------------------------------------------------+
21950 + | PECL :: http |
21951 + +--------------------------------------------------------------------+
21952 + | Redistribution and use in source and binary forms, with or without |
21953 + | modification, are permitted provided that the conditions mentioned |
21954 + | in the accompanying LICENSE file are met. |
21955 + +--------------------------------------------------------------------+
21956 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
21957 + +--------------------------------------------------------------------+
21958 +*/
21959 +
21960 +/* $Id: php_http_inflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */
21961 +
21962 +#ifndef PHP_HTTP_INFLATESTREAM_OBJECT_H
21963 +#define PHP_HTTP_INFLATESTREAM_OBJECT_H
21964 +#ifdef HTTP_HAVE_ZLIB
21965 +#ifdef ZEND_ENGINE_2
21966 +
21967 +typedef struct _http_inflatestream_object_t {
21968 + zend_object zo;
21969 + http_encoding_stream *stream;
21970 +} http_inflatestream_object;
21971 +
21972 +extern zend_class_entry *http_inflatestream_object_ce;
21973 +extern zend_function_entry http_inflatestream_object_fe[];
21974 +
21975 +extern PHP_MINIT_FUNCTION(http_inflatestream_object);
21976 +
21977 +#define http_inflatestream_object_new(ce) _http_inflatestream_object_new((ce) TSRMLS_CC)
21978 +extern zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC);
21979 +#define http_inflatestream_object_new_ex(ce, s, ptr) _http_inflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
21980 +extern zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC);
21981 +#define http_inflatestream_object_clone(zobj) _http_inflatestream_object_clone_obj(zobj TSRMLS_CC)
21982 +extern zend_object_value _http_inflatestream_object_clone_obj(zval *object TSRMLS_DC);
21983 +#define http_inflatestream_object_free(o) _http_inflatestream_object_free((o) TSRMLS_CC)
21984 +extern void _http_inflatestream_object_free(zend_object *object TSRMLS_DC);
21985 +
21986 +PHP_METHOD(HttpInflateStream, __construct);
21987 +PHP_METHOD(HttpInflateStream, factory);
21988 +PHP_METHOD(HttpInflateStream, update);
21989 +PHP_METHOD(HttpInflateStream, flush);
21990 +PHP_METHOD(HttpInflateStream, finish);
21991 +
21992 +#endif
21993 +#endif
21994 +#endif
21995 +
21996 +/*
21997 + * Local variables:
21998 + * tab-width: 4
21999 + * c-basic-offset: 4
22000 + * End:
22001 + * vim600: noet sw=4 ts=4 fdm=marker
22002 + * vim<600: noet sw=4 ts=4
22003 + */
22004 +
22005 --- /dev/null
22006 +++ b/ext/http/php_http_info_api.h
22007 @@ -0,0 +1,79 @@
22008 +/*
22009 + +--------------------------------------------------------------------+
22010 + | PECL :: http |
22011 + +--------------------------------------------------------------------+
22012 + | Redistribution and use in source and binary forms, with or without |
22013 + | modification, are permitted provided that the conditions mentioned |
22014 + | in the accompanying LICENSE file are met. |
22015 + +--------------------------------------------------------------------+
22016 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22017 + +--------------------------------------------------------------------+
22018 +*/
22019 +
22020 +/* $Id: php_http_info_api.h 292841 2009-12-31 08:48:57Z mike $ */
22021 +
22022 +#ifndef PHP_HTTP_INFO_API_H
22023 +#define PHP_HTTP_INFO_API_H
22024 +
22025 +#define IS_HTTP_REQUEST 1
22026 +#define IS_HTTP_RESPONSE 2
22027 +
22028 +#define HTTP_INFO(ptr) (ptr)->http.info
22029 +
22030 +#define HTTP_INFO_REQUEST_FMT_ARGS(_http_ptr, _EOL) "%s %s HTTP/%1.1f" _EOL, \
22031 + (_http_ptr)->info.request.method?(_http_ptr)->info.request.method:"UNKNOWN", \
22032 + (_http_ptr)->info.request.url?(_http_ptr)->info.request.url:"/", \
22033 + (_http_ptr)->version>0.0?(_http_ptr)->version:1.1
22034 +
22035 +#define HTTP_INFO_RESPONSE_FMT_ARGS(_http_ptr, _EOL) "HTTP/%1.1f %d%s%s" _EOL, \
22036 + (_http_ptr)->version>0.0?(_http_ptr)->version:1.1, \
22037 + (_http_ptr)->info.response.code?(_http_ptr)->info.response.code:200, \
22038 + (_http_ptr)->info.response.status&&*(_http_ptr)->info.response.status ? " ":"", \
22039 + STR_PTR((_http_ptr)->info.response.status)
22040 +
22041 +typedef struct _http_request_info_t {
22042 + char *method;
22043 + char *url;
22044 +} http_request_info;
22045 +
22046 +typedef struct _http_response_info_t {
22047 + int code;
22048 + char *status;
22049 +} http_response_info;
22050 +
22051 +typedef union _http_info_union_t {
22052 + http_request_info request;
22053 + http_response_info response;
22054 +} http_info_union;
22055 +
22056 +struct http_info {
22057 + http_info_union info;
22058 + double version;
22059 +};
22060 +
22061 +typedef struct _http_info_t {
22062 + struct http_info http;
22063 + int type;
22064 +} http_info;
22065 +
22066 +typedef void (*http_info_callback)(void **callback_data, HashTable **headers, http_info *info TSRMLS_DC);
22067 +
22068 +#define http_info_default_callback _http_info_default_callback
22069 +PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC);
22070 +#define http_info_dtor _http_info_dtor
22071 +PHP_HTTP_API void _http_info_dtor(http_info *info);
22072 +#define http_info_parse(p, i) _http_info_parse_ex((p), (i), 1 TSRMLS_CC)
22073 +#define http_info_parse_ex(p, i, s) _http_info_parse_ex((p), (i), (s) TSRMLS_CC)
22074 +PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info , zend_bool silent TSRMLS_DC);
22075 +
22076 +#endif
22077 +
22078 +/*
22079 + * Local variables:
22080 + * tab-width: 4
22081 + * c-basic-offset: 4
22082 + * End:
22083 + * vim600: noet sw=4 ts=4 fdm=marker
22084 + * vim<600: noet sw=4 ts=4
22085 + */
22086 +
22087 --- /dev/null
22088 +++ b/ext/http/php_http_message_api.h
22089 @@ -0,0 +1,131 @@
22090 +/*
22091 + +--------------------------------------------------------------------+
22092 + | PECL :: http |
22093 + +--------------------------------------------------------------------+
22094 + | Redistribution and use in source and binary forms, with or without |
22095 + | modification, are permitted provided that the conditions mentioned |
22096 + | in the accompanying LICENSE file are met. |
22097 + +--------------------------------------------------------------------+
22098 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22099 + +--------------------------------------------------------------------+
22100 +*/
22101 +
22102 +/* $Id: php_http_message_api.h 292841 2009-12-31 08:48:57Z mike $ */
22103 +
22104 +#ifndef PHP_HTTP_MESSAGE_API_H
22105 +#define PHP_HTTP_MESSAGE_API_H
22106 +
22107 +#include "php_http_info_api.h"
22108 +
22109 +typedef enum _http_message_type_t {
22110 + HTTP_MSG_NONE = 0,
22111 + HTTP_MSG_REQUEST = IS_HTTP_REQUEST,
22112 + HTTP_MSG_RESPONSE = IS_HTTP_RESPONSE,
22113 +} http_message_type;
22114 +
22115 +typedef struct _http_message_t http_message;
22116 +
22117 +struct _http_message_t {
22118 + phpstr body;
22119 + HashTable hdrs;
22120 + http_message_type type;
22121 + struct http_info http;
22122 + http_message *parent;
22123 +};
22124 +
22125 +/* required minimum length of an HTTP message "HTTP/1.1" */
22126 +#define HTTP_MSG_MIN_SIZE 8
22127 +
22128 +/* shorthand for type checks */
22129 +#define HTTP_MSG_TYPE(TYPE, msg) ((msg) && ((msg)->type == HTTP_MSG_ ##TYPE))
22130 +
22131 +#define http_message_new() http_message_init_ex(NULL, 0)
22132 +#define http_message_init(m) http_message_init_ex((m), 0)
22133 +#define http_message_init_ex(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
22134 +#define http_message_init_rel(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)
22135 +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);
22136 +#define http_message_init_env(m, t) _http_message_init_env((m), (t) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
22137 +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);
22138 +
22139 +#define http_message_set_type(m, t) _http_message_set_type((m), (t))
22140 +PHP_HTTP_API void _http_message_set_type(http_message *m, http_message_type t);
22141 +
22142 +#define http_message_set_info(m, i) _http_message_set_info((m), (i))
22143 +PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info);
22144 +
22145 +#define http_message_header(m, h) _http_message_header_ex((m), (h), sizeof(h), 1)
22146 +#define http_message_header_ex _http_message_header_ex
22147 +static inline zval *_http_message_header_ex(http_message *msg, char *key_str, size_t key_len, int join)
22148 +{
22149 + zval **header;
22150 + if (SUCCESS == zend_hash_find(&msg->hdrs, key_str, key_len, (void *) &header)) {
22151 + if (join && Z_TYPE_PP(header) == IS_ARRAY) {
22152 + zval *header_str, **val;
22153 + HashPosition pos;
22154 + phpstr str;
22155 +
22156 + phpstr_init(&str);
22157 + MAKE_STD_ZVAL(header_str);
22158 + FOREACH_VAL(pos, *header, val) {
22159 + phpstr_appendf(&str, PHPSTR_LEN(&str) ? ", %s":"%s", Z_STRVAL_PP(val));
22160 + }
22161 + phpstr_fix(&str);
22162 + ZVAL_STRINGL(header_str, PHPSTR_VAL(&str), PHPSTR_LEN(&str), 0);
22163 + return header_str;
22164 + } else {
22165 + ZVAL_ADDREF(*header);
22166 + return *header;
22167 + }
22168 + }
22169 + return NULL;
22170 +}
22171 +
22172 +#define http_message_count(c, m) \
22173 +{ \
22174 + http_message *__tmp_msg = (m); \
22175 + for (c = 0; __tmp_msg; __tmp_msg = __tmp_msg->parent, ++(c)); \
22176 +}
22177 +
22178 +#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l))
22179 +#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)
22180 +#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)
22181 +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);
22182 +
22183 +#define http_message_tostring(m, s, l) _http_message_tostring((m), (s), (l))
22184 +PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length);
22185 +
22186 +#define http_message_serialize(m, s, l) _http_message_serialize((m), (s), (l))
22187 +PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length);
22188 +
22189 +#define http_message_reverse(m) _http_message_reverse(m)
22190 +PHP_HTTP_API http_message *_http_message_reverse(http_message *msg);
22191 +
22192 +#define http_message_interconnect(m1, m2) _http_message_interconnect((m1), (m2))
22193 +PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2);
22194 +
22195 +#define http_message_tostruct_recursive(m, s) _http_message_tostruct_recursive((m), (s) TSRMLS_CC)
22196 +PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *strct TSRMLS_DC);
22197 +
22198 +#define http_message_send(m) _http_message_send((m) TSRMLS_CC)
22199 +PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC);
22200 +
22201 +#define http_message_dup(m) _http_message_dup((m) TSRMLS_CC)
22202 +PHP_HTTP_API http_message *_http_message_dup(http_message *msg TSRMLS_DC);
22203 +
22204 +#define http_message_dtor(m) _http_message_dtor((m))
22205 +PHP_HTTP_API void _http_message_dtor(http_message *message);
22206 +
22207 +#define http_message_free(m) _http_message_free((m))
22208 +PHP_HTTP_API void _http_message_free(http_message **message);
22209 +
22210 +#endif
22211 +
22212 +/*
22213 + * Local variables:
22214 + * tab-width: 4
22215 + * c-basic-offset: 4
22216 + * End:
22217 + * vim600: noet sw=4 ts=4 fdm=marker
22218 + * vim<600: noet sw=4 ts=4
22219 + */
22220 +
22221 --- /dev/null
22222 +++ b/ext/http/php_http_message_object.h
22223 @@ -0,0 +1,115 @@
22224 +/*
22225 + +--------------------------------------------------------------------+
22226 + | PECL :: http |
22227 + +--------------------------------------------------------------------+
22228 + | Redistribution and use in source and binary forms, with or without |
22229 + | modification, are permitted provided that the conditions mentioned |
22230 + | in the accompanying LICENSE file are met. |
22231 + +--------------------------------------------------------------------+
22232 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22233 + +--------------------------------------------------------------------+
22234 +*/
22235 +
22236 +/* $Id: php_http_message_object.h 298590 2010-04-26 11:46:35Z mike $ */
22237 +
22238 +#ifndef PHP_HTTP_MESSAGE_OBJECT_H
22239 +#define PHP_HTTP_MESSAGE_OBJECT_H
22240 +#ifdef ZEND_ENGINE_2
22241 +
22242 +typedef struct _http_message_object_t {
22243 + zend_object zo;
22244 + http_message *message;
22245 + zend_object_value parent;
22246 + zval *iterator;
22247 +} http_message_object;
22248 +
22249 +extern zend_class_entry *http_message_object_ce;
22250 +extern zend_function_entry http_message_object_fe[];
22251 +
22252 +extern PHP_MINIT_FUNCTION(http_message_object);
22253 +extern PHP_MSHUTDOWN_FUNCTION(http_message_object);
22254 +
22255 +#define http_message_object_prepend(o, p) http_message_object_prepend_ex((o), (p), 1)
22256 +#define http_message_object_prepend_ex(o, p, t) _http_message_object_prepend_ex((o), (p), (t) TSRMLS_CC)
22257 +extern void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC);
22258 +
22259 +#define http_message_object_reverse(t, r) _http_message_object_reverse((t), (r) TSRMLS_CC)
22260 +extern void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC);
22261 +
22262 +#define http_message_object_new(ce) _http_message_object_new((ce) TSRMLS_CC)
22263 +extern zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC);
22264 +#define http_message_object_new_ex(ce, msg, ptr) _http_message_object_new_ex((ce), (msg), (ptr) TSRMLS_CC)
22265 +extern zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC);
22266 +#define http_message_object_clone(zobj) _http_message_object_clone_obj(zobj TSRMLS_CC)
22267 +extern zend_object_value _http_message_object_clone_obj(zval *object TSRMLS_DC);
22268 +#define http_message_object_free(o) _http_message_object_free((o) TSRMLS_CC)
22269 +extern void _http_message_object_free(zend_object *object TSRMLS_DC);
22270 +
22271 +#define HTTP_MSG_CHECK_OBJ(obj, dofail) \
22272 + if (!(obj)->message) { \
22273 + http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is empty"); \
22274 + dofail; \
22275 + }
22276 +#define HTTP_MSG_CHECK_STD() HTTP_MSG_CHECK_OBJ(obj, RETURN_FALSE)
22277 +
22278 +#define HTTP_MSG_INIT_OBJ(obj) \
22279 + if (!(obj)->message) { \
22280 + (obj)->message = http_message_new(); \
22281 + }
22282 +#define HTTP_MSG_INIT_STD() HTTP_MSG_INIT_OBJ(obj)
22283 +
22284 +PHP_METHOD(HttpMessage, __construct);
22285 +PHP_METHOD(HttpMessage, getBody);
22286 +PHP_METHOD(HttpMessage, setBody);
22287 +PHP_METHOD(HttpMessage, getHeader);
22288 +PHP_METHOD(HttpMessage, getHeaders);
22289 +PHP_METHOD(HttpMessage, setHeaders);
22290 +PHP_METHOD(HttpMessage, addHeaders);
22291 +PHP_METHOD(HttpMessage, getType);
22292 +PHP_METHOD(HttpMessage, setType);
22293 +PHP_METHOD(HttpMessage, getInfo);
22294 +PHP_METHOD(HttpMessage, setInfo);
22295 +PHP_METHOD(HttpMessage, getResponseCode);
22296 +PHP_METHOD(HttpMessage, setResponseCode);
22297 +PHP_METHOD(HttpMessage, getResponseStatus);
22298 +PHP_METHOD(HttpMessage, setResponseStatus);
22299 +PHP_METHOD(HttpMessage, getRequestMethod);
22300 +PHP_METHOD(HttpMessage, setRequestMethod);
22301 +PHP_METHOD(HttpMessage, getRequestUrl);
22302 +PHP_METHOD(HttpMessage, setRequestUrl);
22303 +PHP_METHOD(HttpMessage, getHttpVersion);
22304 +PHP_METHOD(HttpMessage, setHttpVersion);
22305 +PHP_METHOD(HttpMessage, guessContentType);
22306 +PHP_METHOD(HttpMessage, getParentMessage);
22307 +PHP_METHOD(HttpMessage, send);
22308 +PHP_METHOD(HttpMessage, toString);
22309 +PHP_METHOD(HttpMessage, toMessageTypeObject);
22310 +
22311 +PHP_METHOD(HttpMessage, count);
22312 +PHP_METHOD(HttpMessage, serialize);
22313 +PHP_METHOD(HttpMessage, unserialize);
22314 +PHP_METHOD(HttpMessage, rewind);
22315 +PHP_METHOD(HttpMessage, valid);
22316 +PHP_METHOD(HttpMessage, current);
22317 +PHP_METHOD(HttpMessage, key);
22318 +PHP_METHOD(HttpMessage, next);
22319 +
22320 +PHP_METHOD(HttpMessage, factory);
22321 +PHP_METHOD(HttpMessage, fromEnv);
22322 +
22323 +PHP_METHOD(HttpMessage, detach);
22324 +PHP_METHOD(HttpMessage, prepend);
22325 +PHP_METHOD(HttpMessage, reverse);
22326 +
22327 +#endif
22328 +#endif
22329 +
22330 +/*
22331 + * Local variables:
22332 + * tab-width: 4
22333 + * c-basic-offset: 4
22334 + * End:
22335 + * vim600: noet sw=4 ts=4 fdm=marker
22336 + * vim<600: noet sw=4 ts=4
22337 + */
22338 +
22339 --- /dev/null
22340 +++ b/ext/http/php_http_persistent_handle_api.h
22341 @@ -0,0 +1,58 @@
22342 +/*
22343 + +--------------------------------------------------------------------+
22344 + | PECL :: http |
22345 + +--------------------------------------------------------------------+
22346 + | Redistribution and use in source and binary forms, with or without |
22347 + | modification, are permitted provided that the conditions mentioned |
22348 + | in the accompanying LICENSE file are met. |
22349 + +--------------------------------------------------------------------+
22350 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22351 + +--------------------------------------------------------------------+
22352 +*/
22353 +
22354 +/* $Id: php_http_persistent_handle_api.h 292841 2009-12-31 08:48:57Z mike $ */
22355 +
22356 +#ifndef HTTP_PERSISTENT_HANDLE_H
22357 +#define HTTP_PERSISTENT_HANDLE_H
22358 +
22359 +typedef void *(*http_persistent_handle_ctor)(void);
22360 +typedef void (*http_persistent_handle_dtor)(void *handle);
22361 +typedef void *(*http_persistent_handle_copy)(void *handle);
22362 +
22363 +PHP_MINIT_FUNCTION(http_persistent_handle);
22364 +PHP_MSHUTDOWN_FUNCTION(http_persistent_handle);
22365 +
22366 +#define http_persistent_handle_provide(n, c, d, cc) _http_persistent_handle_provide_ex((n), strlen(n), (c), (d), (cc))
22367 +#define http_persistent_handle_provide_ex(n, l, c, d, cc) _http_persistent_handle_provide_ex((n), (l), (c), (d), (cc))
22368 +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);
22369 +
22370 +#define http_persistent_handle_cleanup(n, c) _http_persistent_handle_cleanup_ex((n), strlen(n), (c) TSRMLS_CC)
22371 +#define http_persistent_handle_cleanup_ex(n, l,c ) _http_persistent_handle_cleanup_ex((n), (l), (c) TSRMLS_CC)
22372 +PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC);
22373 +
22374 +#define http_persistent_handle_statall() _http_persistent_handle_statall_ex(NULL TSRMLS_CC)
22375 +#define http_persistent_handle_statall_ex(ht) _http_persistent_handle_statall_ex((ht) TSRMLS_CC)
22376 +PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC);
22377 +
22378 +#define http_persistent_handle_acquire(n, h) _http_persistent_handle_acquire_ex((n), strlen(n), (h) TSRMLS_CC)
22379 +#define http_persistent_handle_acquire_ex(n, l, h) _http_persistent_handle_acquire_ex((n), (l), (h) TSRMLS_CC)
22380 +PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
22381 +
22382 +#define http_persistent_handle_release(n, h) _http_persistent_handle_release_ex((n), strlen(n), (h) TSRMLS_CC)
22383 +#define http_persistent_handle_release_ex(n, l, h) _http_persistent_handle_release_ex((n), (l), (h) TSRMLS_CC)
22384 +PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC);
22385 +
22386 +#define http_persistent_handle_accrete(n, oh, nh) _http_persistent_handle_accrete_ex((n), strlen(n), (oh), (nh) TSRMLS_CC)
22387 +#define http_persistent_handle_accrete_ex(n, l, oh, nh) _http_persistent_handle_accrete_ex((n), (l), (oh), (nh) TSRMLS_CC)
22388 +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);
22389 +
22390 +#endif /* HTTP_PERSISTENT_HANDLE_H */
22391 +
22392 +/*
22393 + * Local variables:
22394 + * tab-width: 4
22395 + * c-basic-offset: 4
22396 + * End:
22397 + * vim600: noet sw=4 ts=4 fdm=marker
22398 + * vim<600: noet sw=4 ts=4
22399 + */
22400 --- /dev/null
22401 +++ b/ext/http/php_http_querystring_api.h
22402 @@ -0,0 +1,38 @@
22403 +/*
22404 + +--------------------------------------------------------------------+
22405 + | PECL :: http |
22406 + +--------------------------------------------------------------------+
22407 + | Redistribution and use in source and binary forms, with or without |
22408 + | modification, are permitted provided that the conditions mentioned |
22409 + | in the accompanying LICENSE file are met. |
22410 + +--------------------------------------------------------------------+
22411 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22412 + +--------------------------------------------------------------------+
22413 +*/
22414 +
22415 +/* $Id: php_http_querystring_api.h 292841 2009-12-31 08:48:57Z mike $ */
22416 +
22417 +#ifndef PHP_HTTP_QUERYSTRING_API_H
22418 +#define PHP_HTTP_QUERYSTRING_API_H
22419 +
22420 +#ifdef HTTP_HAVE_ICONV
22421 +#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC)
22422 +PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC);
22423 +#endif
22424 +
22425 +#define http_querystring_update(qa, qs) _http_querystring_update((qa), (qs) TSRMLS_CC)
22426 +PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC);
22427 +
22428 +#define http_querystring_modify(q, p) _http_querystring_modify((q), (p) TSRMLS_CC)
22429 +PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC);
22430 +
22431 +#endif
22432 +
22433 +/*
22434 + * Local variables:
22435 + * tab-width: 4
22436 + * c-basic-offset: 4
22437 + * End:
22438 + * vim600: noet sw=4 ts=4 fdm=marker
22439 + * vim<600: noet sw=4 ts=4
22440 + */
22441 --- /dev/null
22442 +++ b/ext/http/php_http_querystring_object.h
22443 @@ -0,0 +1,78 @@
22444 +/*
22445 + +--------------------------------------------------------------------+
22446 + | PECL :: http |
22447 + +--------------------------------------------------------------------+
22448 + | Redistribution and use in source and binary forms, with or without |
22449 + | modification, are permitted provided that the conditions mentioned |
22450 + | in the accompanying LICENSE file are met. |
22451 + +--------------------------------------------------------------------+
22452 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22453 + +--------------------------------------------------------------------+
22454 +*/
22455 +
22456 +/* $Id: php_http_querystring_object.h 292841 2009-12-31 08:48:57Z mike $ */
22457 +
22458 +#ifndef PHP_HTTP_QUERYSTRING_OBJECT_H
22459 +#define PHP_HTTP_QUERYSTRING_OBJECT_H
22460 +#ifdef ZEND_ENGINE_2
22461 +
22462 +typedef struct _http_querystring_object_t {
22463 + zend_object zo;
22464 +} http_querystring_object;
22465 +
22466 +#define HTTP_QUERYSTRING_TYPE_BOOL IS_BOOL
22467 +#define HTTP_QUERYSTRING_TYPE_INT IS_LONG
22468 +#define HTTP_QUERYSTRING_TYPE_FLOAT IS_DOUBLE
22469 +#define HTTP_QUERYSTRING_TYPE_STRING IS_STRING
22470 +#define HTTP_QUERYSTRING_TYPE_ARRAY IS_ARRAY
22471 +#define HTTP_QUERYSTRING_TYPE_OBJECT IS_OBJECT
22472 +
22473 +extern zend_class_entry *http_querystring_object_ce;
22474 +extern zend_function_entry http_querystring_object_fe[];
22475 +
22476 +extern PHP_MINIT_FUNCTION(http_querystring_object);
22477 +
22478 +#define http_querystring_object_new(ce) _http_querystring_object_new((ce) TSRMLS_CC)
22479 +extern zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC);
22480 +#define http_querystring_object_new_ex(ce, n, ptr) _http_querystring_object_new_ex((ce), (n), (ptr) TSRMLS_CC)
22481 +extern zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC);
22482 +#define http_querystring_object_free(o) _http_querystring_object_free((o) TSRMLS_CC)
22483 +extern void _http_querystring_object_free(zend_object *object TSRMLS_DC);
22484 +
22485 +PHP_METHOD(HttpQueryString, __construct);
22486 +PHP_METHOD(HttpQueryString, toString);
22487 +PHP_METHOD(HttpQueryString, toArray);
22488 +PHP_METHOD(HttpQueryString, get);
22489 +PHP_METHOD(HttpQueryString, set);
22490 +PHP_METHOD(HttpQueryString, mod);
22491 +PHP_METHOD(HttpQueryString, getBool);
22492 +PHP_METHOD(HttpQueryString, getInt);
22493 +PHP_METHOD(HttpQueryString, getFloat);
22494 +PHP_METHOD(HttpQueryString, getString);
22495 +PHP_METHOD(HttpQueryString, getArray);
22496 +PHP_METHOD(HttpQueryString, getObject);
22497 +#ifdef HTTP_HAVE_ICONV
22498 +PHP_METHOD(HttpQueryString, xlate);
22499 +#endif
22500 +PHP_METHOD(HttpQueryString, factory);
22501 +#ifndef WONKY
22502 +PHP_METHOD(HttpQueryString, singleton);
22503 +#endif
22504 +PHP_METHOD(HttpQueryString, serialize);
22505 +PHP_METHOD(HttpQueryString, unserialize);
22506 +PHP_METHOD(HttpQueryString, offsetGet);
22507 +PHP_METHOD(HttpQueryString, offsetSet);
22508 +PHP_METHOD(HttpQueryString, offsetExists);
22509 +PHP_METHOD(HttpQueryString, offsetUnset);
22510 +#endif
22511 +#endif
22512 +
22513 +/*
22514 + * Local variables:
22515 + * tab-width: 4
22516 + * c-basic-offset: 4
22517 + * End:
22518 + * vim600: noet sw=4 ts=4 fdm=marker
22519 + * vim<600: noet sw=4 ts=4
22520 + */
22521 +
22522 --- /dev/null
22523 +++ b/ext/http/php_http_request_api.h
22524 @@ -0,0 +1,144 @@
22525 +/*
22526 + +--------------------------------------------------------------------+
22527 + | PECL :: http |
22528 + +--------------------------------------------------------------------+
22529 + | Redistribution and use in source and binary forms, with or without |
22530 + | modification, are permitted provided that the conditions mentioned |
22531 + | in the accompanying LICENSE file are met. |
22532 + +--------------------------------------------------------------------+
22533 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22534 + +--------------------------------------------------------------------+
22535 +*/
22536 +
22537 +/* $Id: php_http_request_api.h 292841 2009-12-31 08:48:57Z mike $ */
22538 +
22539 +#ifndef PHP_HTTP_REQUEST_API_H
22540 +#define PHP_HTTP_REQUEST_API_H
22541 +
22542 +#ifdef HTTP_HAVE_CURL
22543 +
22544 +#include "php_http_request_body_api.h"
22545 +#include "php_http_request_method_api.h"
22546 +
22547 +extern PHP_MINIT_FUNCTION(http_request);
22548 +extern PHP_MSHUTDOWN_FUNCTION(http_request);
22549 +
22550 +typedef struct _http_request_t {
22551 + CURL *ch;
22552 + char *url;
22553 + http_request_method meth;
22554 + http_request_body *body;
22555 +
22556 + struct {
22557 + curl_infotype last_type;
22558 + phpstr request;
22559 + phpstr response;
22560 + } conv;
22561 +
22562 + struct {
22563 + phpstr cookies;
22564 + HashTable options;
22565 + struct curl_slist *headers;
22566 + } _cache;
22567 +
22568 + struct {
22569 + uint count;
22570 + double delay;
22571 + } _retry;
22572 +
22573 + char _error[CURL_ERROR_SIZE+1];
22574 + zval *_progress_callback;
22575 +
22576 +#ifdef ZTS
22577 + void ***tsrm_ls;
22578 +#endif
22579 +
22580 + uint _in_progress_cb:1;
22581 +
22582 +} http_request;
22583 +
22584 +#ifndef pestrndup
22585 +# define pestrndup(s,l,p) _pestrndup((s),(l),(p))
22586 +static inline void *_pestrndup(const void *s, size_t l, int p)
22587 +{
22588 + void *d = pemalloc(l+1, p);
22589 + memcpy(d, s, l);
22590 + ((char *) d)[l] = '\0';
22591 + return d;
22592 +}
22593 +#endif
22594 +
22595 +/* CURLOPT_PRIVATE storage living as long as a CURL handle */
22596 +typedef struct _http_request_storage_t {
22597 + char *url;
22598 + char *cookiestore;
22599 + char errorbuffer[CURL_ERROR_SIZE];
22600 +} http_request_storage;
22601 +
22602 +static inline http_request_storage *http_request_storage_get(CURL *ch)
22603 +{
22604 + http_request_storage *st = NULL;
22605 + curl_easy_getinfo(ch, CURLINFO_PRIVATE, &st);
22606 + return st;
22607 +}
22608 +
22609 +#define http_curl_init(r) http_curl_init_ex(NULL, (r))
22610 +#define http_curl_init_ex(c, r) _http_curl_init_ex((c), (r) TSRMLS_CC)
22611 +PHP_HTTP_API CURL *_http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC);
22612 +
22613 +#define http_curl_free(c) _http_curl_free((c) TSRMLS_CC)
22614 +PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC);
22615 +
22616 +#define http_curl_copy(c) _http_curl_copy((c) TSRMLS_CC)
22617 +PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC);
22618 +
22619 +#define http_request_new() _http_request_init_ex(NULL, NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
22620 +#define http_request_init(r) _http_request_init_ex((r), NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC)
22621 +#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)
22622 +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);
22623 +
22624 +#define http_request_dtor(r) _http_request_dtor((r))
22625 +PHP_HTTP_API void _http_request_dtor(http_request *request);
22626 +
22627 +#define http_request_free(r) _http_request_free((r))
22628 +PHP_HTTP_API void _http_request_free(http_request **request);
22629 +
22630 +#define http_request_reset(r) _http_request_reset(r)
22631 +PHP_HTTP_API void _http_request_reset(http_request *r);
22632 +
22633 +#define http_request_enable_cookies(r) _http_request_enable_cookies(r)
22634 +PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request);
22635 +
22636 +#define http_request_reset_cookies(r, s) _http_request_reset_cookies((r), (s))
22637 +PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only);
22638 +
22639 +#define http_request_flush_cookies(r) _http_request_flush_cookies(r)
22640 +PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request);
22641 +
22642 +#define http_request_defaults(r) _http_request_defaults(r)
22643 +PHP_HTTP_API void _http_request_defaults(http_request *request);
22644 +
22645 +#define http_request_prepare(r, o) _http_request_prepare((r), (o))
22646 +PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options);
22647 +
22648 +#define http_request_exec(r) _http_request_exec((r))
22649 +PHP_HTTP_API void _http_request_exec(http_request *request);
22650 +
22651 +#define http_request_info(r, i) _http_request_info((r), (i))
22652 +PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info);
22653 +
22654 +#define http_request_set_progress_callback(r, cb) _http_request_set_progress_callback((r), (cb))
22655 +PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb);
22656 +
22657 +#endif
22658 +#endif
22659 +
22660 +/*
22661 + * Local variables:
22662 + * tab-width: 4
22663 + * c-basic-offset: 4
22664 + * End:
22665 + * vim600: noet sw=4 ts=4 fdm=marker
22666 + * vim<600: noet sw=4 ts=4
22667 + */
22668 +
22669 --- /dev/null
22670 +++ b/ext/http/php_http_request_body_api.h
22671 @@ -0,0 +1,62 @@
22672 +/*
22673 + +--------------------------------------------------------------------+
22674 + | PECL :: http |
22675 + +--------------------------------------------------------------------+
22676 + | Redistribution and use in source and binary forms, with or without |
22677 + | modification, are permitted provided that the conditions mentioned |
22678 + | in the accompanying LICENSE file are met. |
22679 + +--------------------------------------------------------------------+
22680 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22681 + +--------------------------------------------------------------------+
22682 +*/
22683 +
22684 +/* $Id: php_http_request_body_api.h 292841 2009-12-31 08:48:57Z mike $ */
22685 +
22686 +#ifndef PHP_HTTP_REQUEST_BODY_API_H
22687 +#define PHP_HTTP_REQUEST_BODY_API_H
22688 +
22689 +#ifdef HTTP_HAVE_CURL
22690 +
22691 +#define HTTP_REQUEST_BODY_EMPTY 0
22692 +#define HTTP_REQUEST_BODY_CSTRING 1
22693 +#define HTTP_REQUEST_BODY_CURLPOST 2
22694 +#define HTTP_REQUEST_BODY_UPLOADFILE 3
22695 +typedef struct _http_request_body_t {
22696 + void *data;
22697 + size_t size;
22698 + uint type:3;
22699 + uint free:1;
22700 + uint priv:28;
22701 +} http_request_body;
22702 +
22703 +
22704 +#define http_request_body_new() http_request_body_init(NULL)
22705 +#define http_request_body_init(b) http_request_body_init_ex((b), 0, NULL, 0, 0)
22706 +#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)
22707 +#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)
22708 +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);
22709 +
22710 +#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)
22711 +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);
22712 +
22713 +#define http_request_body_encode(b, s, l) _http_request_body_encode((b), (s), (l) TSRMLS_CC)
22714 +PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC);
22715 +
22716 +#define http_request_body_dtor(b) _http_request_body_dtor((b) TSRMLS_CC)
22717 +PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC);
22718 +
22719 +#define http_request_body_free(b) _http_request_body_free((b) TSRMLS_CC)
22720 +PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC);
22721 +
22722 +#endif
22723 +#endif
22724 +
22725 +/*
22726 + * Local variables:
22727 + * tab-width: 4
22728 + * c-basic-offset: 4
22729 + * End:
22730 + * vim600: noet sw=4 ts=4 fdm=marker
22731 + * vim<600: noet sw=4 ts=4
22732 + */
22733 +
22734 --- /dev/null
22735 +++ b/ext/http/php_http_request_datashare_api.h
22736 @@ -0,0 +1,88 @@
22737 +/*
22738 + +--------------------------------------------------------------------+
22739 + | PECL :: http |
22740 + +--------------------------------------------------------------------+
22741 + | Redistribution and use in source and binary forms, with or without |
22742 + | modification, are permitted provided that the conditions mentioned |
22743 + | in the accompanying LICENSE file are met. |
22744 + +--------------------------------------------------------------------+
22745 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22746 + +--------------------------------------------------------------------+
22747 +*/
22748 +
22749 +/* $Id: php_http_request_datashare_api.h 292841 2009-12-31 08:48:57Z mike $ */
22750 +
22751 +#ifndef PHP_HTTP_REQUEST_DATASHARE_API_H
22752 +#define PHP_HTTP_REQUEST_DATASHARE_API_H
22753 +#ifdef HTTP_HAVE_CURL
22754 +#ifdef ZEND_ENGINE_2
22755 +
22756 +#ifdef ZTS
22757 +typedef struct _http_request_datashare_lock_t {
22758 + CURL *ch;
22759 + MUTEX_T mx;
22760 +} http_request_datashare_lock;
22761 +
22762 +typedef union _http_request_datashare_handle_t {
22763 + zend_llist *list;
22764 + http_request_datashare_lock *locks;
22765 +} http_request_datashare_handle;
22766 +#else
22767 +typedef struct _http_request_datashare_handle_t {
22768 + zend_llist *list;
22769 +} http_request_datashare_handle;
22770 +#endif
22771 +
22772 +typedef struct _http_request_datashare_t {
22773 + CURLSH *ch;
22774 + zend_bool persistent;
22775 + http_request_datashare_handle handle;
22776 +} http_request_datashare;
22777 +
22778 +#define HTTP_RSHARE_HANDLES(s) ((s)->persistent ? &HTTP_G->request.datashare.handles : (s)->handle.list)
22779 +
22780 +#define http_request_datashare_global_get _http_request_datashare_global_get
22781 +extern http_request_datashare *_http_request_datashare_global_get(void);
22782 +
22783 +extern PHP_MINIT_FUNCTION(http_request_datashare);
22784 +extern PHP_MSHUTDOWN_FUNCTION(http_request_datashare);
22785 +extern PHP_RINIT_FUNCTION(http_request_datashare);
22786 +extern PHP_RSHUTDOWN_FUNCTION(http_request_datashare);
22787 +
22788 +#define http_request_datashare_new() _http_request_datashare_init_ex(NULL, 0 TSRMLS_CC)
22789 +#define http_request_datashare_init(s) _http_request_datashare_init_ex((s), 0 TSRMLS_CC)
22790 +#define http_request_datashare_init_ex(s, p) _http_request_datashare_init_ex((s), (p) TSRMLS_CC)
22791 +PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC);
22792 +
22793 +#define http_request_datashare_attach(s, r) _http_request_datashare_attach((s), (r) TSRMLS_CC)
22794 +PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC);
22795 +
22796 +#define http_request_datashare_detach(s, r) _http_request_datashare_detach((s), (r) TSRMLS_CC)
22797 +PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC);
22798 +
22799 +#define http_request_datashare_detach_all(s) _http_request_datashare_detach_all((s) TSRMLS_CC)
22800 +PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC);
22801 +
22802 +#define http_request_datashare_dtor(s) _http_request_datashare_dtor((s) TSRMLS_CC)
22803 +PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC);
22804 +
22805 +#define http_request_datashare_free(s) _http_request_datashare_free((s) TSRMLS_CC)
22806 +PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC);
22807 +
22808 +#define http_request_datashare_set(s, o, l, e) _http_request_datashare_set((s), (o), (l), (e) TSRMLS_CC)
22809 +PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC);
22810 +
22811 +
22812 +#endif
22813 +#endif
22814 +#endif
22815 +
22816 +/*
22817 + * Local variables:
22818 + * tab-width: 4
22819 + * c-basic-offset: 4
22820 + * End:
22821 + * vim600: noet sw=4 ts=4 fdm=marker
22822 + * vim<600: noet sw=4 ts=4
22823 + */
22824 +
22825 --- /dev/null
22826 +++ b/ext/http/php_http_request_int.h
22827 @@ -0,0 +1,72 @@
22828 +/*
22829 + +--------------------------------------------------------------------+
22830 + | PECL :: http |
22831 + +--------------------------------------------------------------------+
22832 + | Redistribution and use in source and binary forms, with or without |
22833 + | modification, are permitted provided that the conditions mentioned |
22834 + | in the accompanying LICENSE file are met. |
22835 + +--------------------------------------------------------------------+
22836 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22837 + +--------------------------------------------------------------------+
22838 +*/
22839 +
22840 +/* $Id: php_http_request_int.h 292841 2009-12-31 08:48:57Z mike $ */
22841 +
22842 +#if defined(ZTS) && defined(HTTP_HAVE_SSL)
22843 +# ifdef PHP_WIN32
22844 +# define HTTP_NEED_OPENSSL_TSL
22845 +# include <openssl/crypto.h>
22846 +# else /* !PHP_WIN32 */
22847 +# if defined(HTTP_HAVE_OPENSSL)
22848 +# define HTTP_NEED_OPENSSL_TSL
22849 +# include <openssl/crypto.h>
22850 +# elif defined(HTTP_HAVE_GNUTLS)
22851 +# define HTTP_NEED_GNUTLS_TSL
22852 +# include <gcrypt.h>
22853 +# else
22854 +# warning \
22855 + "libcurl was compiled with SSL support, but configure could not determine which" \
22856 + "library was used; thus no SSL crypto locking callbacks will be set, which may " \
22857 + "cause random crashes on SSL requests"
22858 +# endif /* HTTP_HAVE_OPENSSL || HTTP_HAVE_GNUTLS */
22859 +# endif /* PHP_WIN32 */
22860 +#endif /* ZTS && HTTP_HAVE_SSL */
22861 +
22862 +#define HTTP_CURL_OPT(OPTION, p) curl_easy_setopt((request->ch), OPTION, (p))
22863 +
22864 +#define HTTP_CURL_OPT_STRING(OPTION, ldiff, obdc) \
22865 + { \
22866 + char *K = #OPTION; \
22867 + HTTP_CURL_OPT_STRING_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION, obdc); \
22868 + }
22869 +#define HTTP_CURL_OPT_STRING_EX(keyname, optname, obdc) \
22870 + if (!strcasecmp(key.str, keyname)) { \
22871 + zval *copy = http_request_option_cache_ex(request, keyname, strlen(keyname)+1, 0, http_zsep(IS_STRING, *param)); \
22872 + if (obdc) { \
22873 + HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(copy), return FAILURE); \
22874 + } \
22875 + HTTP_CURL_OPT(optname, Z_STRVAL_P(copy)); \
22876 + zval_ptr_dtor(&copy); \
22877 + continue; \
22878 + }
22879 +#define HTTP_CURL_OPT_LONG(OPTION, ldiff) \
22880 + { \
22881 + char *K = #OPTION; \
22882 + HTTP_CURL_OPT_LONG_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION); \
22883 + }
22884 +#define HTTP_CURL_OPT_LONG_EX(keyname, optname) \
22885 + if (!strcasecmp(key.str, keyname)) { \
22886 + zval *copy = http_zsep(IS_LONG, *param); \
22887 + HTTP_CURL_OPT(optname, Z_LVAL_P(copy)); \
22888 + zval_ptr_dtor(&copy); \
22889 + continue; \
22890 + }
22891 +
22892 +/*
22893 + * Local variables:
22894 + * tab-width: 4
22895 + * c-basic-offset: 4
22896 + * End:
22897 + * vim600: noet sw=4 ts=4 fdm=marker
22898 + * vim<600: noet sw=4 ts=4
22899 + */
22900 --- /dev/null
22901 +++ b/ext/http/php_http_request_method_api.h
22902 @@ -0,0 +1,85 @@
22903 +/*
22904 + +--------------------------------------------------------------------+
22905 + | PECL :: http |
22906 + +--------------------------------------------------------------------+
22907 + | Redistribution and use in source and binary forms, with or without |
22908 + | modification, are permitted provided that the conditions mentioned |
22909 + | in the accompanying LICENSE file are met. |
22910 + +--------------------------------------------------------------------+
22911 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
22912 + +--------------------------------------------------------------------+
22913 +*/
22914 +
22915 +/* $Id: php_http_request_method_api.h 292841 2009-12-31 08:48:57Z mike $ */
22916 +
22917 +#ifndef PHP_HTTP_REQUEST_METHOD_API_H
22918 +#define PHP_HTTP_REQUEST_METHOD_API_H
22919 +
22920 +typedef enum _http_request_method_t {
22921 + /* force the enum to be signed */
22922 + HTTP_NEG_REQUEST_METHOD =-1,
22923 + HTTP_NO_REQUEST_METHOD = 0,
22924 + /* HTTP/1.1 */
22925 + HTTP_GET = 1,
22926 + HTTP_HEAD = 2,
22927 + HTTP_POST = 3,
22928 + HTTP_PUT = 4,
22929 + HTTP_DELETE = 5,
22930 + HTTP_OPTIONS = 6,
22931 + HTTP_TRACE = 7,
22932 + HTTP_CONNECT = 8,
22933 + /* WebDAV - RFC 2518 */
22934 + HTTP_PROPFIND = 9,
22935 + HTTP_PROPPATCH = 10,
22936 + HTTP_MKCOL = 11,
22937 + HTTP_COPY = 12,
22938 + HTTP_MOVE = 13,
22939 + HTTP_LOCK = 14,
22940 + HTTP_UNLOCK = 15,
22941 + /* WebDAV Versioning - RFC 3253 */
22942 + HTTP_VERSION_CONTROL = 16,
22943 + HTTP_REPORT = 17,
22944 + HTTP_CHECKOUT = 18,
22945 + HTTP_CHECKIN = 19,
22946 + HTTP_UNCHECKOUT = 20,
22947 + HTTP_MKWORKSPACE = 21,
22948 + HTTP_UPDATE = 22,
22949 + HTTP_LABEL = 23,
22950 + HTTP_MERGE = 24,
22951 + HTTP_BASELINE_CONTROL = 25,
22952 + HTTP_MKACTIVITY = 26,
22953 + /* WebDAV Access Control - RFC 3744 */
22954 + HTTP_ACL = 27,
22955 + HTTP_MAX_REQUEST_METHOD = 28
22956 +} http_request_method;
22957 +
22958 +#define HTTP_MIN_REQUEST_METHOD (HTTP_NO_REQUEST_METHOD + 1)
22959 +#define HTTP_STD_REQUEST_METHOD(m) ((m > HTTP_NO_REQUEST_METHOD) && (m < HTTP_MAX_REQUEST_METHOD))
22960 +
22961 +extern PHP_MINIT_FUNCTION(http_request_method);
22962 +extern PHP_RINIT_FUNCTION(http_request_method);
22963 +extern PHP_RSHUTDOWN_FUNCTION(http_request_method);
22964 +
22965 +#define http_request_method_name(m) _http_request_method_name((m) TSRMLS_CC)
22966 +PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC);
22967 +
22968 +#define http_request_method_exists(u, l, c) _http_request_method_exists((u), (l), (c) TSRMLS_CC)
22969 +PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id, const char *name TSRMLS_DC);
22970 +
22971 +#define http_request_method_register(m, l) _http_request_method_register((m), (l) TSRMLS_CC)
22972 +PHP_HTTP_API int _http_request_method_register(const char *method, int method_name_len TSRMLS_DC);
22973 +
22974 +#define http_request_method_unregister(mn) _http_request_method_unregister((mn) TSRMLS_CC)
22975 +PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC);
22976 +
22977 +#endif
22978 +
22979 +/*
22980 + * Local variables:
22981 + * tab-width: 4
22982 + * c-basic-offset: 4
22983 + * End:
22984 + * vim600: noet sw=4 ts=4 fdm=marker
22985 + * vim<600: noet sw=4 ts=4
22986 + */
22987 +
22988 --- /dev/null
22989 +++ b/ext/http/php_http_request_object.h
22990 @@ -0,0 +1,118 @@
22991 +/*
22992 + +--------------------------------------------------------------------+
22993 + | PECL :: http |
22994 + +--------------------------------------------------------------------+
22995 + | Redistribution and use in source and binary forms, with or without |
22996 + | modification, are permitted provided that the conditions mentioned |
22997 + | in the accompanying LICENSE file are met. |
22998 + +--------------------------------------------------------------------+
22999 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23000 + +--------------------------------------------------------------------+
23001 +*/
23002 +
23003 +/* $Id: php_http_request_object.h 292841 2009-12-31 08:48:57Z mike $ */
23004 +
23005 +#ifndef PHP_HTTP_REQUEST_OBJECT_H
23006 +#define PHP_HTTP_REQUEST_OBJECT_H
23007 +#ifdef HTTP_HAVE_CURL
23008 +#ifdef ZEND_ENGINE_2
23009 +
23010 +#include "php_http_request_api.h"
23011 +#include "php_http_request_pool_api.h"
23012 +#include "php_http_request_datashare_api.h"
23013 +
23014 +typedef struct _http_request_object_t {
23015 + zend_object zo;
23016 + http_request *request;
23017 + http_request_pool *pool;
23018 + http_request_datashare *share;
23019 +} http_request_object;
23020 +
23021 +extern zend_class_entry *http_request_object_ce;
23022 +extern zend_function_entry http_request_object_fe[];
23023 +
23024 +extern PHP_MINIT_FUNCTION(http_request_object);
23025 +
23026 +#define http_request_object_new(ce) _http_request_object_new((ce) TSRMLS_CC)
23027 +extern zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC);
23028 +#define http_request_object_new_ex(ce, ch, ptr) _http_request_object_new_ex((ce), (ch), (ptr) TSRMLS_CC)
23029 +extern zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC);
23030 +#define http_request_object_clone(zv) _http_request_object_clone_obj((zv) TSRMLS_CC)
23031 +extern zend_object_value _http_request_object_clone_obj(zval *zobject TSRMLS_DC);
23032 +#define http_request_object_free(o) _http_request_object_free((o) TSRMLS_CC)
23033 +extern void _http_request_object_free(zend_object *object TSRMLS_DC);
23034 +
23035 +#define http_request_object_requesthandler(req, this) _http_request_object_requesthandler((req), (this) TSRMLS_CC)
23036 +extern STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC);
23037 +#define http_request_object_responsehandler(req, this) _http_request_object_responsehandler((req), (this) TSRMLS_CC)
23038 +extern STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC);
23039 +
23040 +PHP_METHOD(HttpRequest, __construct);
23041 +PHP_METHOD(HttpRequest, setOptions);
23042 +PHP_METHOD(HttpRequest, getOptions);
23043 +PHP_METHOD(HttpRequest, addSslOptions);
23044 +PHP_METHOD(HttpRequest, setSslOptions);
23045 +PHP_METHOD(HttpRequest, getSslOptions);
23046 +PHP_METHOD(HttpRequest, addHeaders);
23047 +PHP_METHOD(HttpRequest, getHeaders);
23048 +PHP_METHOD(HttpRequest, setHeaders);
23049 +PHP_METHOD(HttpRequest, addCookies);
23050 +PHP_METHOD(HttpRequest, getCookies);
23051 +PHP_METHOD(HttpRequest, setCookies);
23052 +PHP_METHOD(HttpRequest, enableCookies);
23053 +PHP_METHOD(HttpRequest, resetCookies);
23054 +PHP_METHOD(HttpRequest, flushCookies);
23055 +PHP_METHOD(HttpRequest, setMethod);
23056 +PHP_METHOD(HttpRequest, getMethod);
23057 +PHP_METHOD(HttpRequest, setUrl);
23058 +PHP_METHOD(HttpRequest, getUrl);
23059 +PHP_METHOD(HttpRequest, setContentType);
23060 +PHP_METHOD(HttpRequest, getContentType);
23061 +PHP_METHOD(HttpRequest, setQueryData);
23062 +PHP_METHOD(HttpRequest, getQueryData);
23063 +PHP_METHOD(HttpRequest, addQueryData);
23064 +PHP_METHOD(HttpRequest, setPostFields);
23065 +PHP_METHOD(HttpRequest, getPostFields);
23066 +PHP_METHOD(HttpRequest, addPostFields);
23067 +PHP_METHOD(HttpRequest, getBody);
23068 +PHP_METHOD(HttpRequest, setBody);
23069 +PHP_METHOD(HttpRequest, addBody);
23070 +PHP_METHOD(HttpRequest, addPostFile);
23071 +PHP_METHOD(HttpRequest, setPostFiles);
23072 +PHP_METHOD(HttpRequest, getPostFiles);
23073 +PHP_METHOD(HttpRequest, setPutFile);
23074 +PHP_METHOD(HttpRequest, getPutFile);
23075 +PHP_METHOD(HttpRequest, getPutData);
23076 +PHP_METHOD(HttpRequest, setPutData);
23077 +PHP_METHOD(HttpRequest, addPutData);
23078 +PHP_METHOD(HttpRequest, send);
23079 +PHP_METHOD(HttpRequest, getResponseData);
23080 +PHP_METHOD(HttpRequest, getResponseHeader);
23081 +PHP_METHOD(HttpRequest, getResponseCookies);
23082 +PHP_METHOD(HttpRequest, getResponseCode);
23083 +PHP_METHOD(HttpRequest, getResponseStatus);
23084 +PHP_METHOD(HttpRequest, getResponseBody);
23085 +PHP_METHOD(HttpRequest, getResponseInfo);
23086 +PHP_METHOD(HttpRequest, getResponseMessage);
23087 +PHP_METHOD(HttpRequest, getRawResponseMessage);
23088 +PHP_METHOD(HttpRequest, getRequestMessage);
23089 +PHP_METHOD(HttpRequest, getRawRequestMessage);
23090 +PHP_METHOD(HttpRequest, getHistory);
23091 +PHP_METHOD(HttpRequest, clearHistory);
23092 +PHP_METHOD(HttpRequest, getMessageClass);
23093 +PHP_METHOD(HttpRequest, setMessageClass);
23094 +PHP_METHOD(HttpRequest, factory);
23095 +
23096 +#endif
23097 +#endif
23098 +#endif
23099 +
23100 +/*
23101 + * Local variables:
23102 + * tab-width: 4
23103 + * c-basic-offset: 4
23104 + * End:
23105 + * vim600: noet sw=4 ts=4 fdm=marker
23106 + * vim<600: noet sw=4 ts=4
23107 + */
23108 +
23109 --- /dev/null
23110 +++ b/ext/http/php_http_request_pool_api.h
23111 @@ -0,0 +1,97 @@
23112 +/*
23113 + +--------------------------------------------------------------------+
23114 + | PECL :: http |
23115 + +--------------------------------------------------------------------+
23116 + | Redistribution and use in source and binary forms, with or without |
23117 + | modification, are permitted provided that the conditions mentioned |
23118 + | in the accompanying LICENSE file are met. |
23119 + +--------------------------------------------------------------------+
23120 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23121 + +--------------------------------------------------------------------+
23122 +*/
23123 +
23124 +/* $Id: php_http_request_pool_api.h 292841 2009-12-31 08:48:57Z mike $ */
23125 +
23126 +#ifndef PHP_HTTP_REQUEST_POOL_API_H
23127 +#define PHP_HTTP_REQUEST_POOL_API_H
23128 +#ifdef HTTP_HAVE_CURL
23129 +#ifdef ZEND_ENGINE_2
23130 +
23131 +typedef struct _http_request_pool_t {
23132 + CURLM *ch;
23133 + zend_llist finished;
23134 + zend_llist handles;
23135 + int unfinished;
23136 +#ifdef ZTS
23137 + void ***tsrm_ls;
23138 +#endif
23139 +#ifdef HTTP_HAVE_EVENT
23140 + struct event *timeout;
23141 + unsigned useevents:1;
23142 + unsigned runsocket:1;
23143 +#endif
23144 +} http_request_pool;
23145 +
23146 +typedef int (*http_request_pool_apply_func)(http_request_pool *pool, zval *request);
23147 +typedef int (*http_request_pool_apply_with_arg_func)(http_request_pool *pool, zval *request, void *arg);
23148 +
23149 +PHP_MINIT_FUNCTION(http_request_pool);
23150 +#ifdef HTTP_HAVE_EVENT
23151 +PHP_RINIT_FUNCTION(http_request_pool);
23152 +#endif
23153 +
23154 +#define http_request_pool_timeout _http_request_pool_timeout
23155 +extern struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout);
23156 +
23157 +#define http_request_pool_responsehandler _http_request_pool_responsehandler
23158 +extern void _http_request_pool_responsehandler(http_request_pool *pool);
23159 +
23160 +#define http_request_pool_apply_responsehandler _http_request_pool_responsehandler
23161 +extern int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch);
23162 +
23163 +#define http_request_pool_init(p) _http_request_pool_init((p) TSRMLS_CC)
23164 +PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC);
23165 +
23166 +#define http_request_pool_attach(p, r) _http_request_pool_attach((p), (r))
23167 +PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request);
23168 +
23169 +#define http_request_pool_detach(p, r) _http_request_pool_detach((p), (r))
23170 +PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request);
23171 +
23172 +#define http_request_pool_apply(p, f) _http_request_pool_apply((p), (f))
23173 +PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb);
23174 +
23175 +#define http_request_pool_apply_with_arg(p, f, a) _http_request_pool_apply_with_arg((p), (f), (a))
23176 +PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg);
23177 +
23178 +#define http_request_pool_detach_all(p) _http_request_pool_detach_all((p))
23179 +PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool);
23180 +
23181 +#define http_request_pool_send(p) _http_request_pool_send((p))
23182 +PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool);
23183 +
23184 +#define http_request_pool_select _http_request_pool_select
23185 +PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool);
23186 +
23187 +#define http_request_pool_select_ex _http_request_pool_select_ex
23188 +PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout);
23189 +
23190 +#define http_request_pool_perform(p) _http_request_pool_perform((p))
23191 +PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool);
23192 +
23193 +#define http_request_pool_dtor(p) _http_request_pool_dtor((p))
23194 +PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool);
23195 +
23196 +#endif
23197 +#endif
23198 +#endif
23199 +
23200 +/*
23201 + * Local variables:
23202 + * tab-width: 4
23203 + * c-basic-offset: 4
23204 + * End:
23205 + * vim600: noet sw=4 ts=4 fdm=marker
23206 + * vim<600: noet sw=4 ts=4
23207 + */
23208 +
23209 --- /dev/null
23210 +++ b/ext/http/php_http_requestdatashare_object.h
23211 @@ -0,0 +1,59 @@
23212 +/*
23213 + +--------------------------------------------------------------------+
23214 + | PECL :: http |
23215 + +--------------------------------------------------------------------+
23216 + | Redistribution and use in source and binary forms, with or without |
23217 + | modification, are permitted provided that the conditions mentioned |
23218 + | in the accompanying LICENSE file are met. |
23219 + +--------------------------------------------------------------------+
23220 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23221 + +--------------------------------------------------------------------+
23222 +*/
23223 +
23224 +/* $Id: php_http_requestdatashare_object.h 292841 2009-12-31 08:48:57Z mike $ */
23225 +
23226 +#ifndef PHP_HTTP_REQUEST_DATASHARE_OBJECT_H
23227 +#define PHP_HTTP_REQUEST_DATASHARE_OBJECT_H
23228 +#ifdef HTTP_HAVE_CURL
23229 +#ifdef ZEND_ENGINE_2
23230 +
23231 +typedef struct _http_requestdatashare_object_t {
23232 + zend_object zo;
23233 + http_request_datashare *share;
23234 +} http_requestdatashare_object;
23235 +
23236 +extern zend_class_entry *http_requestdatashare_object_ce;
23237 +extern zend_function_entry http_requestdatashare_object_fe[];
23238 +
23239 +extern PHP_MINIT_FUNCTION(http_requestdatashare_object);
23240 +
23241 +#define http_requestdatashare_object_new(ce) _http_requestdatashare_object_new((ce) TSRMLS_CC)
23242 +extern zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC);
23243 +#define http_requestdatashare_object_new_ex(ce, s, ptr) _http_requestdatashare_object_new_ex((ce), (s), (ptr) TSRMLS_CC)
23244 +extern zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC);
23245 +#define http_requestdatashare_object_free(o) _http_requestdatashare_object_free((o) TSRMLS_CC)
23246 +extern void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC);
23247 +
23248 +PHP_METHOD(HttpRequestDataShare, __destruct);
23249 +PHP_METHOD(HttpRequestDataShare, count);
23250 +PHP_METHOD(HttpRequestDataShare, attach);
23251 +PHP_METHOD(HttpRequestDataShare, detach);
23252 +PHP_METHOD(HttpRequestDataShare, reset);
23253 +PHP_METHOD(HttpRequestDataShare, factory);
23254 +#ifndef WONKY
23255 +PHP_METHOD(HttpRequestDataShare, singleton);
23256 +#endif
23257 +
23258 +#endif
23259 +#endif
23260 +#endif
23261 +
23262 +/*
23263 + * Local variables:
23264 + * tab-width: 4
23265 + * c-basic-offset: 4
23266 + * End:
23267 + * vim600: noet sw=4 ts=4 fdm=marker
23268 + * vim<600: noet sw=4 ts=4
23269 + */
23270 +
23271 --- /dev/null
23272 +++ b/ext/http/php_http_requestpool_object.h
23273 @@ -0,0 +1,69 @@
23274 +/*
23275 + +--------------------------------------------------------------------+
23276 + | PECL :: http |
23277 + +--------------------------------------------------------------------+
23278 + | Redistribution and use in source and binary forms, with or without |
23279 + | modification, are permitted provided that the conditions mentioned |
23280 + | in the accompanying LICENSE file are met. |
23281 + +--------------------------------------------------------------------+
23282 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23283 + +--------------------------------------------------------------------+
23284 +*/
23285 +
23286 +/* $Id: php_http_requestpool_object.h 292841 2009-12-31 08:48:57Z mike $ */
23287 +
23288 +#ifndef PHP_HTTP_REQUESTPOOL_OBJECT_H
23289 +#define PHP_HTTP_REQUESTPOOL_OBJECT_H
23290 +#ifdef HTTP_HAVE_CURL
23291 +#ifdef ZEND_ENGINE_2
23292 +
23293 +typedef struct _http_requestpool_object_t {
23294 + zend_object zo;
23295 + http_request_pool pool;
23296 + struct {
23297 + long pos;
23298 + } iterator;
23299 +} http_requestpool_object;
23300 +
23301 +extern zend_class_entry *http_requestpool_object_ce;
23302 +extern zend_function_entry http_requestpool_object_fe[];
23303 +
23304 +extern PHP_MINIT_FUNCTION(http_requestpool_object);
23305 +
23306 +#define http_requestpool_object_new(ce) _http_requestpool_object_new(ce TSRMLS_CC)
23307 +extern zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC);
23308 +#define http_requestpool_object_free(o) _http_requestpool_object_free(o TSRMLS_CC)
23309 +extern void _http_requestpool_object_free(zend_object *object TSRMLS_DC);
23310 +
23311 +PHP_METHOD(HttpRequestPool, __construct);
23312 +PHP_METHOD(HttpRequestPool, __destruct);
23313 +PHP_METHOD(HttpRequestPool, attach);
23314 +PHP_METHOD(HttpRequestPool, detach);
23315 +PHP_METHOD(HttpRequestPool, send);
23316 +PHP_METHOD(HttpRequestPool, reset);
23317 +PHP_METHOD(HttpRequestPool, socketPerform);
23318 +PHP_METHOD(HttpRequestPool, socketSelect);
23319 +PHP_METHOD(HttpRequestPool, valid);
23320 +PHP_METHOD(HttpRequestPool, current);
23321 +PHP_METHOD(HttpRequestPool, key);
23322 +PHP_METHOD(HttpRequestPool, next);
23323 +PHP_METHOD(HttpRequestPool, rewind);
23324 +PHP_METHOD(HttpRequestPool, count);
23325 +PHP_METHOD(HttpRequestPool, getAttachedRequests);
23326 +PHP_METHOD(HttpRequestPool, getFinishedRequests);
23327 +PHP_METHOD(HttpRequestPool, enablePipelining);
23328 +PHP_METHOD(HttpRequestPool, enableEvents);
23329 +
23330 +#endif
23331 +#endif
23332 +#endif
23333 +
23334 +/*
23335 + * Local variables:
23336 + * tab-width: 4
23337 + * c-basic-offset: 4
23338 + * End:
23339 + * vim600: noet sw=4 ts=4 fdm=marker
23340 + * vim<600: noet sw=4 ts=4
23341 + */
23342 +
23343 --- /dev/null
23344 +++ b/ext/http/php_http_response_object.h
23345 @@ -0,0 +1,67 @@
23346 +/*
23347 + +--------------------------------------------------------------------+
23348 + | PECL :: http |
23349 + +--------------------------------------------------------------------+
23350 + | Redistribution and use in source and binary forms, with or without |
23351 + | modification, are permitted provided that the conditions mentioned |
23352 + | in the accompanying LICENSE file are met. |
23353 + +--------------------------------------------------------------------+
23354 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23355 + +--------------------------------------------------------------------+
23356 +*/
23357 +
23358 +/* $Id: php_http_response_object.h 292841 2009-12-31 08:48:57Z mike $ */
23359 +
23360 +#ifndef PHP_HTTP_RESPONSE_OBJECT_H
23361 +#define PHP_HTTP_RESPONSE_OBJECT_H
23362 +#ifdef ZEND_ENGINE_2
23363 +#ifndef WONKY
23364 +
23365 +extern zend_class_entry *http_response_object_ce;
23366 +extern zend_function_entry http_response_object_fe[];
23367 +
23368 +extern PHP_MINIT_FUNCTION(http_response_object);
23369 +
23370 +PHP_METHOD(HttpResponse, setHeader);
23371 +PHP_METHOD(HttpResponse, getHeader);
23372 +PHP_METHOD(HttpResponse, setETag);
23373 +PHP_METHOD(HttpResponse, getETag);
23374 +PHP_METHOD(HttpResponse, setLastModified);
23375 +PHP_METHOD(HttpResponse, getLastModified);
23376 +PHP_METHOD(HttpResponse, setContentDisposition);
23377 +PHP_METHOD(HttpResponse, getContentDisposition);
23378 +PHP_METHOD(HttpResponse, setContentType);
23379 +PHP_METHOD(HttpResponse, getContentType);
23380 +PHP_METHOD(HttpResponse, guessContentType);
23381 +PHP_METHOD(HttpResponse, setCache);
23382 +PHP_METHOD(HttpResponse, getCache);
23383 +PHP_METHOD(HttpResponse, setCacheControl);
23384 +PHP_METHOD(HttpResponse, getCacheControl);
23385 +PHP_METHOD(HttpResponse, setGzip);
23386 +PHP_METHOD(HttpResponse, getGzip);
23387 +PHP_METHOD(HttpResponse, setThrottleDelay);
23388 +PHP_METHOD(HttpResponse, getThrottleDelay);
23389 +PHP_METHOD(HttpResponse, setBufferSize);
23390 +PHP_METHOD(HttpResponse, getBufferSize);
23391 +PHP_METHOD(HttpResponse, setData);
23392 +PHP_METHOD(HttpResponse, getData);
23393 +PHP_METHOD(HttpResponse, setFile);
23394 +PHP_METHOD(HttpResponse, getFile);
23395 +PHP_METHOD(HttpResponse, setStream);
23396 +PHP_METHOD(HttpResponse, getStream);
23397 +PHP_METHOD(HttpResponse, send);
23398 +PHP_METHOD(HttpResponse, capture);
23399 +
23400 +#endif
23401 +#endif
23402 +#endif
23403 +
23404 +/*
23405 + * Local variables:
23406 + * tab-width: 4
23407 + * c-basic-offset: 4
23408 + * End:
23409 + * vim600: noet sw=4 ts=4 fdm=marker
23410 + * vim<600: noet sw=4 ts=4
23411 + */
23412 +
23413 --- /dev/null
23414 +++ b/ext/http/php_http_send_api.h
23415 @@ -0,0 +1,91 @@
23416 +/*
23417 + +--------------------------------------------------------------------+
23418 + | PECL :: http |
23419 + +--------------------------------------------------------------------+
23420 + | Redistribution and use in source and binary forms, with or without |
23421 + | modification, are permitted provided that the conditions mentioned |
23422 + | in the accompanying LICENSE file are met. |
23423 + +--------------------------------------------------------------------+
23424 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23425 + +--------------------------------------------------------------------+
23426 +*/
23427 +
23428 +/* $Id: php_http_send_api.h 292841 2009-12-31 08:48:57Z mike $ */
23429 +
23430 +#ifndef PHP_HTTP_SEND_API_H
23431 +#define PHP_HTTP_SEND_API_H
23432 +
23433 +typedef enum _http_send_mode_t {
23434 + SEND_DATA,
23435 + SEND_RSRC
23436 +} http_send_mode;
23437 +
23438 +#define HTTP_REDIRECT 0L
23439 +#define HTTP_REDIRECT_PERM 301L
23440 +#define HTTP_REDIRECT_FOUND 302L
23441 +#define HTTP_REDIRECT_POST 303L
23442 +#define HTTP_REDIRECT_PROXY 305L
23443 +#define HTTP_REDIRECT_TEMP 307L
23444 +
23445 +extern PHP_MINIT_FUNCTION(http_send);
23446 +
23447 +#define http_send_status(s) sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) (long) (s) TSRMLS_CC)
23448 +#define http_send_header(n, v, r) _http_send_header_ex((n), strlen(n), (v), strlen(v), (r), NULL TSRMLS_CC)
23449 +#define http_send_header_ex(n, nl, v, vl, r, s) _http_send_header_ex((n), (nl), (v), (vl), (r), (s) TSRMLS_CC)
23450 +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);
23451 +#define http_send_header_string(h) _http_send_status_header_ex(0, (h), strlen(h), 1 TSRMLS_CC)
23452 +#define http_send_header_string_ex(h, l, r) _http_send_status_header_ex(0, (h), (l), (r) TSRMLS_CC)
23453 +#define http_send_status_header(s, h) _http_send_status_header_ex((s), (h), (h)?strlen(h):0, 1 TSRMLS_CC)
23454 +#define http_send_status_header_ex(s, h, l, r) _http_send_status_header_ex((s), (h), (l), (r) TSRMLS_CC)
23455 +PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC);
23456 +
23457 +#define http_send_header_zval(n, z, r) http_send_header_zval_ex((n), strlen(n), (z), (r))
23458 +#define http_send_header_zval_ex(n, l, z, r) _http_send_header_zval_ex((n), (l), (z), (r) TSRMLS_CC)
23459 +PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC);
23460 +
23461 +#define http_hide_header(h) http_hide_header_ex((h), strlen(h))
23462 +#define http_hide_header_ex(h, l) _http_hide_header_ex((h), (l) TSRMLS_CC)
23463 +PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC);
23464 +
23465 +#define http_send_last_modified(t) _http_send_last_modified_ex((t), NULL TSRMLS_CC)
23466 +#define http_send_last_modified_ex(t, s) _http_send_last_modified_ex((t), (s) TSRMLS_CC)
23467 +PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC);
23468 +
23469 +#define http_send_etag(e, l) _http_send_etag_ex((e), (l), NULL TSRMLS_CC)
23470 +#define http_send_etag_ex(e, l, s) _http_send_etag_ex((e), (l), (s) TSRMLS_CC)
23471 +PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC);
23472 +
23473 +#define http_send_cache_control(cc, cl) http_send_header_ex("Cache-Control", lenof("Cache-Control"), (cc), (cl), 1, NULL)
23474 +
23475 +#define http_send_content_type(c, l) _http_send_content_type((c), (l) TSRMLS_CC)
23476 +PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC);
23477 +
23478 +#define http_send_content_disposition(f, l, i) _http_send_content_disposition((f), (l), (i) TSRMLS_CC)
23479 +PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC);
23480 +
23481 +#define http_send_data(d, l) http_send((d), (l), SEND_DATA)
23482 +#define http_send_data_ex(d, l, nc) http_send_ex((d), (l), SEND_DATA, (nc))
23483 +#define http_send(d, s, m) _http_send_ex((d), (s), (m), 0 TSRMLS_CC)
23484 +#define http_send_ex(d, s, m, nc) _http_send_ex((d), (s), (m), (nc) TSRMLS_CC)
23485 +PHP_HTTP_API STATUS _http_send_ex(const void *data, size_t data_size, http_send_mode mode, zend_bool no_cache TSRMLS_DC);
23486 +
23487 +#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)
23488 +#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))
23489 +#define http_send_stream(s) http_send_stream_ex((s), 0, 0)
23490 +#define http_send_stream_ex(s, c, nc) _http_send_stream_ex((s), (c), (nc) TSRMLS_CC)
23491 +PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *s, zend_bool close_stream, zend_bool no_cache TSRMLS_DC);
23492 +
23493 +#define http_guess_content_type(mf, mm, d, l, m) _http_guess_content_type((mf), (mm), (d), (l), (m) TSRMLS_CC)
23494 +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);
23495 +
23496 +#endif
23497 +
23498 +/*
23499 + * Local variables:
23500 + * tab-width: 4
23501 + * c-basic-offset: 4
23502 + * End:
23503 + * vim600: noet sw=4 ts=4 fdm=marker
23504 + * vim<600: noet sw=4 ts=4
23505 + */
23506 +
23507 --- /dev/null
23508 +++ b/ext/http/php_http_std_defs.h
23509 @@ -0,0 +1,410 @@
23510 +/*
23511 + +--------------------------------------------------------------------+
23512 + | PECL :: http |
23513 + +--------------------------------------------------------------------+
23514 + | Redistribution and use in source and binary forms, with or without |
23515 + | modification, are permitted provided that the conditions mentioned |
23516 + | in the accompanying LICENSE file are met. |
23517 + +--------------------------------------------------------------------+
23518 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23519 + +--------------------------------------------------------------------+
23520 +*/
23521 +
23522 +/* $Id: php_http_std_defs.h 323304 2012-02-17 21:13:24Z mike $ */
23523 +
23524 +#ifndef PHP_HTTP_STD_DEFS_H
23525 +#define PHP_HTTP_STD_DEFS_H
23526 +
23527 +#if defined(PHP_WIN32)
23528 +# if defined(HTTP_EXPORTS)
23529 +# define PHP_HTTP_API __declspec(dllexport)
23530 +# elif defined(COMPILE_DL_HTTP)
23531 +# define PHP_HTTP_API __declspec(dllimport)
23532 +# else
23533 +# define PHP_HTTP_API
23534 +# endif
23535 +#else
23536 +# define PHP_HTTP_API
23537 +#endif
23538 +
23539 +/* make functions that return SUCCESS|FAILURE more obvious */
23540 +typedef int STATUS;
23541 +
23542 +/* lenof() */
23543 +#define lenof(S) (sizeof(S) - 1)
23544 +
23545 +#ifndef MIN
23546 +# define MIN(a,b) (a<b?a:b)
23547 +#endif
23548 +#ifndef MAX
23549 +# define MAX(a,b) (a>b?a:b)
23550 +#endif
23551 +
23552 +/* STR_SET() */
23553 +#ifndef STR_SET
23554 +# define STR_SET(STR, SET) \
23555 + { \
23556 + STR_FREE(STR); \
23557 + STR = SET; \
23558 + }
23559 +#endif
23560 +
23561 +#define STR_PTR(s) (s?s:"")
23562 +
23563 +#define INIT_ZARR(zv, ht) \
23564 + { \
23565 + INIT_PZVAL(&(zv)); \
23566 + Z_TYPE(zv) = IS_ARRAY; \
23567 + Z_ARRVAL(zv) = (ht); \
23568 + }
23569 +
23570 +/* return bool (v == SUCCESS) */
23571 +#define RETVAL_SUCCESS(v) RETVAL_BOOL(SUCCESS == (v))
23572 +#define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v))
23573 +/* return object(values) */
23574 +#define RETVAL_OBJECT(o, addref) \
23575 + RETVAL_OBJVAL((o)->value.obj, addref)
23576 +#define RETURN_OBJECT(o, addref) \
23577 + RETVAL_OBJECT(o, addref); \
23578 + return
23579 +#define RETVAL_OBJVAL(ov, addref) \
23580 + ZVAL_OBJVAL(return_value, ov, addref)
23581 +#define RETURN_OBJVAL(ov, addref) \
23582 + RETVAL_OBJVAL(ov, addref); \
23583 + return
23584 +#define ZVAL_OBJVAL(zv, ov, addref) \
23585 + (zv)->type = IS_OBJECT; \
23586 + (zv)->value.obj = (ov);\
23587 + if (addref && Z_OBJ_HT_P(zv)->add_ref) { \
23588 + Z_OBJ_HT_P(zv)->add_ref((zv) TSRMLS_CC); \
23589 + }
23590 +/* return property */
23591 +#define RETVAL_PROP(n) RETVAL_PROP_EX(getThis(), n)
23592 +#define RETURN_PROP(n) RETURN_PROP_EX(getThis(), n)
23593 +#define RETVAL_PROP_EX(this, n) \
23594 + { \
23595 + zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \
23596 + RETVAL_ZVAL(__prop, 1, 0); \
23597 + }
23598 +#define RETURN_PROP_EX(this, n) \
23599 + { \
23600 + zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \
23601 + RETURN_ZVAL(__prop, 1, 0); \
23602 + }
23603 +
23604 +/* function accepts no args */
23605 +#define NO_ARGS zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "");
23606 +
23607 +/* CR LF */
23608 +#define HTTP_CRLF "\r\n"
23609 +
23610 +/* default cache control */
23611 +#define HTTP_DEFAULT_CACHECONTROL "private, must-revalidate, max-age=0"
23612 +
23613 +/* max URL length */
23614 +#define HTTP_URL_MAXLEN 4096
23615 +
23616 +/* max request method length */
23617 +#define HTTP_REQUEST_METHOD_MAXLEN 31
23618 +
23619 +/* def URL arg separator */
23620 +#define HTTP_URL_ARGSEP "&"
23621 +
23622 +/* send buffer size */
23623 +#define HTTP_SENDBUF_SIZE 40960
23624 +
23625 +/* CURL buffer size */
23626 +#define HTTP_CURLBUF_SIZE 16384
23627 +
23628 +/* known methods */
23629 +#define HTTP_KNOWN_METHODS \
23630 + /* HTTP 1.1 */ \
23631 + "GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, " \
23632 + /* WebDAV - RFC 2518 */ \
23633 + "PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, " \
23634 + /* WebDAV Versioning - RFC 3253 */ \
23635 + "VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, " \
23636 + "MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, " \
23637 + /* WebDAV Access Control - RFC 3744 */ \
23638 + "ACL, " \
23639 + /* END */
23640 +
23641 +#ifdef ZEND_ENGINE_2
23642 +# include "ext/standard/file.h"
23643 +# define HTTP_DEFAULT_STREAM_CONTEXT FG(default_context)
23644 +#else
23645 +# define HTTP_DEFAULT_STREAM_CONTEXT NULL
23646 +#endif
23647 +
23648 +#define HTTP_PHP_INI_ENTRY(entry, default, scope, updater, global) \
23649 + STD_PHP_INI_ENTRY(entry, default, scope, updater, global, zend_http_globals, http_globals)
23650 +#define HTTP_PHP_INI_ENTRY_EX(entry, default, scope, updater, displayer, global) \
23651 + STD_PHP_INI_ENTRY_EX(entry, default, scope, updater, global, zend_http_globals, http_globals, displayer)
23652 +
23653 +
23654 +#define HTTP_LONG_CONSTANT(name, const) REGISTER_LONG_CONSTANT(name, const, CONST_CS | CONST_PERSISTENT)
23655 +
23656 +/* {{{ objects & properties */
23657 +#ifdef ZEND_ENGINE_2
23658 +
23659 +# define HTTP_STATIC_ME_ALIAS(me, al, ai) ZEND_FENTRY(me, ZEND_FN(al), ai, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
23660 +
23661 +# define HTTP_REGISTER_CLASS_EX(classname, name, parent, flags) \
23662 + { \
23663 + zend_class_entry ce; \
23664 + memset(&ce, 0, sizeof(zend_class_entry)); \
23665 + INIT_CLASS_ENTRY(ce, #classname, name## _fe); \
23666 + ce.create_object = _ ##name## _new; \
23667 + name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
23668 + name## _ce->ce_flags |= flags; \
23669 + memcpy(& name## _handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
23670 + }
23671 +
23672 +# define HTTP_REGISTER_CLASS(classname, name, parent, flags) \
23673 + { \
23674 + zend_class_entry ce; \
23675 + memset(&ce, 0, sizeof(zend_class_entry)); \
23676 + INIT_CLASS_ENTRY(ce, #classname, name## _fe); \
23677 + ce.create_object = NULL; \
23678 + name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
23679 + name## _ce->ce_flags |= flags; \
23680 + }
23681 +
23682 +# define HTTP_REGISTER_EXCEPTION(classname, cename, parent) \
23683 + { \
23684 + zend_class_entry ce; \
23685 + memset(&ce, 0, sizeof(zend_class_entry)); \
23686 + INIT_CLASS_ENTRY(ce, #classname, NULL); \
23687 + ce.create_object = NULL; \
23688 + cename = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
23689 + }
23690 +
23691 +# define getObject(t, o) getObjectEx(t, o, getThis())
23692 +# define getObjectEx(t, o, v) t * o = ((t *) zend_object_store_get_object(v TSRMLS_CC))
23693 +# 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);
23694 +# if defined(ZEND_ENGINE_2_4)
23695 +# define freeObject(o) \
23696 + zend_object_std_dtor(o TSRMLS_CC); \
23697 + efree(o);
23698 +# elif !defined(WONKY)
23699 +# define freeObject(o) \
23700 + if (OBJ_GUARDS(o)) { \
23701 + zend_hash_destroy(OBJ_GUARDS(o)); \
23702 + FREE_HASHTABLE(OBJ_GUARDS(o)); \
23703 + } \
23704 + if (OBJ_PROP(o)) { \
23705 + zend_hash_destroy(OBJ_PROP(o)); \
23706 + FREE_HASHTABLE(OBJ_PROP(o)); \
23707 + } \
23708 + efree(o);
23709 +# else
23710 +# define freeObject(o) \
23711 + if (OBJ_PROP(o)) { \
23712 + zend_hash_destroy(OBJ_PROP(o)); \
23713 + FREE_HASHTABLE(OBJ_PROP(o)); \
23714 + } \
23715 + efree(o);
23716 +# endif
23717 +# define OBJ_PROP(o) (o)->zo.properties
23718 +# define OBJ_GUARDS(o) (o)->zo.guards
23719 +
23720 +# define ACC_PROP_PRIVATE(ce, flags) ((flags & ZEND_ACC_PRIVATE) && (EG(scope) && ce == EG(scope))
23721 +# define ACC_PROP_PROTECTED(ce, flags) ((flags & ZEND_ACC_PROTECTED) && (zend_check_protected(ce, EG(scope))))
23722 +# define ACC_PROP_PUBLIC(flags) (flags & ZEND_ACC_PUBLIC)
23723 +# define ACC_PROP(ce, flags) (ACC_PROP_PUBLIC(flags) || ACC_PROP_PRIVATE(ce, flags) || ACC_PROP_PROTECTED(ce, flags))
23724 +
23725 +# define SET_EH_THROW_HTTP() SET_EH_THROW_EX(http_exception_get_default())
23726 +# define SET_EH_THROW_EX(ex) php_set_error_handling(EH_THROW, ex TSRMLS_CC)
23727 +# define SET_EH_NORMAL() php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC)
23728 +
23729 +#endif /* ZEND_ENGINE_2 */
23730 +/* }}} */
23731 +
23732 +#ifdef ZEND_ENGINE_2
23733 +# define with_error_handling(eh, ec) \
23734 + { \
23735 + error_handling_t __eh = GLOBAL_ERROR_HANDLING; \
23736 + zend_class_entry *__ec= GLOBAL_EXCEPTION_CLASS; \
23737 + php_set_error_handling(eh, ec TSRMLS_CC);
23738 +# define end_error_handling() \
23739 + php_set_error_handling(__eh, __ec TSRMLS_CC); \
23740 + }
23741 +#else
23742 +# define with_error_handling(eh, ec)
23743 +# define end_error_handling()
23744 +#endif
23745 +
23746 +#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 5
23747 +# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default(TSRMLS_C)
23748 +#else
23749 +# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default()
23750 +#endif
23751 +
23752 +#ifndef E_THROW
23753 +# define E_THROW 0
23754 +#endif
23755 +#ifdef ZEND_ENGINE_2
23756 +# define HE_THROW E_THROW TSRMLS_CC
23757 +# define HE_NOTICE (HTTP_G->only_exceptions ? E_THROW : E_NOTICE) TSRMLS_CC
23758 +# define HE_WARNING (HTTP_G->only_exceptions ? E_THROW : E_WARNING) TSRMLS_CC
23759 +# define HE_ERROR (HTTP_G->only_exceptions ? E_THROW : E_ERROR) TSRMLS_CC
23760 +#else
23761 +# define HE_THROW E_WARNING TSRMLS_CC
23762 +# define HE_NOTICE E_NOTICE TSRMLS_CC
23763 +# define HE_WARNING E_WARNING TSRMLS_CC
23764 +# define HE_ERROR E_ERROR TSRMLS_CC
23765 +#endif
23766 +
23767 +#define HTTP_E_RUNTIME 1L
23768 +#define HTTP_E_INVALID_PARAM 2L
23769 +#define HTTP_E_HEADER 3L
23770 +#define HTTP_E_MALFORMED_HEADERS 4L
23771 +#define HTTP_E_REQUEST_METHOD 5L
23772 +#define HTTP_E_MESSAGE_TYPE 6L
23773 +#define HTTP_E_ENCODING 7L
23774 +#define HTTP_E_REQUEST 8L
23775 +#define HTTP_E_REQUEST_POOL 9L
23776 +#define HTTP_E_SOCKET 10L
23777 +#define HTTP_E_RESPONSE 11L
23778 +#define HTTP_E_URL 12L
23779 +#define HTTP_E_QUERYSTRING 13L
23780 +
23781 +#ifdef ZEND_ENGINE_2
23782 +# 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)
23783 +# 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)
23784 +# define HTTP_END_ARGS }
23785 +# define HTTP_EMPTY_ARGS_EX(class, method, ret_ref) HTTP_BEGIN_ARGS_EX(class, method, ret_ref, 0) HTTP_END_ARGS
23786 +# define HTTP_ARGS(class, method) args_for_ ##class## _ ##method
23787 +# define HTTP_ARG_VAL(name, pass_ref) ZEND_ARG_INFO(pass_ref, name)
23788 +# define HTTP_ARG_OBJ(class, name, allow_null) ZEND_ARG_OBJ_INFO(0, name, class, allow_null)
23789 +#endif
23790 +
23791 +#ifdef ZEND_ENGINE_2
23792 +# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL, 0, 0}
23793 +#else
23794 +# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL}
23795 +#endif
23796 +
23797 +#ifdef HTTP_HAVE_CURL
23798 +# ifdef ZEND_ENGINE_2
23799 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23800 + HTTP_STATIC_ARG_INFO \
23801 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \
23802 + ZEND_ARG_PASS_INFO(0) \
23803 + ZEND_ARG_PASS_INFO(1) \
23804 + ZEND_END_ARG_INFO(); \
23805 + \
23806 + HTTP_STATIC_ARG_INFO \
23807 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \
23808 + ZEND_ARG_PASS_INFO(0) \
23809 + ZEND_ARG_PASS_INFO(0) \
23810 + ZEND_ARG_PASS_INFO(1) \
23811 + ZEND_END_ARG_INFO(); \
23812 + \
23813 + HTTP_STATIC_ARG_INFO \
23814 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \
23815 + ZEND_ARG_PASS_INFO(0) \
23816 + ZEND_ARG_PASS_INFO(0) \
23817 + ZEND_ARG_PASS_INFO(0) \
23818 + ZEND_ARG_PASS_INFO(1) \
23819 + ZEND_END_ARG_INFO(); \
23820 + \
23821 + HTTP_STATIC_ARG_INFO \
23822 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_5, 0) \
23823 + ZEND_ARG_PASS_INFO(0) \
23824 + ZEND_ARG_PASS_INFO(0) \
23825 + ZEND_ARG_PASS_INFO(0) \
23826 + ZEND_ARG_PASS_INFO(0) \
23827 + ZEND_ARG_PASS_INFO(1) \
23828 + ZEND_END_ARG_INFO();
23829 +
23830 +# else
23831 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23832 + static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \
23833 + static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
23834 + static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
23835 + static unsigned char http_arg_pass_ref_5[] = {5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
23836 +# endif /* ZEND_ENGINE_2 */
23837 +#else
23838 +# ifdef ZEND_ENGINE_2
23839 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23840 + HTTP_STATIC_ARG_INFO \
23841 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \
23842 + ZEND_ARG_PASS_INFO(0) \
23843 + ZEND_ARG_PASS_INFO(1) \
23844 + ZEND_END_ARG_INFO(); \
23845 +\
23846 + HTTP_STATIC_ARG_INFO \
23847 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \
23848 + ZEND_ARG_PASS_INFO(0) \
23849 + ZEND_ARG_PASS_INFO(0) \
23850 + ZEND_ARG_PASS_INFO(1) \
23851 + ZEND_END_ARG_INFO(); \
23852 +\
23853 + HTTP_STATIC_ARG_INFO \
23854 + ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \
23855 + ZEND_ARG_PASS_INFO(0) \
23856 + ZEND_ARG_PASS_INFO(0) \
23857 + ZEND_ARG_PASS_INFO(0) \
23858 + ZEND_ARG_PASS_INFO(1) \
23859 + ZEND_END_ARG_INFO();
23860 +# else
23861 +# define HTTP_DECLARE_ARG_PASS_INFO() \
23862 + static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \
23863 + static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \
23864 + static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
23865 +# endif /* ZEND_ENGINE_2 */
23866 +#endif /* HTTP_HAVE_CURL */
23867 +
23868 +
23869 +#ifndef HAVE_CURL_SHARE_STRERROR
23870 +# define curl_share_strerror(dummy) "unknown error"
23871 +#endif
23872 +#ifndef HAVE_CURL_EASY_STRERROR
23873 +# define curl_easy_strerror(dummy) "unknown error"
23874 +#endif
23875 +#ifndef HAVE_CURL_MULTI_STRERROR
23876 +# define curl_multi_strerror(dummy) "unknown error"
23877 +#endif
23878 +
23879 +#define PHP_MINIT_CALL(func) PHP_MINIT(func)(INIT_FUNC_ARGS_PASSTHRU)
23880 +#define PHP_RINIT_CALL(func) PHP_RINIT(func)(INIT_FUNC_ARGS_PASSTHRU)
23881 +#define PHP_MSHUTDOWN_CALL(func) PHP_MSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU)
23882 +#define PHP_RSHUTDOWN_CALL(func) PHP_RSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU)
23883 +
23884 +#define Z_OBJ_DELREF(z) \
23885 + if (Z_OBJ_HT(z)->del_ref) { \
23886 + Z_OBJ_HT(z)->del_ref(&(z) TSRMLS_CC); \
23887 + }
23888 +#define Z_OBJ_ADDREF(z) \
23889 + if (Z_OBJ_HT(z)->add_ref) { \
23890 + Z_OBJ_HT(z)->add_ref(&(z) TSRMLS_CC); \
23891 + }
23892 +#define Z_OBJ_DELREF_P(z) \
23893 + if (Z_OBJ_HT_P(z)->del_ref) { \
23894 + Z_OBJ_HT_P(z)->del_ref((z) TSRMLS_CC); \
23895 + }
23896 +#define Z_OBJ_ADDREF_P(z) \
23897 + if (Z_OBJ_HT_P(z)->add_ref) { \
23898 + Z_OBJ_HT_P(z)->add_ref((z) TSRMLS_CC); \
23899 + }
23900 +#define Z_OBJ_DELREF_PP(z) \
23901 + if (Z_OBJ_HT_PP(z)->del_ref) { \
23902 + Z_OBJ_HT_PP(z)->del_ref(*(z) TSRMLS_CC); \
23903 + }
23904 +#define Z_OBJ_ADDREF_PP(z) \
23905 + if (Z_OBJ_HT_PP(z)->add_ref) { \
23906 + Z_OBJ_HT_PP(z)->add_ref(*(z) TSRMLS_CC); \
23907 + }
23908 +
23909 +#endif /* PHP_HTTP_STD_DEFS_H */
23910 +
23911 +/*
23912 + * Local variables:
23913 + * tab-width: 4
23914 + * c-basic-offset: 4
23915 + * End:
23916 + * vim600: noet sw=4 ts=4 fdm=marker
23917 + * vim<600: noet sw=4 ts=4
23918 + */
23919 +
23920 --- /dev/null
23921 +++ b/ext/http/php_http_url_api.h
23922 @@ -0,0 +1,165 @@
23923 +/*
23924 + +--------------------------------------------------------------------+
23925 + | PECL :: http |
23926 + +--------------------------------------------------------------------+
23927 + | Redistribution and use in source and binary forms, with or without |
23928 + | modification, are permitted provided that the conditions mentioned |
23929 + | in the accompanying LICENSE file are met. |
23930 + +--------------------------------------------------------------------+
23931 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
23932 + +--------------------------------------------------------------------+
23933 +*/
23934 +
23935 +/* $Id: php_http_url_api.h 292841 2009-12-31 08:48:57Z mike $ */
23936 +
23937 +#ifndef PHP_HTTP_URL_API_H
23938 +#define PHP_HTTP_URL_API_H
23939 +
23940 +#include "ext/standard/url.h"
23941 +
23942 +extern PHP_MINIT_FUNCTION(http_url);
23943 +
23944 +#define http_absolute_url(u) _http_absolute_url_ex((u), HTTP_URL_REPLACE TSRMLS_CC)
23945 +#define http_absolute_url_ex(u, f) _http_absolute_url_ex((u), (f) TSRMLS_CC)
23946 +PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC);
23947 +
23948 +#define HTTP_URL_REPLACE 0x000
23949 +#define HTTP_URL_JOIN_PATH 0x001
23950 +#define HTTP_URL_JOIN_QUERY 0x002
23951 +#define HTTP_URL_STRIP_USER 0x004
23952 +#define HTTP_URL_STRIP_PASS 0x008
23953 +#define HTTP_URL_STRIP_AUTH (HTTP_URL_STRIP_USER|HTTP_URL_STRIP_PASS)
23954 +#define HTTP_URL_STRIP_PORT 0x020
23955 +#define HTTP_URL_STRIP_PATH 0x040
23956 +#define HTTP_URL_STRIP_QUERY 0x080
23957 +#define HTTP_URL_STRIP_FRAGMENT 0x100
23958 +#define HTTP_URL_STRIP_ALL ( \
23959 + HTTP_URL_STRIP_AUTH | \
23960 + HTTP_URL_STRIP_PORT | \
23961 + HTTP_URL_STRIP_PATH | \
23962 + HTTP_URL_STRIP_QUERY | \
23963 + HTTP_URL_STRIP_FRAGMENT \
23964 +)
23965 +#define HTTP_URL_FROM_ENV 0x1000
23966 +
23967 +#define http_build_url(f, o, n, p, s, l) _http_build_url((f), (o), (n), (p), (s), (l) TSRMLS_CC)
23968 +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);
23969 +
23970 +#define http_urlencode_hash(h, q) _http_urlencode_hash_ex((h), 1, NULL, 0, (q), NULL TSRMLS_CC)
23971 +#define http_urlencode_hash_ex(h, o, p, pl, q, ql) _http_urlencode_hash_ex((h), (o), (p), (pl), (q), (ql) TSRMLS_CC)
23972 +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);
23973 +
23974 +#define http_urlencode_hash_recursive(ht, s, as, al, pr, pl) _http_urlencode_hash_recursive((ht), (s), (as), (al), (pr), (pl) TSRMLS_CC)
23975 +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);
23976 +
23977 +#define http_url_from_struct(u, ht) _http_url_from_struct((u), (ht) TSRMLS_CC)
23978 +static inline php_url *_http_url_from_struct(php_url *url, HashTable *ht TSRMLS_DC)
23979 +{
23980 + zval **e;
23981 +
23982 + if (!url) {
23983 + url = ecalloc(1, sizeof(php_url));
23984 + }
23985 +
23986 + if ((SUCCESS == zend_hash_find(ht, "scheme", sizeof("scheme"), (void *) &e))
23987 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23988 + url->scheme = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23989 + }
23990 + if ((SUCCESS == zend_hash_find(ht, "user", sizeof("user"), (void *) &e))
23991 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23992 + url->user = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23993 + }
23994 + if ((SUCCESS == zend_hash_find(ht, "pass", sizeof("pass"), (void *) &e))
23995 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
23996 + url->pass = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
23997 + }
23998 + if ((SUCCESS == zend_hash_find(ht, "host", sizeof("host"), (void *) &e))
23999 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
24000 + url->host = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
24001 + }
24002 + if ((SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &e))
24003 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
24004 + url->path = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
24005 + }
24006 + if ((SUCCESS == zend_hash_find(ht, "query", sizeof("query"), (void *) &e))
24007 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
24008 + url->query = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
24009 + }
24010 + if ((SUCCESS == zend_hash_find(ht, "fragment", sizeof("fragment"), (void *) &e))
24011 + && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) {
24012 + url->fragment = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e));
24013 + }
24014 + if (SUCCESS == zend_hash_find(ht, "port", sizeof("port"), (void *) &e)) {
24015 + if (Z_TYPE_PP(e) == IS_LONG) {
24016 + url->port = (unsigned short) Z_LVAL_PP(e);
24017 + } else {
24018 + zval *o = http_zsep(IS_LONG, *e);
24019 +
24020 + url->port = (unsigned short) Z_LVAL_P(o);
24021 + zval_ptr_dtor(&o);
24022 + }
24023 + }
24024 +
24025 + return url;
24026 +}
24027 +
24028 +#define http_url_tostruct(u, strct) _http_url_tostruct((u), (strct) TSRMLS_CC)
24029 +static inline HashTable *_http_url_tostruct(php_url *url, zval *strct TSRMLS_DC)
24030 +{
24031 + zval arr;
24032 +
24033 + if (strct) {
24034 + switch (Z_TYPE_P(strct)) {
24035 + default:
24036 + zval_dtor(strct);
24037 + array_init(strct);
24038 + case IS_ARRAY:
24039 + case IS_OBJECT:
24040 + INIT_ZARR(arr, HASH_OF(strct));
24041 + }
24042 + } else {
24043 + INIT_PZVAL(&arr);
24044 + array_init(&arr);
24045 + }
24046 +
24047 + if (url) {
24048 + if (url->scheme) {
24049 + add_assoc_string(&arr, "scheme", url->scheme, 1);
24050 + }
24051 + if (url->user) {
24052 + add_assoc_string(&arr, "user", url->user, 1);
24053 + }
24054 + if (url->pass) {
24055 + add_assoc_string(&arr, "pass", url->pass, 1);
24056 + }
24057 + if (url->host) {
24058 + add_assoc_string(&arr, "host", url->host, 1);
24059 + }
24060 + if (url->port) {
24061 + add_assoc_long(&arr, "port", (long) url->port);
24062 + }
24063 + if (url->path) {
24064 + add_assoc_string(&arr, "path", url->path, 1);
24065 + }
24066 + if (url->query) {
24067 + add_assoc_string(&arr, "query", url->query, 1);
24068 + }
24069 + if (url->fragment) {
24070 + add_assoc_string(&arr, "fragment", url->fragment, 1);
24071 + }
24072 + }
24073 +
24074 + return Z_ARRVAL(arr);
24075 +}
24076 +
24077 +#endif
24078 +
24079 +/*
24080 + * Local variables:
24081 + * tab-width: 4
24082 + * c-basic-offset: 4
24083 + * End:
24084 + * vim600: noet sw=4 ts=4 fdm=marker
24085 + * vim<600: noet sw=4 ts=4
24086 + */
24087 +
24088 --- /dev/null
24089 +++ b/ext/http/php_http_util_object.h
24090 @@ -0,0 +1,35 @@
24091 +/*
24092 + +--------------------------------------------------------------------+
24093 + | PECL :: http |
24094 + +--------------------------------------------------------------------+
24095 + | Redistribution and use in source and binary forms, with or without |
24096 + | modification, are permitted provided that the conditions mentioned |
24097 + | in the accompanying LICENSE file are met. |
24098 + +--------------------------------------------------------------------+
24099 + | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
24100 + +--------------------------------------------------------------------+
24101 +*/
24102 +
24103 +/* $Id: php_http_util_object.h 292841 2009-12-31 08:48:57Z mike $ */
24104 +
24105 +#ifndef PHP_HTTP_UTIL_OBJECT_H
24106 +#define PHP_HTTP_UTIL_OBJECT_H
24107 +#ifdef ZEND_ENGINE_2
24108 +
24109 +extern zend_class_entry *http_util_object_ce;
24110 +extern zend_function_entry http_util_object_fe[];
24111 +
24112 +extern PHP_MINIT_FUNCTION(http_util_object);
24113 +
24114 +#endif
24115 +#endif
24116 +
24117 +/*
24118 + * Local variables:
24119 + * tab-width: 4
24120 + * c-basic-offset: 4
24121 + * End:
24122 + * vim600: noet sw=4 ts=4 fdm=marker
24123 + * vim<600: noet sw=4 ts=4
24124 + */
24125 +
24126 --- /dev/null
24127 +++ b/ext/http/phpstr/phpstr.c
24128 @@ -0,0 +1,379 @@
24129 +
24130 +/* $Id: phpstr.c 211942 2006-04-24 17:17:09Z mike $ */
24131 +
24132 +#include "php.h"
24133 +#include "phpstr.h"
24134 +
24135 +PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags)
24136 +{
24137 + if (!buf) {
24138 + buf = pemalloc(sizeof(phpstr), flags & PHPSTR_INIT_PERSISTENT);
24139 + }
24140 +
24141 + if (buf) {
24142 + buf->size = (chunk_size) ? chunk_size : PHPSTR_DEFAULT_SIZE;
24143 + buf->pmem = (flags & PHPSTR_INIT_PERSISTENT) ? 1 : 0;
24144 + buf->data = (flags & PHPSTR_INIT_PREALLOC) ? pemalloc(buf->size, buf->pmem) : NULL;
24145 + buf->free = (flags & PHPSTR_INIT_PREALLOC) ? buf->size : 0;
24146 + buf->used = 0;
24147 + }
24148 +
24149 + return buf;
24150 +}
24151 +
24152 +PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length)
24153 +{
24154 + if ((buf = phpstr_init(buf))) {
24155 + if (PHPSTR_NOMEM == phpstr_append(buf, string, length)) {
24156 + pefree(buf, buf->pmem);
24157 + buf = NULL;
24158 + }
24159 + }
24160 + return buf;
24161 +}
24162 +
24163 +PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error)
24164 +{
24165 + char *ptr = NULL;
24166 +#if 0
24167 + fprintf(stderr, "RESIZE: size=%lu, used=%lu, free=%lu\n", buf->size, buf->used, buf->free);
24168 +#endif
24169 + if (buf->free < len) {
24170 + size_t size = override_size ? override_size : buf->size;
24171 +
24172 + while ((size + buf->free) < len) {
24173 + size <<= 1;
24174 + }
24175 +
24176 + if (allow_error) {
24177 + ptr = perealloc_recoverable(buf->data, buf->used + buf->free + size, buf->pmem);
24178 + } else {
24179 + ptr = perealloc(buf->data, buf->used + buf->free + size, buf->pmem);
24180 + }
24181 +
24182 + if (ptr) {
24183 + buf->data = ptr;
24184 + } else {
24185 + return PHPSTR_NOMEM;
24186 + }
24187 +
24188 + buf->free += size;
24189 + return size;
24190 + }
24191 + return 0;
24192 +}
24193 +
24194 +PHPSTR_API size_t phpstr_shrink(phpstr *buf)
24195 +{
24196 + /* avoid another realloc on fixation */
24197 + if (buf->free > 1) {
24198 + char *ptr = perealloc(buf->data, buf->used + 1, buf->pmem);
24199 +
24200 + if (ptr) {
24201 + buf->data = ptr;
24202 + } else {
24203 + return PHPSTR_NOMEM;
24204 + }
24205 + buf->free = 1;
24206 + }
24207 + return buf->used;
24208 +}
24209 +
24210 +PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len)
24211 +{
24212 + if (PHPSTR_NOMEM == phpstr_resize(buf, append_len)) {
24213 + return PHPSTR_NOMEM;
24214 + }
24215 + memcpy(buf->data + buf->used, append, append_len);
24216 + buf->used += append_len;
24217 + buf->free -= append_len;
24218 + return append_len;
24219 +}
24220 +
24221 +PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...)
24222 +{
24223 + va_list argv;
24224 + char *append;
24225 + size_t append_len, alloc;
24226 +
24227 + va_start(argv, format);
24228 + append_len = vspprintf(&append, 0, format, argv);
24229 + va_end(argv);
24230 +
24231 + alloc = phpstr_append(buf, append, append_len);
24232 + efree(append);
24233 +
24234 + if (PHPSTR_NOMEM == alloc) {
24235 + return PHPSTR_NOMEM;
24236 + }
24237 + return append_len;
24238 +}
24239 +
24240 +PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset)
24241 +{
24242 + if (PHPSTR_NOMEM == phpstr_resize(buf, insert_len)) {
24243 + return PHPSTR_NOMEM;
24244 + }
24245 + memmove(buf->data + offset + insert_len, buf->data + offset, insert_len);
24246 + memcpy(buf->data + offset, insert, insert_len);
24247 + buf->used += insert_len;
24248 + buf->free -= insert_len;
24249 + return insert_len;
24250 +}
24251 +
24252 +PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...)
24253 +{
24254 + va_list argv;
24255 + char *insert;
24256 + size_t insert_len, alloc;
24257 +
24258 + va_start(argv, format);
24259 + insert_len = vspprintf(&insert, 0, format, argv);
24260 + va_end(argv);
24261 +
24262 + alloc = phpstr_insert(buf, insert, insert_len, offset);
24263 + efree(insert);
24264 +
24265 + if (PHPSTR_NOMEM == alloc) {
24266 + return PHPSTR_NOMEM;
24267 + }
24268 + return insert_len;
24269 +}
24270 +
24271 +PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len)
24272 +{
24273 + if (PHPSTR_NOMEM == phpstr_resize(buf, prepend_len)) {
24274 + return PHPSTR_NOMEM;
24275 + }
24276 + memmove(buf->data + prepend_len, buf->data, buf->used);
24277 + memcpy(buf->data, prepend, prepend_len);
24278 + buf->used += prepend_len;
24279 + buf->free -= prepend_len;
24280 + return prepend_len;
24281 +}
24282 +
24283 +PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...)
24284 +{
24285 + va_list argv;
24286 + char *prepend;
24287 + size_t prepend_len, alloc;
24288 +
24289 + va_start(argv, format);
24290 + prepend_len = vspprintf(&prepend, 0, format, argv);
24291 + va_end(argv);
24292 +
24293 + alloc = phpstr_prepend(buf, prepend, prepend_len);
24294 + efree(prepend);
24295 +
24296 + if (PHPSTR_NOMEM == alloc) {
24297 + return PHPSTR_NOMEM;
24298 + }
24299 + return prepend_len;
24300 +}
24301 +
24302 +PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len)
24303 +{
24304 + char *copy = ecalloc(1, buf->used + 1);
24305 + memcpy(copy, buf->data, buf->used);
24306 + if (into) {
24307 + *into = copy;
24308 + }
24309 + if (len) {
24310 + *len = buf->used;
24311 + }
24312 + return copy;
24313 +}
24314 +
24315 +PHPSTR_API phpstr *phpstr_dup(const phpstr *buf)
24316 +{
24317 + phpstr *dup = phpstr_clone(buf);
24318 + if (PHPSTR_NOMEM == phpstr_append(dup, buf->data, buf->used)) {
24319 + phpstr_free(&dup);
24320 + }
24321 + return dup;
24322 +}
24323 +
24324 +PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length)
24325 +{
24326 + if (offset >= buf->used) {
24327 + return 0;
24328 + }
24329 + if (offset + length > buf->used) {
24330 + length = buf->used - offset;
24331 + }
24332 + memmove(buf->data + offset, buf->data + offset + length, buf->used - length);
24333 + buf->used -= length;
24334 + buf->free += length;
24335 + return length;
24336 +}
24337 +
24338 +PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t length)
24339 +{
24340 + if (offset >= buf->used) {
24341 + return NULL;
24342 + } else {
24343 + size_t need = 1 + ((length + offset) > buf->used ? (buf->used - offset) : (length - offset));
24344 + phpstr *sub = phpstr_init_ex(NULL, need, PHPSTR_INIT_PREALLOC | (buf->pmem ? PHPSTR_INIT_PERSISTENT:0));
24345 + if (sub) {
24346 + if (PHPSTR_NOMEM == phpstr_append(sub, buf->data + offset, need)) {
24347 + phpstr_free(&sub);
24348 + } else {
24349 + sub->size = buf->size;
24350 + }
24351 + }
24352 + return sub;
24353 + }
24354 +}
24355 +
24356 +PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length)
24357 +{
24358 + if (length < buf->used) {
24359 + return phpstr_sub(buf, buf->used - length, length);
24360 + } else {
24361 + return phpstr_sub(buf, 0, buf->used);
24362 + }
24363 +}
24364 +
24365 +
24366 +PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv)
24367 +{
24368 + unsigned i = 0;
24369 + buf = phpstr_init(buf);
24370 +
24371 + if (buf) {
24372 + while (argc > i++) {
24373 + phpstr_free_t f = va_arg(argv, phpstr_free_t);
24374 + phpstr *current = va_arg(argv, phpstr *);
24375 + phpstr_append(buf, current->data, current->used);
24376 + FREE_PHPSTR(f, current);
24377 + }
24378 + }
24379 +
24380 + return buf;
24381 +}
24382 +
24383 +PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...)
24384 +{
24385 + va_list argv;
24386 + phpstr *ret;
24387 +
24388 + va_start(argv, argc);
24389 + ret = phpstr_merge_va(buf, argc, argv);
24390 + va_end(argv);
24391 + return ret;
24392 +}
24393 +
24394 +PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...)
24395 +{
24396 + va_list argv;
24397 + phpstr *ret;
24398 +
24399 + va_start(argv, argc);
24400 + ret = phpstr_merge_va(NULL, argc, argv);
24401 + va_end(argv);
24402 + return ret;
24403 +}
24404 +
24405 +PHPSTR_API phpstr *phpstr_fix(phpstr *buf)
24406 +{
24407 + if (PHPSTR_NOMEM == phpstr_resize_ex(buf, 1, 1, 0)) {
24408 + return NULL;
24409 + }
24410 + buf->data[buf->used] = '\0';
24411 + return buf;
24412 +}
24413 +
24414 +PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right)
24415 +{
24416 + if (left->used > right->used) {
24417 + return -1;
24418 + } else if (right->used > left->used) {
24419 + return 1;
24420 + } else {
24421 + return memcmp(left->data, right->data, left->used);
24422 + }
24423 +}
24424 +
24425 +PHPSTR_API void phpstr_reset(phpstr *buf)
24426 +{
24427 + buf->free += buf->used;
24428 + buf->used = 0;
24429 +}
24430 +
24431 +PHPSTR_API void phpstr_dtor(phpstr *buf)
24432 +{
24433 + if (buf->data) {
24434 + pefree(buf->data, buf->pmem);
24435 + buf->data = NULL;
24436 + }
24437 + buf->used = 0;
24438 + buf->free = 0;
24439 +}
24440 +
24441 +PHPSTR_API void phpstr_free(phpstr **buf)
24442 +{
24443 + if (*buf) {
24444 + phpstr_dtor(*buf);
24445 + pefree(*buf, (*buf)->pmem);
24446 + *buf = NULL;
24447 + }
24448 +}
24449 +
24450 +PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size)
24451 +{
24452 + phpstr *storage;
24453 +
24454 + *chunk = NULL;
24455 +
24456 + if (!*s) {
24457 + *s = phpstr_init_ex(NULL, chunk_size << 1, chunk_size ? PHPSTR_INIT_PREALLOC : 0);
24458 + }
24459 + storage = *s;
24460 +
24461 + if (data_len) {
24462 + phpstr_append(storage, data, data_len);
24463 + }
24464 +
24465 + if (!chunk_size) {
24466 + phpstr_data(storage, chunk, &chunk_size);
24467 + phpstr_free(s);
24468 + return chunk_size;
24469 + }
24470 +
24471 + if (storage->used >= (chunk_size = storage->size >> 1)) {
24472 + *chunk = estrndup(storage->data, chunk_size);
24473 + phpstr_cut(storage, 0, chunk_size);
24474 + return chunk_size;
24475 + }
24476 +
24477 + return 0;
24478 +}
24479 +
24480 +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)
24481 +{
24482 + char *chunk = NULL;
24483 + size_t got = 0;
24484 +
24485 + while ((got = phpstr_chunk_buffer(s, data, data_len, &chunk, chunk_len))) {
24486 + passthru(opaque, chunk, got TSRMLS_CC);
24487 + if (!chunk_len) {
24488 + /* we already got the last chunk,
24489 + and freed all resources */
24490 + break;
24491 + }
24492 + data = NULL;
24493 + data_len = 0;
24494 + STR_SET(chunk, NULL);
24495 + }
24496 + STR_FREE(chunk);
24497 +}
24498 +
24499 +/*
24500 + * Local variables:
24501 + * tab-width: 4
24502 + * c-basic-offset: 4
24503 + * End:
24504 + * vim600: sw=4 ts=4 fdm=marker
24505 + * vim<600: sw=4 ts=4
24506 + */
24507 +
24508 --- /dev/null
24509 +++ b/ext/http/phpstr/phpstr.h
24510 @@ -0,0 +1,224 @@
24511 +
24512 +/* $Id: phpstr.h 229282 2007-02-07 15:31:50Z mike $ */
24513 +
24514 +#ifndef _PHPSTR_H_
24515 +#define _PHPSTR_H_
24516 +
24517 +#ifndef PHPSTR_DEFAULT_SIZE
24518 +# define PHPSTR_DEFAULT_SIZE 256
24519 +#endif
24520 +
24521 +#define PHPSTR_NOMEM ((size_t) -1)
24522 +
24523 +#ifndef STR_FREE
24524 +# define STR_FREE(STR) \
24525 + { \
24526 + if (STR) { \
24527 + efree(STR); \
24528 + } \
24529 + }
24530 +#endif
24531 +#ifndef STR_SET
24532 +# define STR_SET(STR, SET) \
24533 + { \
24534 + STR_FREE(STR); \
24535 + STR = SET; \
24536 + }
24537 +#endif
24538 +#ifndef TSRMLS_D
24539 +# define TSRMLS_D
24540 +# define TSRMLS_DC
24541 +# define TSRMLS_CC
24542 +# define TSRMLS_C
24543 +#endif
24544 +#ifdef PHP_ATTRIBUTE_FORMAT
24545 +# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b) PHP_ATTRIBUTE_FORMAT(f, a, b)
24546 +#else
24547 +# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b)
24548 +#endif
24549 +#ifndef pemalloc
24550 +# define pemalloc(s,p) malloc(s)
24551 +# define pefree(x,p) free(x)
24552 +# define perealloc(x,s,p) realloc(x,s)
24553 +# define perealloc_recoverable perealloc
24554 +# define ecalloc calloc
24555 +static inline void *estrndup(void *p, size_t s)
24556 +{
24557 + char *r = (char *) malloc(s+1);
24558 + if (r) memcpy((void *) r, p, s), r[s] = '\0';
24559 + return (void *) r;
24560 +}
24561 +#endif
24562 +
24563 +#if defined(PHP_WIN32)
24564 +# if defined(PHPSTR_EXPORTS)
24565 +# define PHPSTR_API __declspec(dllexport)
24566 +# elif defined(COMPILE_DL_PHPSTR)
24567 +# define PHPSTR_API __declspec(dllimport)
24568 +# else
24569 +# define PHPSTR_API
24570 +# endif
24571 +#else
24572 +# define PHPSTR_API
24573 +#endif
24574 +
24575 +#define PHPSTR(p) ((phpstr *) (p))
24576 +#define PHPSTR_VAL(p) (PHPSTR(p))->data
24577 +#define PHPSTR_LEN(p) (PHPSTR(p))->used
24578 +
24579 +#define FREE_PHPSTR_PTR(STR) pefree(STR, STR->pmem)
24580 +#define FREE_PHPSTR_VAL(STR) phpstr_dtor(STR)
24581 +#define FREE_PHPSTR_ALL(STR) phpstr_free(&(STR))
24582 +#define FREE_PHPSTR(free, STR) \
24583 + switch (free) \
24584 + { \
24585 + case PHPSTR_FREE_NOT: break; \
24586 + case PHPSTR_FREE_PTR: pefree(STR, STR->pmem); break; \
24587 + case PHPSTR_FREE_VAL: phpstr_dtor(STR); break; \
24588 + case PHPSTR_FREE_ALL: \
24589 + { \
24590 + phpstr *PTR = (STR); \
24591 + phpstr_free(&PTR); \
24592 + } \
24593 + break; \
24594 + default: break; \
24595 + }
24596 +
24597 +#define RETURN_PHPSTR_PTR(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_PTR, 0)
24598 +#define RETURN_PHPSTR_VAL(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 0)
24599 +#define RETURN_PHPSTR_DUP(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
24600 +#define RETVAL_PHPSTR_PTR(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_PTR, 0)
24601 +#define RETVAL_PHPSTR_VAL(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 0)
24602 +#define RETVAL_PHPSTR_DUP(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 1)
24603 +/* RETURN_PHPSTR(buf, PHPSTR_FREE_PTR, 0) */
24604 +#define RETURN_PHPSTR(STR, free, dup) \
24605 + RETVAL_PHPSTR((STR), (free), (dup)); \
24606 + return;
24607 +
24608 +#define RETVAL_PHPSTR(STR, free, dup) \
24609 + phpstr_fix(STR); \
24610 + RETVAL_STRINGL((STR)->data, (STR)->used, (dup)); \
24611 + FREE_PHPSTR((free), (STR));
24612 +
24613 +typedef struct _phpstr_t {
24614 + char *data;
24615 + size_t used;
24616 + size_t free;
24617 + size_t size;
24618 + unsigned pmem:1;
24619 + unsigned reserved:31;
24620 +} phpstr;
24621 +
24622 +typedef enum _phpstr_free_t {
24623 + PHPSTR_FREE_NOT = 0,
24624 + PHPSTR_FREE_PTR, /* pefree() */
24625 + PHPSTR_FREE_VAL, /* phpstr_dtor() */
24626 + PHPSTR_FREE_ALL /* phpstr_free() */
24627 +} phpstr_free_t;
24628 +
24629 +#define PHPSTR_ALL_FREE(STR) PHPSTR_FREE_ALL,(STR)
24630 +#define PHPSTR_PTR_FREE(STR) PHPSTR_FREE_PTR,(STR)
24631 +#define PHPSTR_VAL_FREE(STR) PHPSTR_FREE_VAL,(STR)
24632 +#define PHPSTR_NOT_FREE(STR) PHPSTR_FREE_NOT,(STR)
24633 +
24634 +#define PHPSTR_INIT_PREALLOC 0x01
24635 +#define PHPSTR_INIT_PERSISTENT 0x02
24636 +
24637 +/* create a new phpstr */
24638 +#define phpstr_new() phpstr_init(NULL)
24639 +#define phpstr_init(b) phpstr_init_ex(b, PHPSTR_DEFAULT_SIZE, 0)
24640 +#define phpstr_clone(phpstr_pointer) phpstr_init_ex(NULL, (phpstr_pointer)->size, (phpstr_pointer)->pmem ? PHPSTR_INIT_PERSISTENT:0)
24641 +PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags);
24642 +
24643 +/* create a phpstr from a zval or c-string */
24644 +#define phpstr_from_zval(z) phpstr_from_string(Z_STRVAL(z), Z_STRLEN(z))
24645 +#define phpstr_from_zval_ex(b, z) phpstr_from_string_ex(b, Z_STRVAL(z), Z_STRLEN(z))
24646 +#define phpstr_from_string(s, l) phpstr_from_string_ex(NULL, (s), (l))
24647 +PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length);
24648 +
24649 +/* usually only called from within the internal functions */
24650 +#define phpstr_resize(b, s) phpstr_resize_ex((b), (s), 0, 0)
24651 +PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error);
24652 +
24653 +/* shrink memory chunk to actually used size (+1) */
24654 +PHPSTR_API size_t phpstr_shrink(phpstr *buf);
24655 +
24656 +/* append data to the phpstr */
24657 +#define phpstr_appends(b, a) phpstr_append((b), (a), sizeof(a)-1)
24658 +#define phpstr_appendl(b, a) phpstr_append((b), (a), strlen(a))
24659 +PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len);
24660 +PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3);
24661 +
24662 +/* insert data at a specific position of the phpstr */
24663 +#define phpstr_inserts(b, i, o) phpstr_insert((b), (i), sizeof(i)-1, (o))
24664 +#define phpstr_insertl(b, i, o) phpstr_insert((b), (i), strlen(i), (o))
24665 +PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset);
24666 +PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 3, 4);
24667 +
24668 +/* prepend data */
24669 +#define phpstr_prepends(b, p) phpstr_prepend((b), (p), sizeof(p)-1)
24670 +#define phpstr_prependl(b, p) phpstr_prepend((b), (p), strlen(p))
24671 +PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len);
24672 +PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3);
24673 +
24674 +/* get a zero-terminated string */
24675 +PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len);
24676 +
24677 +/* get a part of the phpstr */
24678 +#define phpstr_mid(b, o, l) phpstr_sub((b), (o), (l))
24679 +#define phpstr_left(b, l) phpstr_sub((b), 0, (l))
24680 +PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length);
24681 +PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t len);
24682 +
24683 +/* remove a substring */
24684 +PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length);
24685 +
24686 +/* get a complete phpstr duplicate */
24687 +PHPSTR_API phpstr *phpstr_dup(const phpstr *buf);
24688 +
24689 +/* merge several phpstr objects
24690 + use like:
24691 +
24692 + phpstr *final = phpstr_merge(3,
24693 + PHPSTR_NOT_FREE(&keep),
24694 + PHPSTR_ALL_FREE(middle_ptr),
24695 + PHPSTR_VAL_FREE(&local);
24696 +*/
24697 +PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...);
24698 +PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...);
24699 +PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv);
24700 +
24701 +/* sets a trailing NUL byte */
24702 +PHPSTR_API phpstr *phpstr_fix(phpstr *buf);
24703 +
24704 +/* memcmp for phpstr objects */
24705 +PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right);
24706 +
24707 +/* reset phpstr object */
24708 +PHPSTR_API void phpstr_reset(phpstr *buf);
24709 +
24710 +/* free a phpstr objects contents */
24711 +PHPSTR_API void phpstr_dtor(phpstr *buf);
24712 +
24713 +/* free a phpstr object completely */
24714 +PHPSTR_API void phpstr_free(phpstr **buf);
24715 +
24716 +/* stores data in a phpstr until it reaches chunk_size */
24717 +PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size);
24718 +
24719 +typedef void (*phpstr_passthru_func)(void *opaque, const char *, size_t TSRMLS_DC);
24720 +
24721 +/* wrapper around phpstr_chunk_buffer, which passes available chunks to passthru() */
24722 +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);
24723 +
24724 +#endif
24725 +
24726 +
24727 +/*
24728 + * Local variables:
24729 + * tab-width: 4
24730 + * c-basic-offset: 4
24731 + * End:
24732 + * vim600: sw=4 ts=4 fdm=marker
24733 + * vim<600: sw=4 ts=4
24734 + */
24735 --- /dev/null
24736 +++ b/ext/http/tests/HttpMessage_001.phpt
24737 @@ -0,0 +1,70 @@
24738 +--TEST--
24739 +HttpMessage
24740 +--SKIPIF--
24741 +<?php
24742 +include 'skip.inc';
24743 +checkmin("5.2.5");
24744 +?>
24745 +--FILE--
24746 +<?php
24747 +echo "-TEST\n";
24748 +$m = new HttpMessage(
24749 + "HTTP/1.1 301\r\n".
24750 + "Location: /anywhere\r\n".
24751 + "HTTP/1.1 302\r\n".
24752 + "Location: /somewhere\r\n".
24753 + "HTTP/1.1 206 Partial content\r\n".
24754 + "Content-Range: bytes=2-3\r\n".
24755 + "Transfer-Encoding: chunked\r\n".
24756 + "\r\n".
24757 + "01\r\n".
24758 + "X\r\n".
24759 + "00"
24760 +);
24761 +
24762 +var_dump($m->getResponseStatus());
24763 +
24764 +$x = $m->getParentMessage();
24765 +$x = $m->getParentMessage();
24766 +$x = $m->getParentMessage();
24767 +
24768 +var_dump($m->getBody());
24769 +var_dump(HttpMessage::fromString($m->toString(true))->toString(true));
24770 +try {
24771 + do {
24772 + var_dump($m->toString());
24773 + } while ($m = $m->getParentMessage());
24774 +} catch (HttpException $ex) {
24775 +}
24776 +
24777 +echo "Done\n";
24778 +?>
24779 +--EXPECTF--
24780 +%aTEST
24781 +string(15) "Partial content"
24782 +string(1) "X"
24783 +string(190) "HTTP/1.1 301
24784 +Location: /anywhere
24785 +HTTP/1.1 302
24786 +Location: /somewhere
24787 +HTTP/1.1 206 Partial content
24788 +Content-Range: bytes=2-3
24789 +X-Original-Transfer-Encoding: chunked
24790 +Content-Length: 1
24791 +
24792 +X
24793 +"
24794 +string(119) "HTTP/1.1 206 Partial content
24795 +Content-Range: bytes=2-3
24796 +X-Original-Transfer-Encoding: chunked
24797 +Content-Length: 1
24798 +
24799 +X
24800 +"
24801 +string(36) "HTTP/1.1 302
24802 +Location: /somewhere
24803 +"
24804 +string(35) "HTTP/1.1 301
24805 +Location: /anywhere
24806 +"
24807 +Done
24808 --- /dev/null
24809 +++ b/ext/http/tests/HttpMessage_002.phpt
24810 @@ -0,0 +1,65 @@
24811 +--TEST--
24812 +HttpMessage properties
24813 +--SKIPIF--
24814 +<?php
24815 +include 'skip.inc';
24816 +checkmin("5.2.5");
24817 +checkcls('HttpMessage');
24818 +?>
24819 +--FILE--
24820 +<?php
24821 +class Message extends HttpMessage
24822 +{
24823 + var $var_property = 'var';
24824 + public $public_property = 'public';
24825 + protected $protected_property = 'protected';
24826 + private $private_property = 'private';
24827 +
24828 + public function test()
24829 + {
24830 + var_dump($this->var_property);
24831 + var_dump($this->public_property);
24832 + var_dump($this->protected_property);
24833 + var_dump($this->private_property);
24834 + var_dump($this->non_ex_property);
24835 + $this->var_property.='_property';
24836 + $this->public_property.='_property';
24837 + $this->protected_property.='_property';
24838 + $this->private_property.='_property';
24839 + $this->non_ex_property = 'non_ex';
24840 + var_dump($this->var_property);
24841 + var_dump($this->public_property);
24842 + var_dump($this->protected_property);
24843 + var_dump($this->private_property);
24844 + var_dump($this->non_ex_property);
24845 +
24846 + print_r($this->headers);
24847 + $this->headers['Foo'] = 'Bar';
24848 + }
24849 +}
24850 +
24851 +error_reporting(E_ALL|E_STRICT);
24852 +
24853 +echo "-TEST\n";
24854 +$m = new Message;
24855 +$m->test();
24856 +echo "Done\n";
24857 +?>
24858 +--EXPECTF--
24859 +%aTEST
24860 +string(3) "var"
24861 +string(6) "public"
24862 +string(9) "protected"
24863 +string(7) "private"
24864 +
24865 +Notice: Undefined property: Message::$non_ex_property in %s
24866 +NULL
24867 +string(12) "var_property"
24868 +string(15) "public_property"
24869 +string(18) "protected_property"
24870 +string(16) "private_property"
24871 +string(6) "non_ex"
24872 +Array
24873 +(
24874 +)
24875 +%aFatal error%sCannot access HttpMessage properties by reference or array key/index in%s
24876 --- /dev/null
24877 +++ b/ext/http/tests/HttpMessage_003.phpt
24878 @@ -0,0 +1,70 @@
24879 +--TEST--
24880 +HttpMessage implements Serializable, Countable
24881 +--SKIPIF--
24882 +<?php
24883 +include 'skip.inc';
24884 +checkmin("5.2.5");
24885 +?>
24886 +--FILE--
24887 +<?php
24888 +echo "-TEST\n";
24889 +
24890 +$m = new HttpMessage(
24891 + "HTTP/1.1 301\r\n".
24892 + "Location: /anywhere\r\n".
24893 + "HTTP/1.1 302\r\n".
24894 + "Location: /somewhere\r\n".
24895 + "HTTP/1.1 200\r\n".
24896 + "Transfer-Encoding: chunked\r\n".
24897 + "\r\n".
24898 + "01\r\n".
24899 + "X\r\n".
24900 + "00"
24901 +);
24902 +
24903 +var_dump($m->count());
24904 +var_dump($m->serialize());
24905 +$m->unserialize("HTTP/1.1 200 Ok\r\nServer: Funky/1.0");
24906 +var_dump($m);
24907 +var_dump($m->count());
24908 +
24909 +echo "Done\n";
24910 +?>
24911 +--EXPECTF--
24912 +%aTEST
24913 +int(3)
24914 +string(148) "HTTP/1.1 301
24915 +Location: /anywhere
24916 +HTTP/1.1 302
24917 +Location: /somewhere
24918 +HTTP/1.1 200
24919 +X-Original-Transfer-Encoding: chunked
24920 +Content-Length: 1
24921 +
24922 +X
24923 +"
24924 +object(HttpMessage)#%d (%d) {
24925 + ["type%s]=>
24926 + int(2)
24927 + ["body%s]=>
24928 + string(0) ""
24929 + ["requestMethod%s]=>
24930 + string(0) ""
24931 + ["requestUrl%s]=>
24932 + string(0) ""
24933 + ["responseStatus%s]=>
24934 + string(2) "Ok"
24935 + ["responseCode%s]=>
24936 + int(200)
24937 + ["httpVersion%s]=>
24938 + float(1.1)
24939 + ["headers%s]=>
24940 + array(1) {
24941 + ["Server"]=>
24942 + string(9) "Funky/1.0"
24943 + }
24944 + ["parentMessage%s]=>
24945 + NULL
24946 +}
24947 +int(1)
24948 +Done
24949 --- /dev/null
24950 +++ b/ext/http/tests/HttpMessage_004.phpt
24951 @@ -0,0 +1,36 @@
24952 +--TEST--
24953 +HttpMessage::detach()
24954 +--SKIPIF--
24955 +<?php
24956 +include 'skip.inc';
24957 +checkver(5);
24958 +?>
24959 +--FILE--
24960 +<?php
24961 +echo "-TEST\n";
24962 +
24963 +$m = new HttpMessage("
24964 +GET / HTTP/1.1
24965 +Host: example.com
24966 +Accept: */*
24967 +Connection: close
24968 +HTTP/1.1 200 ok
24969 +Server: Funky/1.0
24970 +Content-Type: text/plain
24971 +Content-Length: 3
24972 +
24973 +Hi!"
24974 +);
24975 +
24976 +$d = $m->detach();
24977 +$d->addHeaders(array('Server'=>'Funky/2.0'));
24978 +var_dump($d->getHeaders() == $m->getHeaders());
24979 +var_dump($d->getBody());
24980 +
24981 +echo "Done\n";
24982 +?>
24983 +--EXPECTF--
24984 +%aTEST
24985 +bool(false)
24986 +string(3) "Hi!"
24987 +Done
24988 \ No newline at end of file
24989 --- /dev/null
24990 +++ b/ext/http/tests/HttpMessage_005.phpt
24991 @@ -0,0 +1,86 @@
24992 +--TEST--
24993 +HttpMessage::prepend()
24994 +--SKIPIF--
24995 +<?php
24996 +include 'skip.inc';
24997 +checkver(5);
24998 +?>
24999 +--FILE--
25000 +<?php
25001 +echo "-TEST\n";
25002 +
25003 +$m1 = new HttpMessage("
25004 +GET / HTTP/1.1
25005 +Host: example.com
25006 +Accept: */*
25007 +Connection: close
25008 +HTTP/1.1 200 ok
25009 +Server: Funky/1.0
25010 +Content-Type: text/plain
25011 +Content-Length: 3
25012 +
25013 +Hi!"
25014 +);
25015 +
25016 +$m2 = new HttpMessage("
25017 +GET http://example.com/ HTTP/1.0
25018 +HTTP/1.1 200 ok
25019 +Server: Funky/2.0
25020 +Content-Type: text/html
25021 +Content-Length: 9
25022 +
25023 +Hi there!"
25024 +);
25025 +
25026 +$m1->prepend($m2);
25027 +$m2 = NULL;
25028 +echo $m1->toString(true);
25029 +
25030 +$m1->prepend($m1->detach(), false);
25031 +echo $m1->toString(true);
25032 +
25033 +echo "Done\n";
25034 +?>
25035 +--EXPECTF--
25036 +%aTEST
25037 +GET http://example.com/ HTTP/1.0
25038 +HTTP/1.1 200 ok
25039 +Server: Funky/2.0
25040 +Content-Type: text/html
25041 +Content-Length: 9
25042 +
25043 +Hi there!
25044 +GET / HTTP/1.1
25045 +Host: example.com
25046 +Accept: */*
25047 +Connection: close
25048 +HTTP/1.1 200 ok
25049 +Server: Funky/1.0
25050 +Content-Type: text/plain
25051 +Content-Length: 3
25052 +
25053 +Hi!
25054 +GET http://example.com/ HTTP/1.0
25055 +HTTP/1.1 200 ok
25056 +Server: Funky/2.0
25057 +Content-Type: text/html
25058 +Content-Length: 9
25059 +
25060 +Hi there!
25061 +GET / HTTP/1.1
25062 +Host: example.com
25063 +Accept: */*
25064 +Connection: close
25065 +HTTP/1.1 200 ok
25066 +Server: Funky/1.0
25067 +Content-Type: text/plain
25068 +Content-Length: 3
25069 +
25070 +Hi!
25071 +HTTP/1.1 200 ok
25072 +Server: Funky/1.0
25073 +Content-Type: text/plain
25074 +Content-Length: 3
25075 +
25076 +Hi!
25077 +Done
25078 \ No newline at end of file
25079 --- /dev/null
25080 +++ b/ext/http/tests/HttpMessage_006.phpt
25081 @@ -0,0 +1,35 @@
25082 +--TEST--
25083 +HttpMessage iterator
25084 +--SKIPIF--
25085 +<?php
25086 +include 'skip.inc';
25087 +checkver(5);
25088 +?>
25089 +--FILE--
25090 +<?php
25091 +echo "-TEST\n";
25092 +
25093 +$m = new HttpMessage("
25094 +GET / HTTP/1.1
25095 +HTTP/1.1 200 OK
25096 +GET /foo HTTP/1.1
25097 +HTTP/1.1 304 Not Modified
25098 +");
25099 +
25100 +foreach ($m as $msg) {
25101 + echo "==\n", $msg;
25102 +}
25103 +
25104 +echo "Done\n";
25105 +?>
25106 +--EXPECTF--
25107 +%aTEST
25108 +==
25109 +HTTP/1.1 304 Not Modified
25110 +==
25111 +GET /foo HTTP/1.1
25112 +==
25113 +HTTP/1.1 200 OK
25114 +==
25115 +GET / HTTP/1.1
25116 +Done
25117 \ No newline at end of file
25118 --- /dev/null
25119 +++ b/ext/http/tests/HttpMessage_007.phpt
25120 @@ -0,0 +1,46 @@
25121 +--TEST--
25122 +HttpMessage::reverse()
25123 +--SKIPIF--
25124 +<?php
25125 +include 'skip.inc';
25126 +checkver(5);
25127 +?>
25128 +--FILE--
25129 +<?php
25130 +echo "-TEST\n";
25131 +$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";
25132 +echo HttpMessage::fromString($s)->toString(true);
25133 +echo "===\n";
25134 +echo HttpMessage::fromString($s)->reverse()->toString(true);
25135 +
25136 +$m = new HttpMessage($s);
25137 +$r = $m->reverse();
25138 +unset($m);
25139 +var_dump($r->count());
25140 +echo $r->toString(true);
25141 +
25142 +echo "Done\n";
25143 +?>
25144 +--EXPECTF--
25145 +%aTEST
25146 +GET /first HTTP/1.1
25147 +HTTP/1.1 200 Ok-first
25148 +GET /second HTTP/1.1
25149 +HTTP/1.1 200 Ok-second
25150 +GET /third HTTP/1.1
25151 +HTTP/1.1 200 Ok-third
25152 +===
25153 +HTTP/1.1 200 Ok-third
25154 +GET /third HTTP/1.1
25155 +HTTP/1.1 200 Ok-second
25156 +GET /second HTTP/1.1
25157 +HTTP/1.1 200 Ok-first
25158 +GET /first HTTP/1.1
25159 +int(6)
25160 +HTTP/1.1 200 Ok-third
25161 +GET /third HTTP/1.1
25162 +HTTP/1.1 200 Ok-second
25163 +GET /second HTTP/1.1
25164 +HTTP/1.1 200 Ok-first
25165 +GET /first HTTP/1.1
25166 +Done
25167 --- /dev/null
25168 +++ b/ext/http/tests/HttpMessage_008.phpt
25169 @@ -0,0 +1,41 @@
25170 +--TEST--
25171 +HttpMessage::toMessageTypeObject()
25172 +--SKIPIF--
25173 +<?php
25174 +include 'skip.inc';
25175 +checkver(5);
25176 +checkcls('HttpRequest');
25177 +?>
25178 +--FILE--
25179 +<?php
25180 +echo "-TEST\n";
25181 +
25182 +$b = HttpRequest::encodeBody(array("a"=>"b",1=>2),null);
25183 +
25184 +$m = new HttpMessage;
25185 +$m->setType(HttpMessage::TYPE_REQUEST);
25186 +$m->setRequestMethod('POST');
25187 +$m->setRequestUrl("http://www.example.com");
25188 +$m->setHttpVersion('1.1');
25189 +$m->addHeaders(
25190 + array(
25191 + "Content-Type" => "application/x-www-form-urlencoded",
25192 + "Host" => "www.example.com",
25193 + "Content-Length"=> strlen($b),
25194 + )
25195 +);
25196 +$m->setBody($b);
25197 +$r = $m->toMessageTypeObject();
25198 +echo $m,"\n";
25199 +echo "Done\n";
25200 +?>
25201 +--EXPECTF--
25202 +%aTEST
25203 +POST http://www.example.com HTTP/1.1
25204 +Content-Type: application/x-www-form-urlencoded
25205 +Host: www.example.com
25206 +Content-Length: 7
25207 +
25208 +a=b&1=2
25209 +
25210 +Done
25211 --- /dev/null
25212 +++ b/ext/http/tests/HttpMessage_009_bug16700.phpt
25213 @@ -0,0 +1,24 @@
25214 +--TEST--
25215 +Bug #16700 - child classes of HttpMessage cannot not have array properties
25216 +--SKIPIF--
25217 +<?php
25218 +include 'skip.inc';
25219 +checkver(5);
25220 +?>
25221 +--FILE--
25222 +<?php
25223 +echo "-TEST\n";
25224 +
25225 +class ChildMessage extends HttpMessage {
25226 + public $properties = array();
25227 +}
25228 +
25229 +$child = new ChildMessage;
25230 +$child->properties['foo'] = 'bar';
25231 +echo $child->properties['foo'], "\n";
25232 +echo "Done\n";
25233 +?>
25234 +--EXPECTF--
25235 +%aTEST
25236 +bar
25237 +Done
25238 --- /dev/null
25239 +++ b/ext/http/tests/HttpQueryString_001.phpt
25240 @@ -0,0 +1,116 @@
25241 +--TEST--
25242 +HttpQueryString global
25243 +--SKIPIF--
25244 +<?php
25245 +include 'skip.inc';
25246 +checkmin("5.2.5");
25247 +?>
25248 +--FILE--
25249 +<?php
25250 +echo "-TEST\n";
25251 +
25252 +$_GET = array('a'=>'b','c'=>'3.4','r'=>array(1,2,3));
25253 +$_SERVER['QUERY_STRING'] = 'a=b&c=3.4&r[0]=1&r[1]=2&r[2]=3';
25254 +
25255 +var_dump(HttpQueryString::singleton()->get());
25256 +var_dump(HttpQueryString::singleton()->get('n'));
25257 +var_dump(HttpQueryString::singleton()->get('a'));
25258 +var_dump(HttpQueryString::singleton()->get('a', "i", 0, true));
25259 +var_dump(HttpQueryString::singleton()->get('a', "string", 'hi!'));
25260 +var_dump(HttpQueryString::singleton()->get('c'));
25261 +var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_INT));
25262 +var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_FLOAT));
25263 +var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_BOOL));
25264 +var_dump(HttpQueryString::singleton()->get('r'));
25265 +var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_ARRAY));
25266 +var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_OBJECT));
25267 +
25268 +HttpQueryString::singleton()->set(new HttpQueryString(false, 'z[0]=2'));
25269 +
25270 +HttpQueryString::singleton()->set(array('a'=>'b', 'c'=> "3.4"));
25271 +HttpQueryString::singleton()->set(array('a' => NULL));
25272 +
25273 +var_dump(HttpQueryString::singleton());
25274 +var_dump($_GET);
25275 +var_dump($_SERVER['QUERY_STRING']);
25276 +
25277 +echo "Done\n";
25278 +?>
25279 +--EXPECTF--
25280 +%aTEST
25281 +string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3"
25282 +NULL
25283 +string(1) "b"
25284 +int(0)
25285 +string(3) "hi!"
25286 +string(3) "3.4"
25287 +int(3)
25288 +float(3.4)
25289 +bool(true)
25290 +array(3) {
25291 + [0]=>
25292 + int(1)
25293 + [1]=>
25294 + int(2)
25295 + [2]=>
25296 + int(3)
25297 +}
25298 +array(3) {
25299 + [0]=>
25300 + int(1)
25301 + [1]=>
25302 + int(2)
25303 + [2]=>
25304 + int(3)
25305 +}
25306 +object(stdClass)#%d (%d) {
25307 + [0]=>
25308 + int(1)
25309 + [1]=>
25310 + int(2)
25311 + [2]=>
25312 + int(3)
25313 +}
25314 +object(HttpQueryString)#1 (2) {
25315 + ["queryArray%s]=>
25316 + &array(3) {
25317 + ["c"]=>
25318 + string(3) "3.4"
25319 + ["r"]=>
25320 + array(3) {
25321 + [0]=>
25322 + int(1)
25323 + [1]=>
25324 + int(2)
25325 + [2]=>
25326 + int(3)
25327 + }
25328 + ["z"]=>
25329 + array(1) {
25330 + [0]=>
25331 + string(1) "2"
25332 + }
25333 + }
25334 + ["queryString%s]=>
25335 + &string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
25336 +}
25337 +array(3) {
25338 + ["c"]=>
25339 + string(3) "3.4"
25340 + ["r"]=>
25341 + array(3) {
25342 + [0]=>
25343 + int(1)
25344 + [1]=>
25345 + int(2)
25346 + [2]=>
25347 + int(3)
25348 + }
25349 + ["z"]=>
25350 + array(1) {
25351 + [0]=>
25352 + string(1) "2"
25353 + }
25354 +}
25355 +string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
25356 +Done
25357 \ No newline at end of file
25358 --- /dev/null
25359 +++ b/ext/http/tests/HttpQueryString_002.phpt
25360 @@ -0,0 +1,108 @@
25361 +--TEST--
25362 +HttpQueryString local
25363 +--SKIPIF--
25364 +<?php
25365 +include 'skip.inc';
25366 +checkmin("5.2.5");
25367 +?>
25368 +--FILE--
25369 +<?php
25370 +echo "-TEST\n";
25371 +
25372 +$q = new HttpQueryString(false, $array = array('a'=>'b','c'=>'3.4','r'=>array(1,2,3)));
25373 +var_dump($q->get());
25374 +var_dump($q->get('n'));
25375 +var_dump($q->get('a'));
25376 +var_dump($q->get('a', "i", 0, true));
25377 +var_dump($q->get('a', "string", 'hi!'));
25378 +var_dump($q->get('c'));
25379 +var_dump($q->get('c', HttpQueryString::TYPE_INT));
25380 +var_dump($q->get('c', HttpQueryString::TYPE_FLOAT));
25381 +var_dump($q->get('c', HttpQueryString::TYPE_BOOL));
25382 +var_dump($q->get('r'));
25383 +var_dump($q->get('r', HttpQueryString::TYPE_ARRAY));
25384 +var_dump($q->get('r', HttpQueryString::TYPE_OBJECT));
25385 +
25386 +$q->set('z[0]=2');
25387 +$q->set(array('a'=>'b', 'c'=> "3.4"));
25388 +$q->set(array('a' => NULL));
25389 +
25390 +var_dump($q);
25391 +var_dump($array);
25392 +
25393 +echo "Done\n";
25394 +?>
25395 +--EXPECTF--
25396 +%aTEST
25397 +string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3"
25398 +NULL
25399 +string(1) "b"
25400 +int(0)
25401 +string(3) "hi!"
25402 +string(3) "3.4"
25403 +int(3)
25404 +float(3.4)
25405 +bool(true)
25406 +array(3) {
25407 + [0]=>
25408 + int(1)
25409 + [1]=>
25410 + int(2)
25411 + [2]=>
25412 + int(3)
25413 +}
25414 +array(3) {
25415 + [0]=>
25416 + int(1)
25417 + [1]=>
25418 + int(2)
25419 + [2]=>
25420 + int(3)
25421 +}
25422 +object(stdClass)#%d (%d) {
25423 + [0]=>
25424 + int(1)
25425 + [1]=>
25426 + int(2)
25427 + [2]=>
25428 + int(3)
25429 +}
25430 +object(HttpQueryString)#1 (2) {
25431 + ["queryArray%s]=>
25432 + array(3) {
25433 + ["c"]=>
25434 + string(3) "3.4"
25435 + ["r"]=>
25436 + array(3) {
25437 + [0]=>
25438 + int(1)
25439 + [1]=>
25440 + int(2)
25441 + [2]=>
25442 + int(3)
25443 + }
25444 + ["z"]=>
25445 + array(1) {
25446 + [0]=>
25447 + string(1) "2"
25448 + }
25449 + }
25450 + ["queryString%s]=>
25451 + string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2"
25452 +}
25453 +array(3) {
25454 + ["a"]=>
25455 + string(1) "b"
25456 + ["c"]=>
25457 + string(3) "3.4"
25458 + ["r"]=>
25459 + array(3) {
25460 + [0]=>
25461 + int(1)
25462 + [1]=>
25463 + int(2)
25464 + [2]=>
25465 + int(3)
25466 + }
25467 +}
25468 +Done
25469 \ No newline at end of file
25470 --- /dev/null
25471 +++ b/ext/http/tests/HttpQueryString_003.phpt
25472 @@ -0,0 +1,24 @@
25473 +--TEST--
25474 +HttpQueryString xlate
25475 +--SKIPIF--
25476 +<?php
25477 +include 'skip.inc';
25478 +checkmin("5.2.5");
25479 +checkext('iconv');
25480 +?>
25481 +--FILE--
25482 +<?php
25483 +echo "-TEST\n";
25484 +$qs = new HttpQueryString(false, "ä[0]=ü&ö[a]=ß");
25485 +var_dump($qs->get());
25486 +$qs->xlate("latin1", "utf8");
25487 +var_dump($qs->get());
25488 +$qs->xlate("utf8", "latin1");
25489 +var_dump($qs->get());
25490 +echo "Done\n";
25491 +--EXPECTF--
25492 +%aTEST
25493 +string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF"
25494 +string(41) "%C3%A4%5B0%5D=%C3%BC&%C3%B6%5Ba%5D=%C3%9F"
25495 +string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF"
25496 +Done
25497 --- /dev/null
25498 +++ b/ext/http/tests/HttpQueryString_004.phpt
25499 @@ -0,0 +1,54 @@
25500 +--TEST--
25501 +HttpQueryString w/ objects
25502 +--SKIPIF--
25503 +<?php
25504 +include 'skip.inc';
25505 +checkmin("5.2.5");
25506 +?>
25507 +--FILE--
25508 +<?php
25509 +echo "-TEST\n";
25510 +class test_props {
25511 + public $bar;
25512 + public $baz;
25513 + protected $dont_show;
25514 + private $dont_show2;
25515 + function __construct() {
25516 + $this->bar = (object) array("baz"=>1);
25517 + $this->dont_show = 'xxx';
25518 + $this->dont_show2 = 'zzz';
25519 + }
25520 +}
25521 +$foo = new test_props;
25522 +var_dump($q = new HttpQueryString(false, $foo));
25523 +$foo->bar->baz = 0;
25524 +var_dump($q->mod($foo));
25525 +echo "Done\n";
25526 +?>
25527 +--EXPECTF--
25528 +%aTEST
25529 +object(HttpQueryString)#3 (2) {
25530 + ["queryArray%s]=>
25531 + array(1) {
25532 + ["bar"]=>
25533 + array(1) {
25534 + ["baz"]=>
25535 + int(1)
25536 + }
25537 + }
25538 + ["queryString%s]=>
25539 + string(14) "bar%5Bbaz%5D=1"
25540 +}
25541 +object(HttpQueryString)#4 (2) {
25542 + ["queryArray%s]=>
25543 + array(1) {
25544 + ["bar"]=>
25545 + array(1) {
25546 + ["baz"]=>
25547 + int(0)
25548 + }
25549 + }
25550 + ["queryString%s]=>
25551 + string(14) "bar%5Bbaz%5D=0"
25552 +}
25553 +Done
25554 --- /dev/null
25555 +++ b/ext/http/tests/HttpRequestDataShare_001.phpt
25556 @@ -0,0 +1,38 @@
25557 +--TEST--
25558 +HttpRequestDataShare
25559 +--SKIPIF--
25560 +<?php
25561 +include "skip.inc";
25562 +checkurl("www.google.com");
25563 +checkcls("HttpRequestDataShare");
25564 +?>
25565 +--FILE--
25566 +<?php
25567 +echo "-TEST\n";
25568 +
25569 +$s = new HttpRequestDataShare;
25570 +$s->dns = true;
25571 +$s->cookie = true;
25572 +
25573 +$r1 = new HttpRequest("http://www.google.com/");
25574 +$r2 = new HttpRequest("http://www.google.com/");
25575 +
25576 +$r1->enableCookies();
25577 +$r2->enableCookies();
25578 +
25579 +$s->attach($r1);
25580 +$s->attach($r2);
25581 +
25582 +$r1->send();
25583 +$r2->send();
25584 +
25585 +$s->reset();
25586 +
25587 +var_dump(current($r1->getResponseCookies())->cookies["PREF"] === HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]);
25588 +
25589 +echo "Done\n";
25590 +?>
25591 +--EXPECTF--
25592 +%aTEST
25593 +bool(true)
25594 +Done
25595 --- /dev/null
25596 +++ b/ext/http/tests/HttpRequestDataShare_002.phpt
25597 @@ -0,0 +1,52 @@
25598 +--TEST--
25599 +HttpRequestDataShare global
25600 +--SKIPIF--
25601 +<?php
25602 +include "skip.inc";
25603 +checkurl("www.google.com");
25604 +checkcls("HttpRequestDataShare");
25605 +?>
25606 +--FILE--
25607 +<?php
25608 +echo "-TEST\n";
25609 +
25610 +$s = HttpRequestDataShare::singleton(true);
25611 +$s->cookie = true;
25612 +var_dump($s);
25613 +
25614 +$r1 = new HttpRequest("http://www.google.com/");
25615 +$r2 = new HttpRequest("http://www.google.com/");
25616 +
25617 +$r1->enableCookies();
25618 +$r2->enableCookies();
25619 +
25620 +$s->attach($r1);
25621 +$s->attach($r2);
25622 +
25623 +$r1->send();
25624 +$r2->send();
25625 +
25626 +$s->reset();
25627 +
25628 +if (current($r1->getResponseCookies())->cookies["PREF"] !== HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]) {
25629 + var_dump(
25630 + current($r1->getResponseCookies())->cookies["PREF"],
25631 + HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]
25632 + );
25633 +}
25634 +
25635 +echo "Done\n";
25636 +?>
25637 +--EXPECTF--
25638 +%aTEST
25639 +object(HttpRequestDataShare)#1 (4) {
25640 + ["cookie"]=>
25641 + bool(true)
25642 + ["dns"]=>
25643 + bool(true)
25644 + ["ssl"]=>
25645 + bool(false)
25646 + ["connect"]=>
25647 + bool(false)
25648 +}
25649 +Done
25650 --- /dev/null
25651 +++ b/ext/http/tests/HttpRequestPool_001.phpt
25652 @@ -0,0 +1,51 @@
25653 +--TEST--
25654 +HttpRequestPool
25655 +--SKIPIF--
25656 +<?php
25657 +include 'skip.inc';
25658 +checkmin("5.2.5");
25659 +checkcls('HttpRequestPool');
25660 +checkurl('www.php.net');
25661 +checkurl('dev.iworks.at');
25662 +?>
25663 +--FILE--
25664 +<?php
25665 +echo "-TEST\n";
25666 +$post = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
25667 +$post->addPostFields(array('a'=>1,'b'=>2)) ;
25668 +
25669 +$pool = new HttpRequestPool(
25670 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
25671 + $post
25672 +);
25673 +
25674 +$pool->send();
25675 +
25676 +foreach ($pool as $req) {
25677 + echo $req->getUrl(), '=',
25678 + $req->getResponseCode(), ':',
25679 + $req->getResponseMessage()->getResponseCode(), "\n";
25680 +}
25681 +
25682 +foreach ($pool as $req) {
25683 + try {
25684 + $pool->attach(new HttpRequest('http://foo.bar'));
25685 + } catch (HttpRequestPoolException $x) {
25686 + echo ".\n";
25687 + }
25688 +}
25689 +
25690 +foreach ($pool as $req) {
25691 + $pool->detach($req);
25692 +}
25693 +
25694 +echo "Done\n";
25695 +?>
25696 +
25697 +--EXPECTF--
25698 +%aTEST
25699 +http://www.php.net/=200:200
25700 +http://dev.iworks.at/ext-http/.print_request.php=200:200
25701 +.
25702 +.
25703 +Done
25704 --- /dev/null
25705 +++ b/ext/http/tests/HttpRequestPool_002.phpt
25706 @@ -0,0 +1,51 @@
25707 +--TEST--
25708 +extending HttpRequestPool
25709 +--SKIPIF--
25710 +<?php
25711 +include 'skip.inc';
25712 +checkcls('HttpRequestPool');
25713 +checkurl('www.php.net');
25714 +?>
25715 +--FILE--
25716 +<?php
25717 +echo "-TEST\n";
25718 +
25719 +class MyPool extends HttpRequestPool
25720 +{
25721 + public function send()
25722 + {
25723 + while ($this->socketPerform()) {
25724 + if (!$this->socketSelect()) {
25725 + throw new HttpSocketException;
25726 + }
25727 + }
25728 + }
25729 +
25730 + protected final function socketPerform()
25731 + {
25732 + $result = parent::socketPerform();
25733 +
25734 + echo ".";
25735 + foreach ($this->getFinishedRequests() as $r) {
25736 + echo "=", $r->getResponseCode(), "=";
25737 + $this->detach($r);
25738 + }
25739 +
25740 + return $result;
25741 + }
25742 +}
25743 +
25744 +$pool = new MyPool(
25745 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
25746 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD),
25747 + new HttpRequest('http://www.php.net/', HTTP_METH_HEAD)
25748 +);
25749 +
25750 +$pool->send();
25751 +
25752 +echo "\nDone\n";
25753 +?>
25754 +--EXPECTREGEX--
25755 +.+TEST
25756 +\.*=200=\.*=200=\.*=200=
25757 +Done
25758 --- /dev/null
25759 +++ b/ext/http/tests/HttpRequestPool_003.phpt
25760 @@ -0,0 +1,175 @@
25761 +--TEST--
25762 +HttpRequestPool chain
25763 +--SKIPIF--
25764 +<?php
25765 +include 'skip.inc';
25766 +checkcls('HttpRequest');
25767 +checkcls('HttpRequestPool');
25768 +?>
25769 +--FILE--
25770 +<?php
25771 +
25772 +echo "-TEST\n";
25773 +
25774 +set_time_limit(0);
25775 +ini_set('error_reporting', E_ALL);
25776 +ini_set('html_errors', 0);
25777 +
25778 +class Pool extends HttpRequestPool
25779 +{
25780 + private $all;
25781 + private $rem;
25782 + private $dir;
25783 +
25784 + public final function __construct($urls_file = 'urls.txt', $cache_dir = 'HttpRequestPool_cache')
25785 + {
25786 + $this->dir = (is_dir($cache_dir) or @mkdir($cache_dir)) ? $cache_dir : null;
25787 +
25788 + foreach (array_map('trim', file($urls_file)) as $url) {
25789 + $this->all[$url] = $this->dir ? $this->dir .'/'. md5($url) : null;
25790 + }
25791 +
25792 + $this->send();
25793 + }
25794 +
25795 + public final function send()
25796 + {
25797 + if (RMAX) {
25798 + $now = array_slice($this->all, 0, RMAX);
25799 + $this->rem = array_slice($this->all, RMAX);
25800 + } else {
25801 + $now = $urls;
25802 + $this->rem = array();
25803 + }
25804 +
25805 + foreach ($now as $url => $file) {
25806 + $this->attach(
25807 + new HttpRequest(
25808 + $url,
25809 + HttpRequest::METH_GET,
25810 + array(
25811 + 'redirect' => 5,
25812 + 'compress' => GZIP,
25813 + 'timeout' => TOUT,
25814 + 'connecttimeout' => TOUT,
25815 + 'lastmodified' => is_file($file)?filemtime($file):0
25816 + )
25817 + )
25818 + );
25819 + }
25820 +
25821 + while ($this->socketPerform()) {
25822 + if (!$this->socketSelect()) {
25823 + throw new HttpSocketException;
25824 + }
25825 + }
25826 + }
25827 +
25828 + protected final function socketPerform()
25829 + {
25830 + try {
25831 + $rc = parent::socketPerform();
25832 + } catch (HttpRequestException $x) {
25833 + // a request may have thrown an exception,
25834 + // but it is still save to continue
25835 + echo $x->getMessage(), "\n";
25836 + }
25837 +
25838 + foreach ($this->getFinishedRequests() as $r) {
25839 + $this->detach($r);
25840 +
25841 + $u = $r->getUrl();
25842 + $c = $r->getResponseCode();
25843 + $b = $r->getResponseBody();
25844 +
25845 + printf("%d %s %d\n", $c, $u, strlen($b));
25846 +
25847 + if ($c == 200 && $this->dir) {
25848 + file_put_contents($this->all[$u], $b);
25849 + }
25850 +
25851 + if ($a = each($this->rem)) {
25852 + list($url, $file) = $a;
25853 + $this->attach(
25854 + new HttpRequest(
25855 + $url,
25856 + HttpRequest::METH_GET,
25857 + array(
25858 + 'redirect' => 5,
25859 + 'compress' => GZIP,
25860 + 'timeout' => TOUT,
25861 + 'connecttimeout' => TOUT,
25862 + 'lastmodified' => is_file($file)?filemtime($file):0
25863 + )
25864 + )
25865 + );
25866 + }
25867 + }
25868 + return $rc;
25869 + }
25870 +}
25871 +
25872 +define('GZIP', true);
25873 +define('TOUT', 50);
25874 +define('RMAX', 10);
25875 +chdir(dirname(__FILE__));
25876 +
25877 +$time = microtime(true);
25878 +$pool = new Pool();
25879 +printf("Elapsed: %0.3fs\n", microtime(true)-$time);
25880 +
25881 +echo "Done\n";
25882 +?>
25883 +--EXPECTF--
25884 +%aTEST
25885 +%d %s %d
25886 +%d %s %d
25887 +%d %s %d
25888 +%d %s %d
25889 +%d %s %d
25890 +%d %s %d
25891 +%d %s %d
25892 +%d %s %d
25893 +%d %s %d
25894 +%d %s %d
25895 +%d %s %d
25896 +%d %s %d
25897 +%d %s %d
25898 +%d %s %d
25899 +%d %s %d
25900 +%d %s %d
25901 +%d %s %d
25902 +%d %s %d
25903 +%d %s %d
25904 +%d %s %d
25905 +%d %s %d
25906 +%d %s %d
25907 +%d %s %d
25908 +%d %s %d
25909 +%d %s %d
25910 +%d %s %d
25911 +%d %s %d
25912 +%d %s %d
25913 +%d %s %d
25914 +%d %s %d
25915 +%d %s %d
25916 +%d %s %d
25917 +%d %s %d
25918 +%d %s %d
25919 +%d %s %d
25920 +%d %s %d
25921 +%d %s %d
25922 +%d %s %d
25923 +%d %s %d
25924 +%d %s %d
25925 +%d %s %d
25926 +%d %s %d
25927 +%d %s %d
25928 +%d %s %d
25929 +%d %s %d
25930 +%d %s %d
25931 +%d %s %d
25932 +%d %s %d
25933 +%d %s %d
25934 +Elapsed: %fs
25935 +Done
25936 --- /dev/null
25937 +++ b/ext/http/tests/HttpRequestPool_004.phpt
25938 @@ -0,0 +1,19 @@
25939 +--TEST--
25940 +HttpRequestPool::__destruct() invalid curl handle
25941 +--SKIPIF--
25942 +<?php
25943 +include 'skip.inc';
25944 +checkmin("5.2.5");
25945 +checkcls('HttpRequest');
25946 +checkcls('HttpRequestPool');
25947 +?>
25948 +--FILE--
25949 +<?php
25950 +echo "-TEST\n";
25951 +$p = new HttpRequestPool(new HttpRequest('http://example.com'));
25952 +$p = null;
25953 +echo "Done\n";
25954 +?>
25955 +--EXPECTF--
25956 +%aTEST
25957 +Done
25958 --- /dev/null
25959 +++ b/ext/http/tests/HttpRequestPool_005.phpt
25960 @@ -0,0 +1,46 @@
25961 +--TEST--
25962 +HttpRequestPool exception
25963 +--SKIPIF--
25964 +<?php
25965 +include 'skip.inc';
25966 +checkmin("5.2.5");
25967 +checkcls('HttpRequestPool');
25968 +?>
25969 +--FILE--
25970 +<?php
25971 +echo "-TEST\n";
25972 +
25973 +$p = new HttpRequestPool(new HttpRequest('http://_____'));
25974 +try {
25975 + $p->send();
25976 +} catch (HttpRequestPoolException $x) {
25977 + for ($i=0; $x; ++$i, $x = @$x->innerException) {
25978 + printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage());
25979 + }
25980 + var_dump($i);
25981 +}
25982 +$p = new HttpRequestPool(new HttpRequest('http://_____'), new HttpRequest('http://_____'));
25983 +try {
25984 + $p->send();
25985 +} catch (HttpRequestPoolException $x) {
25986 + for ($i=0; $x; ++$i, $x = @$x->innerException) {
25987 + printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage());
25988 + }
25989 + var_dump($i);
25990 +}
25991 +echo "Done\n";
25992 +?>
25993 +--EXPECTF--
25994 +%aTEST
25995 +HttpRequestPoolException: Exception caused by 2 inner exception(s)
25996 + HttpInvalidParamException: Empty or too short HTTP message: ''
25997 + HttpRequestException: %souldn't resolve host name; %s (http://_____/)
25998 +int(3)
25999 +HttpRequestPoolException: Exception caused by 4 inner exception(s)
26000 + HttpInvalidParamException: Empty or too short HTTP message: ''
26001 + HttpRequestException: %souldn't resolve host name; %s (http://_____/)
26002 + HttpInvalidParamException: Empty or too short HTTP message: ''
26003 + HttpRequestException: %souldn't resolve host name; %s (http://_____/)
26004 +int(5)
26005 +Done
26006 +
26007 --- /dev/null
26008 +++ b/ext/http/tests/HttpRequestPool_006.phpt
26009 @@ -0,0 +1,50 @@
26010 +--TEST--
26011 +HttpRequestPool detaching in callbacks
26012 +--SKIPIF--
26013 +<?php
26014 +include 'skip.inc';
26015 +checkcls("HttpRequestPool");
26016 +checkurl("at.php.net");
26017 +checkurl("de.php.net");
26018 +?>
26019 +--FILE--
26020 +<?php
26021 +echo "-TEST\n";
26022 +class r extends HttpRequest {
26023 + function onProgress() {
26024 + static $i = array();
26025 + if (empty($i[$this->getUrl()])) {
26026 + $i[$this->getUrl()] = true;
26027 + try {
26028 + $GLOBALS['p']->detach($this);
26029 + } catch (Exception $ex) {
26030 + echo $ex, "\n";
26031 + }
26032 + }
26033 + }
26034 + function onFinish() {
26035 + $GLOBALS['p']->detach($this);
26036 + }
26037 +}
26038 +$p = new HttpRequestPool(new r("http://at.php.net"), new r("http://de.php.net"));
26039 +$p->send();
26040 +var_dump($p->getAttachedRequests());
26041 +echo "Done\n";
26042 +?>
26043 +--EXPECTF--
26044 +%aTEST
26045 +exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d
26046 +Stack trace:
26047 +#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r))
26048 +#1 [internal function]: r->onProgress(Array)
26049 +#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send()
26050 +#3 {main}
26051 +exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d
26052 +Stack trace:
26053 +#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r))
26054 +#1 [internal function]: r->onProgress(Array)
26055 +#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send()
26056 +#3 {main}
26057 +array(0) {
26058 +}
26059 +Done
26060 --- /dev/null
26061 +++ b/ext/http/tests/HttpRequest_001.phpt
26062 @@ -0,0 +1,51 @@
26063 +--TEST--
26064 +HttpRequest options
26065 +--SKIPIF--
26066 +<?php
26067 +include 'skip.inc';
26068 +checkmin("5.2.5");
26069 +checkcls('HttpRequest');
26070 +?>
26071 +--FILE--
26072 +<?php
26073 +echo "-TEST\n";
26074 +$r1 = new HttpRequest(null, 0, array('redirect'=>11, 'headers'=>array('X-Foo'=>'Bar')));
26075 +$r2 = new HttpRequest;
26076 +$r2->setOptions(array('redirect'=>99, 'headers'=>array('X-Bar'=>'Foo')));
26077 +$o1 = $r1->getOptions();
26078 +$o2 = $r2->getOptions();
26079 +$r1->setOptions($o2);
26080 +$r2->setOptions($o1);
26081 +print_r(array($o1, $o2));
26082 +var_dump(serialize($r1->getOptions()) === serialize($r2->getOptions()));
26083 +$r1 = null;
26084 +$r2 = null;
26085 +?>
26086 +--EXPECTF--
26087 +%aTEST
26088 +Array
26089 +(
26090 + [0] => Array
26091 + (
26092 + [headers] => Array
26093 + (
26094 + [X-Foo] => Bar
26095 + [X-Bar] => Foo
26096 + )
26097 +
26098 + [redirect] => 11
26099 + )
26100 +
26101 + [1] => Array
26102 + (
26103 + [headers] => Array
26104 + (
26105 + [X-Bar] => Foo
26106 + [X-Foo] => Bar
26107 + )
26108 +
26109 + [redirect] => 99
26110 + )
26111 +
26112 +)
26113 +bool(false)
26114 --- /dev/null
26115 +++ b/ext/http/tests/HttpRequest_002.phpt
26116 @@ -0,0 +1,86 @@
26117 +--TEST--
26118 +HttpRequest GET/POST
26119 +--SKIPIF--
26120 +<?php
26121 +include 'skip.inc';
26122 +checkmin("5.2.5");
26123 +checkcls('HttpRequest');
26124 +checkurl('www.google.com');
26125 +checkurl('dev.iworks.at');
26126 +?>
26127 +--FILE--
26128 +<?php
26129 +echo "-TEST\n";
26130 +
26131 +$r = new HttpRequest('http://www.google.com', HttpRequest::METH_GET);
26132 +$r->send();
26133 +print_r($r->getResponseInfo());
26134 +
26135 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
26136 +$r->addCookies(array('MyCookie' => 'foobar'));
26137 +$r->addQueryData(array('gq'=>'foobar','gi'=>10));
26138 +$r->addPostFields(array('pq'=>'foobar','pi'=>10));
26139 +$r->addPostFile('upload', dirname(__FILE__).'/data.txt', 'text/plain');
26140 +$r->send();
26141 +echo $r->getResponseBody();
26142 +var_dump($r->getResponseMessage()->getResponseCode());
26143 +
26144 +echo "Done";
26145 +?>
26146 +--EXPECTF--
26147 +%aTEST
26148 +Array
26149 +(
26150 + [effective_url] => http://www.google.com/
26151 + [response_code] => 302
26152 + [total_time] => %f
26153 + [namelookup_time] => %f
26154 + [connect_time] => %f
26155 + [pretransfer_time] => %f
26156 + [size_upload] => %d
26157 + [size_download] => %d
26158 + [speed_download] => %d
26159 + [speed_upload] => %d
26160 + [header_size] => %d
26161 + [request_size] => %d
26162 + [ssl_verifyresult] => %d
26163 + [filetime] => -1
26164 + [content_length_download] => %d
26165 + [content_length_upload] => %d
26166 + [starttransfer_time] => %f
26167 + [content_type] => %s
26168 + [redirect_time] => %d
26169 + [redirect_count] => %d
26170 + [connect_code] => %d
26171 + [httpauth_avail] => %d
26172 + [proxyauth_avail] => %d
26173 + [os_errno] => %d
26174 + [num_connects] => %d
26175 + [ssl_engines] => Array
26176 + %a
26177 + [cookies] => Array
26178 + %a
26179 + [error] =>
26180 +)
26181 +Array
26182 +(
26183 + [gq] => foobar
26184 + [gi] => 10
26185 + [pq] => foobar
26186 + [pi] => 10
26187 + [MyCookie] => foobar
26188 +)
26189 +Array
26190 +(
26191 + [upload] => Array
26192 + (
26193 + [name] => data.txt
26194 + [type] => text/plain
26195 + [tmp_name] => %a
26196 + [error] => 0
26197 + [size] => 1010
26198 + )
26199 +
26200 +)
26201 +int(200)
26202 +Done
26203 --- /dev/null
26204 +++ b/ext/http/tests/HttpRequest_003.phpt
26205 @@ -0,0 +1,54 @@
26206 +--TEST--
26207 +HttpRequest SSL
26208 +--SKIPIF--
26209 +<?php
26210 +include 'skip.inc';
26211 +checkmin("5.2.5");
26212 +checkurl('arweb.info');
26213 +skipif(!http_support(HTTP_SUPPORT_SSLREQUESTS), 'need ssl-request support')
26214 +?>
26215 +--FILE--
26216 +<?php
26217 +echo "-TEST\n";
26218 +$o = array('redirect' => '3', 'ssl' => array('version' => '3', 'verifyhost' => '1'));
26219 +$r = new HttpRequest('https://ssl.irmler.at/iworks/data.txt');
26220 +$r->setOptions($o);
26221 +$r->send();
26222 +var_dump($r->getResponseBody());
26223 +var_dump(is_object($r->getResponseMessage()));
26224 +var_dump(is_object($r->getResponseMessage()));
26225 +var_dump(is_object($r->getResponseMessage()));
26226 +var_dump($o);
26227 +$r->setOptions($o);
26228 +$r->send();
26229 +var_dump($o);
26230 +?>
26231 +--EXPECTF--
26232 +%aTEST
26233 +string(10) "1234567890"
26234 +bool(true)
26235 +bool(true)
26236 +bool(true)
26237 +array(2) {
26238 + ["redirect"]=>
26239 + string(1) "3"
26240 + ["ssl"]=>
26241 + array(2) {
26242 + ["version"]=>
26243 + string(1) "3"
26244 + ["verifyhost"]=>
26245 + string(1) "1"
26246 + }
26247 +}
26248 +array(2) {
26249 + ["redirect"]=>
26250 + string(1) "3"
26251 + ["ssl"]=>
26252 + array(2) {
26253 + ["version"]=>
26254 + string(1) "3"
26255 + ["verifyhost"]=>
26256 + string(1) "1"
26257 + }
26258 +}
26259 +
26260 --- /dev/null
26261 +++ b/ext/http/tests/HttpRequest_004.phpt
26262 @@ -0,0 +1,162 @@
26263 +--TEST--
26264 +HttpRequest multiple posts
26265 +--SKIPIF--
26266 +<?php
26267 +include 'skip.inc';
26268 +checkcls('HttpRequest');
26269 +?>
26270 +--FILE--
26271 +<?php
26272 +echo "-TEST\n";
26273 +
26274 +$fields = array(
26275 + array('int' => 1, 'dbl' => M_PI),
26276 + array('str' => 'something', 'nil' => null)
26277 +);
26278 +
26279 +echo "\nFirst Request\n";
26280 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HttpRequest::METH_POST);
26281 +$r->setPostFields($fields[0]);
26282 +$r->addPostFields($fields[1]);
26283 +var_dump($r->send()->getBody());
26284 +var_dump($fields);
26285 +
26286 +echo "\nSecond Request\n";
26287 +$r->setPostFields($fields);
26288 +var_dump($r->send()->getBody());
26289 +var_dump($fields);
26290 +
26291 +echo "\nThird Request\n";
26292 +$r->addPostFields(array('x' => 'X'));
26293 +var_dump($r->send()->getBody());
26294 +var_dump($fields);
26295 +
26296 +echo "\nFourth Request\n";
26297 +$r->setPostFields(array());
26298 +var_dump($r->send()->getBody());
26299 +var_dump($fields);
26300 +
26301 +echo "Done\n";
26302 +?>
26303 +--EXPECTF--
26304 +%aTEST
26305 +
26306 +First Request
26307 +string(%d) "Array
26308 +(
26309 + [int] => 1
26310 + [dbl] => 3.1415926535898
26311 + [str] => something
26312 + [nil] =>
26313 +)
26314 +string(44) "int=1&dbl=3.1415926535898&str=something&nil="
26315 +"
26316 +array(2) {
26317 + [0]=>
26318 + array(2) {
26319 + ["int"]=>
26320 + int(1)
26321 + ["dbl"]=>
26322 + float(3.1415926535898)
26323 + }
26324 + [1]=>
26325 + array(2) {
26326 + ["str"]=>
26327 + string(9) "something"
26328 + ["nil"]=>
26329 + NULL
26330 + }
26331 +}
26332 +
26333 +Second Request
26334 +string(%d) "Array
26335 +(
26336 + [0] => Array
26337 + (
26338 + [int] => 1
26339 + [dbl] => 3.1415926535898
26340 + )
26341 +
26342 + [1] => Array
26343 + (
26344 + [str] => something
26345 + [nil] =>
26346 + )
26347 +
26348 +)
26349 +string(72) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D="
26350 +"
26351 +array(2) {
26352 + [0]=>
26353 + array(2) {
26354 + ["int"]=>
26355 + int(1)
26356 + ["dbl"]=>
26357 + float(3.1415926535898)
26358 + }
26359 + [1]=>
26360 + array(2) {
26361 + ["str"]=>
26362 + string(9) "something"
26363 + ["nil"]=>
26364 + NULL
26365 + }
26366 +}
26367 +
26368 +Third Request
26369 +string(%d) "Array
26370 +(
26371 + [0] => Array
26372 + (
26373 + [int] => 1
26374 + [dbl] => 3.1415926535898
26375 + )
26376 +
26377 + [1] => Array
26378 + (
26379 + [str] => something
26380 + [nil] =>
26381 + )
26382 +
26383 + [x] => X
26384 +)
26385 +string(76) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D=&x=X"
26386 +"
26387 +array(2) {
26388 + [0]=>
26389 + array(2) {
26390 + ["int"]=>
26391 + int(1)
26392 + ["dbl"]=>
26393 + float(3.1415926535898)
26394 + }
26395 + [1]=>
26396 + array(2) {
26397 + ["str"]=>
26398 + string(9) "something"
26399 + ["nil"]=>
26400 + NULL
26401 + }
26402 +}
26403 +
26404 +Fourth Request
26405 +string(13) "string(0) ""
26406 +"
26407 +array(2) {
26408 + [0]=>
26409 + array(2) {
26410 + ["int"]=>
26411 + int(1)
26412 + ["dbl"]=>
26413 + float(3.1415926535898)
26414 + }
26415 + [1]=>
26416 + array(2) {
26417 + ["str"]=>
26418 + string(9) "something"
26419 + ["nil"]=>
26420 + NULL
26421 + }
26422 +}
26423 +Done
26424 +
26425 --- /dev/null
26426 +++ b/ext/http/tests/HttpRequest_005.phpt
26427 @@ -0,0 +1,24 @@
26428 +--TEST--
26429 +HttpRequest accessors
26430 +--SKIPIF--
26431 +<?php
26432 +include 'skip.inc';
26433 +checkcls('HttpRequest');
26434 +?>
26435 +--FILE--
26436 +<?php
26437 +echo "-TEST\n";
26438 +error_reporting(0);
26439 +$r = new HttpRequest;
26440 +foreach (get_class_methods('HttpRequest') as $method) {
26441 + try {
26442 + if (strlen($method) > 3 && substr($method, 0, 3) == 'get')
26443 + $x = $r->$method();
26444 + } catch (HttpException $e) {
26445 + }
26446 +}
26447 +echo "Done\n";
26448 +?>
26449 +--EXPECTF--
26450 +%aTEST
26451 +Done
26452 --- /dev/null
26453 +++ b/ext/http/tests/HttpRequest_006.phpt
26454 @@ -0,0 +1,147 @@
26455 +--TEST--
26456 +HttpRequest XMLRPC
26457 +--SKIPIF--
26458 +<?php
26459 +include 'skip.inc';
26460 +checkext('xmlrpc');
26461 +checkcls('HttpRequest');
26462 +?>
26463 +--FILE--
26464 +<?php
26465 +echo "-TEST\n";
26466 +
26467 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
26468 +$r->setContentType('text/xml');
26469 +$r->setBody(xmlrpc_encode_request('testMethod', array('foo' => 'bar')));
26470 +var_dump($r->send());
26471 +var_dump($r->send());
26472 +var_dump($r->send());
26473 +
26474 +echo "Done\n";
26475 +?>
26476 +--EXPECTF--
26477 +%aTEST
26478 +object(HttpMessage)#%d (%d) {
26479 + ["type:protected"]=>
26480 + int(2)
26481 + ["body:protected"]=>
26482 + string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
26483 +<methodCall>
26484 +<methodName>testMethod</methodName>
26485 +<params>
26486 + <param>
26487 + <value>
26488 + <struct>
26489 + <member>
26490 + <name>foo</name>
26491 + <value>
26492 + <string>bar</string>
26493 + </value>
26494 + </member>
26495 + </struct>
26496 + </value>
26497 + </param>
26498 +</params>
26499 +</methodCall>
26500 +"
26501 +"
26502 + ["requestMethod:protected"]=>
26503 + string(0) ""
26504 + ["requestUrl:protected"]=>
26505 + string(0) ""
26506 + ["responseStatus:protected"]=>
26507 + string(2) "OK"
26508 + ["responseCode:protected"]=>
26509 + int(200)
26510 + ["httpVersion:protected"]=>
26511 + float(1.1)
26512 + ["headers:protected"]=>
26513 + array(6) {
26514 + %a
26515 + }
26516 + ["parentMessage:protected"]=>
26517 + NULL
26518 +}
26519 +object(HttpMessage)#%d (%d) {
26520 + ["type:protected"]=>
26521 + int(2)
26522 + ["body:protected"]=>
26523 + string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
26524 +<methodCall>
26525 +<methodName>testMethod</methodName>
26526 +<params>
26527 + <param>
26528 + <value>
26529 + <struct>
26530 + <member>
26531 + <name>foo</name>
26532 + <value>
26533 + <string>bar</string>
26534 + </value>
26535 + </member>
26536 + </struct>
26537 + </value>
26538 + </param>
26539 +</params>
26540 +</methodCall>
26541 +"
26542 +"
26543 + ["requestMethod:protected"]=>
26544 + string(0) ""
26545 + ["requestUrl:protected"]=>
26546 + string(0) ""
26547 + ["responseStatus:protected"]=>
26548 + string(2) "OK"
26549 + ["responseCode:protected"]=>
26550 + int(200)
26551 + ["httpVersion:protected"]=>
26552 + float(1.1)
26553 + ["headers:protected"]=>
26554 + array(6) {
26555 + %a
26556 + }
26557 + ["parentMessage:protected"]=>
26558 + NULL
26559 +}
26560 +object(HttpMessage)#%d (%d) {
26561 + ["type:protected"]=>
26562 + int(2)
26563 + ["body:protected"]=>
26564 + string(309) "string(294) "<?xml version="1.0" encoding="iso-8859-1%s]>
26565 +<methodCall>
26566 +<methodName>testMethod</methodName>
26567 +<params>
26568 + <param>
26569 + <value>
26570 + <struct>
26571 + <member>
26572 + <name>foo</name>
26573 + <value>
26574 + <string>bar</string>
26575 + </value>
26576 + </member>
26577 + </struct>
26578 + </value>
26579 + </param>
26580 +</params>
26581 +</methodCall>
26582 +"
26583 +"
26584 + ["requestMethod:protected"]=>
26585 + string(0) ""
26586 + ["requestUrl:protected"]=>
26587 + string(0) ""
26588 + ["responseStatus:protected"]=>
26589 + string(2) "OK"
26590 + ["responseCode:protected"]=>
26591 + int(200)
26592 + ["httpVersion:protected"]=>
26593 + float(1.1)
26594 + ["headers:protected"]=>
26595 + array(6) {
26596 + %a
26597 + }
26598 + ["parentMessage:protected"]=>
26599 + NULL
26600 +}
26601 +Done
26602 --- /dev/null
26603 +++ b/ext/http/tests/HttpRequest_007.phpt
26604 @@ -0,0 +1,63 @@
26605 +--TEST--
26606 +HttpRequest PUT
26607 +--SKIPIF--
26608 +<?php
26609 +include 'skip.inc';
26610 +checkcls('HttpRequest');
26611 +?>
26612 +--FILE--
26613 +<?php
26614 +echo "-TEST\n";
26615 +
26616 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
26617 +$r->recordHistory = true;
26618 +$r->addHeaders(array('content-type' => 'text/plain'));
26619 +$r->setPutFile(__FILE__);
26620 +$r->send();
26621 +var_dump($r->getHistory()->toString(true));
26622 +echo "Done\n";
26623 +?>
26624 +--EXPECTF--
26625 +%aTEST
26626 +string(%d) "PUT /ext-http/.print_put.php5 HTTP/1.1
26627 +User-Agent: PECL::HTTP/%a
26628 +Host: dev.iworks.at
26629 +Accept: */*
26630 +Content-Type: text/plain
26631 +Content-Length: %d
26632 +Expect: 100-continue
26633 +
26634 +<?php
26635 +echo "-TEST\n";
26636 +
26637 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
26638 +$r->recordHistory = true;
26639 +$r->addHeaders(array('content-type' => 'text/plain'));
26640 +$r->setPutFile(__FILE__);
26641 +$r->send();
26642 +var_dump($r->getHistory()->toString(true));
26643 +echo "Done\n";
26644 +?>
26645 +
26646 +HTTP/1.1 100 Continue
26647 +HTTP/1.1 200 OK
26648 +Date: %a
26649 +Server: %a
26650 +Vary: Accept-Encoding
26651 +Content-Length: %d
26652 +Content-Type: text/html
26653 +
26654 +<?php
26655 +echo "-TEST\n";
26656 +
26657 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_put.php5', HTTP_METH_PUT);
26658 +$r->recordHistory = true;
26659 +$r->addHeaders(array('content-type' => 'text/plain'));
26660 +$r->setPutFile(__FILE__);
26661 +$r->send();
26662 +var_dump($r->getHistory()->toString(true));
26663 +echo "Done\n";
26664 +?>
26665 +
26666 +"
26667 +Done
26668 --- /dev/null
26669 +++ b/ext/http/tests/HttpRequest_008.phpt
26670 @@ -0,0 +1,32 @@
26671 +--TEST--
26672 +HttpRequest custom request method
26673 +--SKIPIF--
26674 +<?php
26675 +include 'skip.inc';
26676 +checkcls('HttpRequest');
26677 +?>
26678 +--FILE--
26679 +<?php
26680 +echo "-TEST\n";
26681 +
26682 +HttpRequest::methodRegister('foobar');
26683 +$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HttpRequest::METH_FOOBAR);
26684 +$r->setContentType('text/plain');
26685 +$r->setBody('Yep, this is FOOBAR!');
26686 +var_dump($r->send()->getResponseCode());
26687 +var_dump($r->getRawRequestMessage());
26688 +
26689 +echo "Done\n";
26690 +?>
26691 +--EXPECTF--
26692 +%aTEST
26693 +int(200)
26694 +string(%d) "FOOBAR /ext-http/.print_request.php HTTP/1.1
26695 +User-Agent: %a
26696 +Host: dev.iworks.at
26697 +Accept: */*
26698 +Content-Type: text/plain
26699 +Content-Length: 20
26700 +
26701 +Yep, this is FOOBAR!"
26702 +Done
26703 --- /dev/null
26704 +++ b/ext/http/tests/HttpRequest_009.phpt
26705 @@ -0,0 +1,48 @@
26706 +--TEST--
26707 +HttpRequest callbacks
26708 +--SKIPIF--
26709 +<?php
26710 +include 'skip.inc';
26711 +checkcls('HttpRequest');
26712 +?>
26713 +--FILE--
26714 +<?php
26715 +echo "-TEST\n";
26716 +
26717 +class _R extends HttpRequest
26718 +{
26719 + function onProgress($progress)
26720 + {
26721 + print_r($progress);
26722 + }
26723 +
26724 + function onFinish()
26725 + {
26726 + var_dump($this->getResponseCode());
26727 + }
26728 +}
26729 +
26730 +$r = new _R('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST);
26731 +$r->addPostFile('upload', __FILE__, 'text/plain');
26732 +$r->send();
26733 +
26734 +echo "Done\n";
26735 +?>
26736 +--EXPECTF--
26737 +%aTEST
26738 +Array
26739 +(
26740 + [dltotal] => %f
26741 + [dlnow] => %f
26742 + [ultotal] => %f
26743 + [ulnow] => %f
26744 +)
26745 +%array
26746 +(
26747 + [dltotal] => %f
26748 + [dlnow] => %f
26749 + [ultotal] => %f
26750 + [ulnow] => %f
26751 +)
26752 +int(200)
26753 +Done
26754 --- /dev/null
26755 +++ b/ext/http/tests/HttpRequest_010.phpt
26756 @@ -0,0 +1,48 @@
26757 +--TEST--
26758 +HttpRequest cookie API
26759 +--SKIPIF--
26760 +<?php
26761 +include 'skip.inc';
26762 +checkmin("5.2.5");
26763 +checkcls("HttpRequest");
26764 +?>
26765 +--FILE--
26766 +<?php
26767 +echo "-TEST\n";
26768 +
26769 +$r = new HttpRequest("http://dev.iworks.at/ext-http/.cookie.php");
26770 +
26771 +$r->send();
26772 +$c[0] = $r->getResponseInfo("cookies");
26773 +if (!empty($c[0])) {
26774 + var_dump('$c[0]', $c[0]);
26775 +}
26776 +
26777 +var_dump($r->enableCookies());
26778 +$r->send();
26779 +
26780 +$c[1] = $r->getResponseInfo("cookies");
26781 +if (empty($c[1])) {
26782 + var_dump('$c[1]', $c[1]);
26783 +}
26784 +
26785 +var_dump($r->resetCookies());
26786 +$r->send();
26787 +
26788 +$c[2] = $r->getResponseInfo("cookies");
26789 +if ($c[1] === $c[2]) {
26790 + var_dump('$c[1]', $c[1], '$c[2]', $c[2]);
26791 +}
26792 +
26793 +$r->send();
26794 +$c[3] = $r->getResponseInfo("cookies");
26795 +if ($c[2] !== $c[3]) {
26796 + var_dump('$c[2]', $c[2], '$c[3]', $c[3]);
26797 +}
26798 +
26799 +echo "Done\n";
26800 +--EXPECTF--
26801 +%aTEST
26802 +bool(true)
26803 +bool(true)
26804 +Done
26805 --- /dev/null
26806 +++ b/ext/http/tests/HttpResponse_001.phpt
26807 @@ -0,0 +1,25 @@
26808 +--TEST--
26809 +HttpResponse - send data with caching headers
26810 +--SKIPIF--
26811 +<?php
26812 +include 'skip.inc';
26813 +checkmin("5.2.5");
26814 +checkcgi();
26815 +?>
26816 +--FILE--
26817 +<?php
26818 +HttpResponse::setCache(true);
26819 +HttpResponse::setCacheControl('public', 3600);
26820 +HttpResponse::setData('foobar');
26821 +HttpResponse::send();
26822 +?>
26823 +--EXPECTF--
26824 +X-Powered-By: PHP/%a
26825 +Cache-Control: public, must-revalidate, max-age=3600
26826 +Last-Modified: %a, %d %a 20%d %d:%d:%d GMT
26827 +Content-Type: %a
26828 +Accept-Ranges: bytes
26829 +ETag: "3858f62230ac3c915f300c664312c63f"
26830 +Content-Length: 6
26831 +
26832 +foobar
26833 --- /dev/null
26834 +++ b/ext/http/tests/HttpResponse_002.phpt
26835 @@ -0,0 +1,25 @@
26836 +--TEST--
26837 +HttpResponse - send gzipped file
26838 +--SKIPIF--
26839 +<?php
26840 +include 'skip.inc';
26841 +checkmin("5.2.5");
26842 +checkcgi();
26843 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
26844 +?>
26845 +--ENV--
26846 +HTTP_ACCEPT_ENCODING=gzip
26847 +--FILE--
26848 +<?php
26849 +HttpResponse::setGzip(true);
26850 +HttpResponse::setFile(__FILE__);
26851 +HttpResponse::send();
26852 +?>
26853 +--EXPECTF--
26854 +X-Powered-By: PHP/%a
26855 +Content-Type: %a
26856 +Accept-Ranges: bytes
26857 +Content-Encoding: gzip
26858 +Vary: Accept-Encoding
26859 +
26860 +%a
26861 --- /dev/null
26862 +++ b/ext/http/tests/HttpResponse_003.phpt
26863 @@ -0,0 +1,30 @@
26864 +--TEST--
26865 +HttpResponse - send gzipped file with caching headers
26866 +--SKIPIF--
26867 +<?php
26868 +include 'skip.inc';
26869 +checkmin("5.2.5");
26870 +checkcgi();
26871 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
26872 +?>
26873 +--ENV--
26874 +HTTP_ACCEPT_ENCODING=gzip
26875 +--FILE--
26876 +<?php
26877 +HttpResponse::setGzip(true);
26878 +HttpResponse::setCache(true);
26879 +HttpResponse::setCacheControl('public', 3600);
26880 +HttpResponse::setFile(__FILE__);
26881 +HttpResponse::send();
26882 +?>
26883 +--EXPECTF--
26884 +X-Powered-By: PHP/%a
26885 +Cache-Control: public, must-revalidate, max-age=3600
26886 +Last-Modified: %a, %d %a 20%d %d:%d:%d GMT
26887 +Content-Type: %a
26888 +Accept-Ranges: bytes
26889 +ETag: "%a"
26890 +Content-Encoding: gzip
26891 +Vary: Accept-Encoding
26892 +
26893 +%a
26894 --- /dev/null
26895 +++ b/ext/http/tests/HttpResponse_004.phpt
26896 @@ -0,0 +1,27 @@
26897 +--TEST--
26898 +HttpResponse - send cached gzipped data
26899 +--SKIPIF--
26900 +<?php
26901 +include 'skip.inc';
26902 +checkcgi();
26903 +checkmin("5.2.7");
26904 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
26905 +?>
26906 +--ENV--
26907 +HTTP_IF_NONE_MATCH="900150983cd24fb0d6963f7d28e17f72"
26908 +HTTP_ACCEPT_ENCODING=gzip
26909 +--FILE--
26910 +<?php
26911 +HttpResponse::setGzip(true);
26912 +HttpResponse::setCache(true);
26913 +HttpResponse::setCacheControl('public', 3600);
26914 +HttpResponse::setData("abc");
26915 +HttpResponse::send();
26916 +?>
26917 +--EXPECTF--
26918 +Status: 304%s
26919 +X-Powered-By: PHP/%s
26920 +Cache-Control: public, must-revalidate, max-age=3600
26921 +Last-Modified: %s
26922 +Accept-Ranges: bytes
26923 +ETag: "900150983cd24fb0d6963f7d28e17f72"
26924 --- /dev/null
26925 +++ b/ext/http/tests/HttpResponse_005.phpt
26926 @@ -0,0 +1,24 @@
26927 +--TEST--
26928 +HttpResponse file not found
26929 +--SKIPIF--
26930 +<?php
26931 +include 'skip.inc';
26932 +checkcgi();
26933 +checkmin("5.2.5");
26934 +?>
26935 +--FILE--
26936 +<?php
26937 +ini_set("error_reporting", 0);
26938 +ini_set("default_mimetype", "text/plain");
26939 +
26940 +HttpResponse::setContentType("application/pdf");
26941 +HttpResponse::setContentDisposition("doc.pdf");
26942 +HttpResponse::setFile("__nonexistant__.pdf");
26943 +HttpResponse::send();
26944 +?>
26945 +--EXPECTF--
26946 +Status: 404%s
26947 +X-Powered-By: PHP/%s
26948 +Content-Type: text/plain
26949 +
26950 +File not found
26951 --- /dev/null
26952 +++ b/ext/http/tests/allowed_methods_002.phpt
26953 @@ -0,0 +1,21 @@
26954 +--TEST--
26955 +allowed methods
26956 +--SKIPIF--
26957 +<?php
26958 +include 'skip.inc';
26959 +checkcgi();
26960 +checkmin("5.2.5");
26961 +?>
26962 +--FILE--
26963 +<?php
26964 +include 'log.inc';
26965 +log_prepare(_AMETH_LOG);
26966 +ini_set('http.request.methods.allowed', 'POST');
26967 +echo "Done\n";
26968 +?>
26969 +--EXPECTF--
26970 +Status: 405%s
26971 +X-Powered-By: PHP/%a
26972 +Allow: POST
26973 +Content-type: %a
26974 +
26975 --- /dev/null
26976 +++ b/ext/http/tests/allowed_methods_002_logging.phpt
26977 @@ -0,0 +1,21 @@
26978 +--TEST--
26979 +logging allowed methods
26980 +--SKIPIF--
26981 +<?php
26982 +include 'skip.inc';
26983 +checkcgi();
26984 +checkmin("5.2.5");
26985 +?>
26986 +--ENV--
26987 +HTTP_HOST=example.com
26988 +--FILE--
26989 +<?php
26990 +echo "-TEST\n";
26991 +include 'log.inc';
26992 +log_content(_AMETH_LOG);
26993 +echo "Done";
26994 +?>
26995 +--EXPECTF--
26996 +%aTEST
26997 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [405-ALLOWED] Allow: POST <%a>
26998 +Done
26999 --- /dev/null
27000 +++ b/ext/http/tests/bug_15800.phpt
27001 @@ -0,0 +1,49 @@
27002 +--TEST--
27003 +Bug #15800 Double free when zval is separated in convert_to_*
27004 +--SKIPIF--
27005 +<?php
27006 +include 'skip.inc';
27007 +checkmin("5.2.5");
27008 +checkcls('HttpRequest');
27009 +skipif(!function_exists('debug_zval_dump'), "need DEBUG version of PHP");
27010 +?>
27011 +--FILE--
27012 +<?php
27013 +echo "-TEST\n";
27014 +$o = array('ssl' => array('verifypeer'=>'1'));
27015 +debug_zval_dump($o);
27016 +
27017 +$r = new HttpRequest('http://www.google.com');
27018 +$r->setOptions($o);
27019 +$r->send();
27020 +debug_zval_dump($o);
27021 +
27022 +unset($r);
27023 +debug_zval_dump($o);
27024 +
27025 +echo "Done\n";
27026 +?>
27027 +--EXPECTF--
27028 +%aTEST
27029 +array(1) refcount(2){
27030 + ["ssl"]=>
27031 + array(1) refcount(1){
27032 + ["verifypeer"]=>
27033 + string(1) "1" refcount(1)
27034 + }
27035 +}
27036 +array(1) refcount(2){
27037 + ["ssl"]=>
27038 + array(1) refcount(1){
27039 + ["verifypeer"]=>
27040 + string(1) "1" refcount(3)
27041 + }
27042 +}
27043 +array(1) refcount(2){
27044 + ["ssl"]=>
27045 + array(1) refcount(1){
27046 + ["verifypeer"]=>
27047 + string(1) "1" refcount(1)
27048 + }
27049 +}
27050 +Done
27051 --- /dev/null
27052 +++ b/ext/http/tests/build_str_001.phpt
27053 @@ -0,0 +1,30 @@
27054 +--TEST--
27055 +http_build_str
27056 +--SKIPIF--
27057 +<?php
27058 +include 'skip.inc';
27059 +?>
27060 +--FILE--
27061 +<?php
27062 +echo "-TEST\n";
27063 +
27064 +parse_str("a=b", $q);
27065 +echo http_build_str($q, null, "&"), "\n";
27066 +
27067 +parse_str("a=b&c[0]=1", $q);
27068 +echo http_build_str($q, null, "&"), "\n";
27069 +
27070 +parse_str("a=b&c[0]=1&d[e]=f", $q);
27071 +echo http_build_str($q, null, "&"), "\n";
27072 +
27073 +echo http_build_str(array(1,2,array(3)), "foo", "&"), "\n";
27074 +
27075 +echo "Done\n";
27076 +?>
27077 +--EXPECTF--
27078 +%aTEST
27079 +a=b
27080 +a=b&c%5B0%5D=1
27081 +a=b&c%5B0%5D=1&d%5Be%5D=f
27082 +foo%5B0%5D=1&foo%5B1%5D=2&foo%5B2%5D%5B0%5D=3
27083 +Done
27084 --- /dev/null
27085 +++ b/ext/http/tests/build_url_001.phpt
27086 @@ -0,0 +1,18 @@
27087 +--TEST--
27088 +http_build_url() with relative paths
27089 +--SKIPIF--
27090 +<?php
27091 +include 'skip.inc';
27092 +?>
27093 +--FILE--
27094 +<?php
27095 +echo "-TEST\n";
27096 +echo http_build_url('page'), "\n";
27097 +echo http_build_url('with/some/path/'), "\n";
27098 +echo "Done\n";
27099 +?>
27100 +--EXPECTF--
27101 +%aTEST
27102 +http://%a/page
27103 +http://%a/with/some/path/
27104 +Done
27105 --- /dev/null
27106 +++ b/ext/http/tests/build_url_002.phpt
27107 @@ -0,0 +1,30 @@
27108 +--TEST--
27109 +http_build_url() with parse_url()
27110 +--SKIPIF--
27111 +<?php
27112 +include 'skip.inc';
27113 +?>
27114 +--FILE--
27115 +<?php
27116 +echo "-TEST\n";
27117 +echo http_build_url(parse_url("http://example.org/orig?q=1#f"),
27118 + parse_url("https://www.example.com:9999/replaced#n")), "\n";
27119 +echo http_build_url(("http://example.org/orig?q=1#f"),
27120 + ("https://www.example.com:9999/replaced#n"), 0, $u), "\n";
27121 +print_r($u);
27122 +echo "Done\n";
27123 +?>
27124 +--EXPECTF--
27125 +%aTEST
27126 +https://www.example.com:9999/replaced?q=1#n
27127 +https://www.example.com:9999/replaced?q=1#n
27128 +Array
27129 +(
27130 + [scheme] => https
27131 + [host] => www.example.com
27132 + [port] => 9999
27133 + [path] => /replaced
27134 + [query] => q=1
27135 + [fragment] => n
27136 +)
27137 +Done
27138 --- /dev/null
27139 +++ b/ext/http/tests/build_url_003.phpt
27140 @@ -0,0 +1,26 @@
27141 +--TEST--
27142 +http_build_url()
27143 +--SKIPIF--
27144 +<?php
27145 +include 'skip.inc';
27146 +checkmin("5.2.5");
27147 +?>
27148 +--ENV--
27149 +HTTP_HOST=www.example.com
27150 +--FILE--
27151 +<?php
27152 +$url = '/path/?query#anchor';
27153 +echo "-TEST\n";
27154 +printf("-%s-\n", http_build_url($url));
27155 +printf("-%s-\n", http_build_url($url, array('scheme' => 'https')));
27156 +printf("-%s-\n", http_build_url($url, array('scheme' => 'https', 'host' => 'ssl.example.com')));
27157 +printf("-%s-\n", http_build_url($url, array('scheme' => 'ftp', 'host' => 'ftp.example.com', 'port' => 21)));
27158 +echo "Done\n";
27159 +?>
27160 +--EXPECTF--
27161 +%aTEST
27162 +-http://www.example.com/path/?query#anchor-
27163 +-https://www.example.com/path/?query#anchor-
27164 +-https://ssl.example.com/path/?query#anchor-
27165 +-ftp://ftp.example.com/path/?query#anchor-
27166 +Done
27167 --- /dev/null
27168 +++ b/ext/http/tests/build_url_004.phpt
27169 @@ -0,0 +1,22 @@
27170 +--TEST--
27171 +http_build_url flags
27172 +--SKPIF--
27173 +<?php
27174 +include 'skip.inc';
27175 +?>
27176 +--FILE--
27177 +<?php
27178 +echo "-TEST\n";
27179 +echo http_build_url("http://mike@www.example.com/foo/bar", "./baz", HTTP_URL_STRIP_AUTH|HTTP_URL_JOIN_PATH), "\n";
27180 +echo http_build_url("http://mike@www.example.com/foo/bar/", "../baz", HTTP_URL_STRIP_USER|HTTP_URL_JOIN_PATH), "\n";
27181 +echo http_build_url("http://mike:1234@www.example.com/foo/bar/", "./../baz", HTTP_URL_STRIP_PASS|HTTP_URL_JOIN_PATH), "\n";
27182 +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";
27183 +echo "Done\n";
27184 +?>
27185 +--EXPECTF--
27186 +%aTEST
27187 +http://www.example.com/foo/baz
27188 +http://www.example.com/foo/baz
27189 +http://mike@www.example.com/foo/baz
27190 +http://www.example.com/?a%5B0%5D=1&a%5B1%5D=b&b=c
27191 +Done
27192 --- /dev/null
27193 +++ b/ext/http/tests/chunked_decode_001.phpt
27194 @@ -0,0 +1,25 @@
27195 +--TEST--
27196 +http_chunked_decode() "\r\n"
27197 +--SKIPIF--
27198 +<?php
27199 +include 'skip.inc';
27200 +?>
27201 +--FILE--
27202 +<?php
27203 +echo "-TEST\n";
27204 +$data =
27205 +"02\r\n".
27206 +"ab\r\n".
27207 +"04\r\n".
27208 +"ra\nc\r\n".
27209 +"06\r\n".
27210 +"adabra\r\n".
27211 +"0\r\n".
27212 +"nothing\n";
27213 +var_dump(http_chunked_decode($data));
27214 +?>
27215 +--EXPECTF--
27216 +%aTEST
27217 +string(12) "abra
27218 +cadabra"
27219 +
27220 --- /dev/null
27221 +++ b/ext/http/tests/chunked_decode_002.phpt
27222 @@ -0,0 +1,25 @@
27223 +--TEST--
27224 +http_chunked_decode() "\n"
27225 +--SKIPIF--
27226 +<?php
27227 +include 'skip.inc';
27228 +?>
27229 +--FILE--
27230 +<?php
27231 +echo "-TEST\n";
27232 +$data =
27233 +"02\n".
27234 +"ab\n".
27235 +"04\n".
27236 +"ra\nc\n".
27237 +"06\n".
27238 +"adabra\n".
27239 +"0\n".
27240 +"hidden\n";
27241 +var_dump(http_chunked_decode($data));
27242 +?>
27243 +--EXPECTF--
27244 +%aTEST
27245 +string(12) "abra
27246 +cadabra"
27247 +
27248 --- /dev/null
27249 +++ b/ext/http/tests/chunked_decode_003.phpt
27250 @@ -0,0 +1,27 @@
27251 +--TEST--
27252 +http_chunked_decode() truncated message
27253 +--SKIPIF--
27254 +<?php
27255 +include 'skip.inc';
27256 +?>
27257 +--FILE--
27258 +<?php
27259 +echo "-TEST\n";
27260 +$data =
27261 +"02\r\n".
27262 +"ab\r\n".
27263 +"04\r\n".
27264 +"ra\nc\r\n".
27265 +"06\r\n".
27266 +"adabra\r\n".
27267 +"ff\r\n".
27268 +"\nall we got\n";
27269 +var_dump(http_chunked_decode($data));
27270 +?>
27271 +--EXPECTF--
27272 +%aTEST
27273 +%aWarning%ahttp_chunked_decode()%aTruncated message: chunk size 255 exceeds remaining data size 12 at pos 34 of 46 in%a
27274 +string(24) "abra
27275 +cadabra
27276 +all we got
27277 +"
27278 --- /dev/null
27279 +++ b/ext/http/tests/chunked_decode_004.phpt
27280 @@ -0,0 +1,26 @@
27281 +--TEST--
27282 +http_chunked_decode() truncated message ending with NUL after a chunk
27283 +--SKIPIF--
27284 +<?php
27285 +include 'skip.inc';
27286 +?>
27287 +--FILE--
27288 +<?php
27289 +echo "-TEST\n";
27290 +$data =
27291 +"02\r\n".
27292 +"ab\r\n".
27293 +"04\r\n".
27294 +"ra\nc\r\n".
27295 +"06\r\n".
27296 +"adabra\r\n".
27297 +"0c\r\n".
27298 +"\nall we got\n";
27299 +var_dump(http_chunked_decode($data));
27300 +?>
27301 +--EXPECTF--
27302 +%aTEST
27303 +string(24) "abra
27304 +cadabra
27305 +all we got
27306 +"
27307 --- /dev/null
27308 +++ b/ext/http/tests/cloning_001.phpt
27309 @@ -0,0 +1,29 @@
27310 +--TEST--
27311 +cloning
27312 +--SKIPIF--
27313 +<?php
27314 +include 'skip.inc';
27315 +checkmin("5.2.5");
27316 +checkcls('HttpRequest');
27317 +?>
27318 +--FILE--
27319 +<?php
27320 +echo "-TEST\n";
27321 +
27322 +$r1 = new HttpRequest;
27323 +$r2 = clone $r1;
27324 +$r1->setOptions(array('redirect' => 3));
27325 +var_dump($r1->getOptions() == $r2->getOptions());
27326 +$r1->setUrl('http://www.google.com/');
27327 +var_dump($r1->getUrl() == $r2->getUrl());
27328 +$r1->send();
27329 +var_dump($r1->getResponseInfo() == $r2->getResponseInfo());
27330 +
27331 +echo "Done\n";
27332 +?>
27333 +--EXPECTF--
27334 +%aTEST
27335 +bool(false)
27336 +bool(false)
27337 +bool(false)
27338 +Done
27339 --- /dev/null
27340 +++ b/ext/http/tests/data.txt
27341 @@ -0,0 +1,10 @@
27342 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27343 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27344 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27345 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27346 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27347 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27348 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27349 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27350 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27351 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
27352 --- /dev/null
27353 +++ b/ext/http/tests/date_001.phpt
27354 @@ -0,0 +1,17 @@
27355 +--TEST--
27356 +http_date() with timestamp
27357 +--SKIPIF--
27358 +<?php
27359 +include 'skip.inc';
27360 +?>
27361 +--FILE--
27362 +<?php
27363 +echo "-TEST\n";
27364 +echo http_date(1), "\n";
27365 +echo http_date(1234567890), "\n";
27366 +?>
27367 +--EXPECTF--
27368 +%aTEST
27369 +Thu, 01 Jan 1970 00:00:01 GMT
27370 +Fri, 13 Feb 2009 23:31:30 GMT
27371 +
27372 --- /dev/null
27373 +++ b/ext/http/tests/date_002.phpt
27374 @@ -0,0 +1,21 @@
27375 +--TEST--
27376 +http_date() without timestamp
27377 +--SKIPIF--
27378 +<?php
27379 +include 'skip.inc';
27380 +?>
27381 +--FILE--
27382 +<?php
27383 +echo "-TEST\n";
27384 +ini_set('date.timezone', 'GMT');
27385 +$d = http_date();
27386 +$t = strtotime($d);
27387 +var_dump($t > 1);
27388 +echo "$t\n$d\nDone\n";
27389 +?>
27390 +--EXPECTF--
27391 +%aTEST
27392 +bool(true)
27393 +%d
27394 +%a, %d %a %d %d:%d:%d GMT
27395 +Done
27396 --- /dev/null
27397 +++ b/ext/http/tests/encoding_objects_001.phpt
27398 @@ -0,0 +1,35 @@
27399 +--TEST--
27400 +encoding stream objects
27401 +--SKIPIF--
27402 +<?php
27403 +include 'skip.inc';
27404 +checkver(5);
27405 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
27406 +?>
27407 +--FILE--
27408 +<?php
27409 +echo "-TEST\n";
27410 +$d = new HttpDeflateStream;
27411 +$i = new HttpInflateStream;
27412 +echo $i->flush($d->flush("Hi "));
27413 +echo $i->finish($d->finish("there!\n"));
27414 +echo $i->finish($d->finish("Yo...\n"));
27415 +
27416 +$id = $i->update($d->update($pd = file_get_contents(__FILE__)));
27417 +foreach (glob('*.phpt') as $f) {
27418 + $id .= $i->update($d->update($tmp = file_get_contents($f)));
27419 + $pd .= $tmp;
27420 +}
27421 +$id .= $i->finish($d->finish());
27422 +
27423 +var_dump($id == $pd);
27424 +
27425 +echo "Done\n";
27426 +?>
27427 +--EXPECTF--
27428 +%aTEST
27429 +Hi there!
27430 +Yo...
27431 +bool(true)
27432 +Done
27433 +
27434 --- /dev/null
27435 +++ b/ext/http/tests/encodings.phpt
27436 @@ -0,0 +1,44 @@
27437 +--TEST--
27438 +encodings
27439 +--SKIPIF--
27440 +<?php
27441 +include 'skip.inc';
27442 +skipif(!function_exists('http_deflate'), 'need zlib');
27443 +?>
27444 +--FILE--
27445 +<?php
27446 +echo "-TEST\n";
27447 +
27448 +set_time_limit(0);
27449 +error_reporting(E_ALL);
27450 +
27451 +$s = '';
27452 +
27453 +for ($i = 0; $i < 5000; ++$i) {
27454 + $s .= chr(rand(0,255));
27455 +}
27456 +
27457 +var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_ZLIB)));
27458 +var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_GZIP)));
27459 +var_dump($s == http_inflate(http_deflate($s, HTTP_DEFLATE_TYPE_RAW)));
27460 +
27461 +if (extension_loaded('zlib')) {
27462 +
27463 + $s = "A simple test string, which won't blow up ext/zlib.\n";
27464 +
27465 + ($s == http_inflate(gzencode($s))) or print "GZIP Failed\n";
27466 + ($s == http_inflate(gzdeflate($s))) or print "DEFLATE Failed\n";
27467 + ($s == http_inflate(gzcompress($s))) or print "COMPRESS Failed\n";
27468 +
27469 + ($s == gzinflate(http_deflate($s, HTTP_DEFLATE_TYPE_RAW))) or print "INFLATE Failed\n";
27470 + ($s == gzuncompress(http_deflate($s, HTTP_DEFLATE_TYPE_ZLIB))) or print "UNCOMPRESS Failed\n";
27471 +}
27472 +
27473 +echo "Done\n";
27474 +?>
27475 +--EXPECTF--
27476 +%aTEST
27477 +bool(true)
27478 +bool(true)
27479 +bool(true)
27480 +Done
27481 --- /dev/null
27482 +++ b/ext/http/tests/etag_mode_031.phpt
27483 @@ -0,0 +1,23 @@
27484 +--TEST--
27485 +crc32 etag (may fail because PHPs crc32 is actually crc32b)
27486 +--SKIPIF--
27487 +<?php
27488 +include 'skip.inc';
27489 +checkcgi();
27490 +checkmin("5.2.5");
27491 +?>
27492 +--FILE--
27493 +<?php
27494 +ini_set('http.etag.mode', extension_loaded('hash')?'crc32b':'crc32');
27495 +http_cache_etag();
27496 +http_send_data("abc\n");
27497 +?>
27498 +--EXPECTF--
27499 +X-Powered-By: PHP/%a
27500 +Cache-Control: private, must-revalidate, max-age=0
27501 +Accept-Ranges: bytes
27502 +ETag: "4e818847"
27503 +Content-Length: 4
27504 +Content-type: %a
27505 +
27506 +abc
27507 --- /dev/null
27508 +++ b/ext/http/tests/etag_mode_032.phpt
27509 @@ -0,0 +1,23 @@
27510 +--TEST--
27511 +sha1 etag
27512 +--SKIPIF--
27513 +<?php
27514 +include 'skip.inc';
27515 +checkcgi();
27516 +checkmin("5.2.5");
27517 +?>
27518 +--FILE--
27519 +<?php
27520 +ini_set('http.etag.mode', 'SHA1');
27521 +http_cache_etag();
27522 +http_send_data("abc\n");
27523 +?>
27524 +--EXPECTF--
27525 +X-Powered-By: PHP/%a
27526 +Cache-Control: private, must-revalidate, max-age=0
27527 +Accept-Ranges: bytes
27528 +ETag: "03cfd743661f07975fa2f1220c5194cbaff48451"
27529 +Content-Length: 4
27530 +Content-type: %a
27531 +
27532 +abc
27533 --- /dev/null
27534 +++ b/ext/http/tests/etag_mode_033.phpt
27535 @@ -0,0 +1,23 @@
27536 +--TEST--
27537 +md5 etag
27538 +--SKIPIF--
27539 +<?php
27540 +include 'skip.inc';
27541 +checkcgi();
27542 +checkmin("5.2.5");
27543 +?>
27544 +--FILE--
27545 +<?php
27546 +ini_set('http.etag.mode', 'MD5');
27547 +http_cache_etag();
27548 +http_send_data("abc\n");
27549 +?>
27550 +--EXPECTF--
27551 +X-Powered-By: PHP/%a
27552 +Cache-Control: private, must-revalidate, max-age=0
27553 +Accept-Ranges: bytes
27554 +ETag: "0bee89b07a248e27c83fc3d5951213c1"
27555 +Content-Length: 4
27556 +Content-type: %a
27557 +
27558 +abc
27559 --- /dev/null
27560 +++ b/ext/http/tests/etag_mode_034.phpt
27561 @@ -0,0 +1,24 @@
27562 +--TEST--
27563 +ext/hash etag
27564 +--SKIPIF--
27565 +<?php
27566 +include 'skip.inc';
27567 +checkcgi();
27568 +checkmin("5.2.5");
27569 +skipif(!extension_loaded('hash'), 'need ext/hash support');
27570 +?>
27571 +--FILE--
27572 +<?php
27573 +ini_set('http.etag.mode', 'sha256');
27574 +http_cache_etag();
27575 +http_send_data("abc\n");
27576 +?>
27577 +--EXPECTF--
27578 +X-Powered-By: PHP/%a
27579 +Cache-Control: private, must-revalidate, max-age=0
27580 +Accept-Ranges: bytes
27581 +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb"
27582 +Content-Length: 4
27583 +Content-type: %a
27584 +
27585 +abc
27586 --- /dev/null
27587 +++ b/ext/http/tests/etag_mode_041.phpt
27588 @@ -0,0 +1,21 @@
27589 +--TEST--
27590 +ob crc32 etag (may fail because PHPs crc32 is actually crc32b)
27591 +--SKIPIF--
27592 +<?php
27593 +include 'skip.inc';
27594 +checkcgi();
27595 +checkmin("5.2.5");
27596 +?>
27597 +--FILE--
27598 +<?php
27599 +ini_set('http.etag.mode', extension_loaded('hash')?'crc32b':'crc32');
27600 +http_cache_etag();
27601 +print("abc\n");
27602 +?>
27603 +--EXPECTF--
27604 +X-Powered-By: PHP/%a
27605 +Cache-Control: private, must-revalidate, max-age=0
27606 +ETag: "4e818847"
27607 +Content-type: %a
27608 +
27609 +abc
27610 --- /dev/null
27611 +++ b/ext/http/tests/etag_mode_042.phpt
27612 @@ -0,0 +1,21 @@
27613 +--TEST--
27614 +ob sha1 etag
27615 +--SKIPIF--
27616 +<?php
27617 +include 'skip.inc';
27618 +checkcgi();
27619 +checkmin("5.2.5");
27620 +?>
27621 +--FILE--
27622 +<?php
27623 +ini_set('http.etag.mode', 'SHA1');
27624 +http_cache_etag();
27625 +print("abc\n");
27626 +?>
27627 +--EXPECTF--
27628 +X-Powered-By: PHP/%a
27629 +Cache-Control: private, must-revalidate, max-age=0
27630 +ETag: "03cfd743661f07975fa2f1220c5194cbaff48451"
27631 +Content-type: %a
27632 +
27633 +abc
27634 --- /dev/null
27635 +++ b/ext/http/tests/etag_mode_043.phpt
27636 @@ -0,0 +1,21 @@
27637 +--TEST--
27638 +ob md5 etag
27639 +--SKIPIF--
27640 +<?php
27641 +include 'skip.inc';
27642 +checkcgi();
27643 +checkmin("5.2.5");
27644 +?>
27645 +--FILE--
27646 +<?php
27647 +ini_set('http.etag.mode', 'bogus');
27648 +http_cache_etag();
27649 +print("abc\n");
27650 +?>
27651 +--EXPECTF--
27652 +X-Powered-By: PHP/%a
27653 +Cache-Control: private, must-revalidate, max-age=0
27654 +ETag: "0bee89b07a248e27c83fc3d5951213c1"
27655 +Content-type: %a
27656 +
27657 +abc
27658 --- /dev/null
27659 +++ b/ext/http/tests/etag_mode_044.phpt
27660 @@ -0,0 +1,22 @@
27661 +--TEST--
27662 +ob ext/hash etag
27663 +--SKIPIF--
27664 +<?php
27665 +include 'skip.inc';
27666 +checkcgi();
27667 +checkmin("5.2.5");
27668 +skipif(!extension_loaded('hash'), 'need ext/hash support');
27669 +?>
27670 +--FILE--
27671 +<?php
27672 +ini_set('http.etag.mode', 'sha256');
27673 +http_cache_etag();
27674 +print("abc\n");
27675 +?>
27676 +--EXPECTF--
27677 +X-Powered-By: PHP/%a
27678 +Cache-Control: private, must-revalidate, max-age=0
27679 +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb"
27680 +Content-type: %a
27681 +
27682 +abc
27683 --- /dev/null
27684 +++ b/ext/http/tests/exceptions.phpt
27685 @@ -0,0 +1,53 @@
27686 +--TEST--
27687 +exceptions
27688 +--SKIPIF--
27689 +<?php
27690 +include 'skip.inc';
27691 +checkmin("5.2.5");
27692 +?>
27693 +--FILE--
27694 +<?php
27695 +echo "-TEST\n";
27696 +
27697 +ini_set('http.only_exceptions', true);
27698 +
27699 +$e = array(
27700 + HTTP_E_RUNTIME => 'Runtime',
27701 + HTTP_E_INVALID_PARAM => 'InvalidParam',
27702 + HTTP_E_HEADER => 'Header',
27703 + HTTP_E_MALFORMED_HEADERS => 'MalformedHeaders',
27704 + HTTP_E_REQUEST_METHOD => 'RequestMethod',
27705 + HTTP_E_MESSAGE_TYPE => 'MessageType',
27706 + HTTP_E_ENCODING => 'Encoding',
27707 + HTTP_E_REQUEST => 'Request',
27708 + HTTP_E_REQUEST_POOL => 'RequestPool',
27709 + HTTP_E_SOCKET => 'Socket',
27710 + HTTP_E_RESPONSE => 'Response',
27711 + HTTP_E_URL => 'Url',
27712 +);
27713 +
27714 +foreach ($e as $i => $c) {
27715 + try {
27716 + $n = "Http{$c}Exception";
27717 + throw new $n;
27718 + } catch (HttpException $x) {
27719 + printf("%2d: %s\n", $i, get_class($x));
27720 + }
27721 +}
27722 +echo "Done\n";
27723 +?>
27724 +--EXPECTF--
27725 +%aTEST
27726 + 1: HttpRuntimeException
27727 + 2: HttpInvalidParamException
27728 + 3: HttpHeaderException
27729 + 4: HttpMalformedHeadersException
27730 + 5: HttpRequestMethodException
27731 + 6: HttpMessageTypeException
27732 + 7: HttpEncodingException
27733 + 8: HttpRequestException
27734 + 9: HttpRequestPoolException
27735 +10: HttpSocketException
27736 +11: HttpResponseException
27737 +12: HttpUrlException
27738 +Done
27739 --- /dev/null
27740 +++ b/ext/http/tests/get_request_data_001.phpt
27741 @@ -0,0 +1,40 @@
27742 +--TEST--
27743 +get request data
27744 +--SKIPIF--
27745 +<?php
27746 +include 'skip.inc';
27747 +?>
27748 +--POST--
27749 +a=b&c=d
27750 +--FILE--
27751 +<?php
27752 +echo "-TEST\n";
27753 +
27754 +$_SERVER['HTTP_ACCEPT_CHARSET'] = 'iso-8859-1, *';
27755 +$_SERVER['HTTP_ACCEPT_ENCODING'] = 'none';
27756 +$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0';
27757 +$_SERVER['HTTP_HOST'] = 'localhost';
27758 +
27759 +$h = http_get_request_headers();
27760 +ksort($h);
27761 +print_r($h);
27762 +var_dump(http_get_request_body());
27763 +var_dump(http_get_request_body());
27764 +var_dump(http_get_request_body());
27765 +var_dump(fread(http_get_request_body_stream(), 4096));
27766 +echo "Done\n";
27767 +?>
27768 +--EXPECTF--
27769 +%aTEST
27770 +Array
27771 +(
27772 + [Accept-Charset] => iso-8859-1, *
27773 + [Accept-Encoding] => none
27774 + [Host] => localhost
27775 + [User-Agent] => Mozilla/5.0
27776 +)
27777 +string(7) "a=b&c=d"
27778 +string(7) "a=b&c=d"
27779 +string(7) "a=b&c=d"
27780 +string(7) "a=b&c=d"
27781 +Done
27782 --- /dev/null
27783 +++ b/ext/http/tests/log.inc
27784 @@ -0,0 +1,23 @@
27785 +<?php
27786 +define('_REDIR_LOG', '__r_log');
27787 +define('_CACHE_LOG', '__c_log');
27788 +define('_AMETH_LOG', '__m_log');
27789 +define('_CMPST_LOG', '__a_log');
27790 +
27791 +function log_prepare($log)
27792 +{
27793 + is_file($log) and @unlink($log);
27794 + switch ($log)
27795 + {
27796 + case _REDIR_LOG: ini_set('http.log.redirect', _REDIR_LOG); break;
27797 + case _CACHE_LOG: ini_set('http.log.cache', _CACHE_LOG); break;
27798 + case _AMETH_LOG: ini_set('http.log.allowed_methods', _AMETH_LOG); break;
27799 + case _CMPTS_LOG: ini_set('http.log.composite', _CMPST_LOG); break;
27800 + }
27801 +}
27802 +function log_content($log)
27803 +{
27804 + echo file_get_contents($log);
27805 + unlink($log);
27806 +}
27807 +?>
27808 --- /dev/null
27809 +++ b/ext/http/tests/match_request_header_001.phpt
27810 @@ -0,0 +1,23 @@
27811 +--TEST--
27812 +http_match_request_header()
27813 +--SKIPIF--
27814 +<?php
27815 +include 'skip.inc';
27816 +checkmin("5.2.5");
27817 +?>
27818 +--ENV--
27819 +HTTP_FOO=bar
27820 +--FILE--
27821 +<?php
27822 +echo "-TEST\n";
27823 +var_dump(http_match_request_header("Foo", "bar", 1));
27824 +var_dump(http_match_request_header("fOO", "BAR", 0));
27825 +var_dump(http_match_request_header("foo", "BAR", 1));
27826 +echo "Done\n";
27827 +?>
27828 +--EXPECTF--
27829 +%aTEST
27830 +bool(true)
27831 +bool(true)
27832 +bool(false)
27833 +Done
27834 --- /dev/null
27835 +++ b/ext/http/tests/negotiation_001.phpt
27836 @@ -0,0 +1,64 @@
27837 +--TEST--
27838 +negotiation
27839 +--SKIPIF--
27840 +<?php
27841 +include 'skip.inc';
27842 +checkmin("5.2.5");
27843 +?>
27844 +--ENV--
27845 +HTTP_ACCEPT=application/xml, application/xhtml+xml, text/html ; q = .8
27846 +HTTP_ACCEPT_LANGUAGE=de-AT,de-DE;q=0.8,en-GB;q=0.3,en-US;q=0.2
27847 +HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7
27848 +--FILE--
27849 +<?php
27850 +echo "-TEST\n";
27851 +$langs = array(
27852 + array('de', 'en', 'es'),
27853 +);
27854 +$csets = array(
27855 + array('utf-8', 'iso-8859-1'),
27856 +);
27857 +$ctype = array(
27858 + array('foo/bar', 'application/xhtml+xml', 'text/html')
27859 +);
27860 +var_dump(http_negotiate_language($langs[0]));
27861 +var_dump(http_negotiate_language($langs[0], $lresult));
27862 +var_dump(http_negotiate_charset($csets[0]));
27863 +var_dump(http_negotiate_charset($csets[0], $cresult));
27864 +var_dump(http_negotiate_content_type($ctype[0]));
27865 +var_dump(http_negotiate_content_type($ctype[0], $tresult));
27866 +var_dump(http_negotiate_language(array("unknown")));
27867 +var_dump(http_negotiate_charset(array("unknown")));
27868 +var_dump(http_negotiate_content_type(array("unknown")));
27869 +print_r($lresult);
27870 +print_r($cresult);
27871 +print_r($tresult);
27872 +echo "Done\n";
27873 +?>
27874 +--EXPECTF--
27875 +%aTEST
27876 +string(2) "de"
27877 +string(2) "de"
27878 +string(10) "iso-8859-1"
27879 +string(10) "iso-8859-1"
27880 +string(21) "application/xhtml+xml"
27881 +string(21) "application/xhtml+xml"
27882 +string(7) "unknown"
27883 +string(7) "unknown"
27884 +string(7) "unknown"
27885 +Array
27886 +(
27887 + [de] => 900
27888 + [en] => 0.27
27889 +)
27890 +Array
27891 +(
27892 + [iso-8859-1] => 1000
27893 + [utf-8] => 0.7
27894 +)
27895 +Array
27896 +(
27897 + [application/xhtml+xml] => 999
27898 + [text/html] => 0.8
27899 +)
27900 +Done
27901 --- /dev/null
27902 +++ b/ext/http/tests/ob_deflatehandler_001.phpt
27903 @@ -0,0 +1,23 @@
27904 +--TEST--
27905 +ob_deflatehandler
27906 +--SKIPIF--
27907 +<?php
27908 +include 'skip.inc';
27909 +checkcgi();
27910 +checkmin("5.2.5");
27911 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
27912 +?>
27913 +--ENV--
27914 +HTTP_ACCEPT_ENCODING=gzip
27915 +--FILE--
27916 +<?php
27917 +ob_start('ob_deflatehandler');
27918 +echo "-TEST\n";
27919 +echo "Done\n";
27920 +?>
27921 +--EXPECTF--
27922 +%a
27923 +Content-Encoding: gzip
27924 +Vary: Accept-Encoding
27925 +%a
27926 +
27927 --- /dev/null
27928 +++ b/ext/http/tests/ob_inflatehandler_001.phpt
27929 @@ -0,0 +1,16 @@
27930 +--TEST--
27931 +ob_inflatehandler
27932 +--SKIPIF--
27933 +<?php
27934 +include 'skip.inc';
27935 +checkcgi();
27936 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
27937 +?>
27938 +--FILE--
27939 +<?php
27940 +ob_start('ob_inflatehandler');
27941 +echo http_deflate("TEST\n");
27942 +?>
27943 +--EXPECTF--
27944 +%aTEST
27945 +
27946 --- /dev/null
27947 +++ b/ext/http/tests/parse_cookie_001.phpt
27948 @@ -0,0 +1,41 @@
27949 +--TEST--
27950 +parse cookie
27951 +--SKIPIF--
27952 +<?php
27953 +include 'skip.inc';
27954 +?>
27955 +--FILE--
27956 +<?php
27957 +echo "-TEST\n";
27958 +
27959 +var_dump(http_parse_cookie('name="value"; foo="bar\"baz"; hey=got"it ; path=/ ; comment=; expires='.http_date(1).' secure ; httpOnly', 0, array("comment")));
27960 +
27961 +echo "Done\n";
27962 +?>
27963 +--EXPECTF--
27964 +%aTEST
27965 +object(stdClass)%a {
27966 + ["cookies"]=>
27967 + array(3) {
27968 + ["name"]=>
27969 + string(5) "value"
27970 + ["foo"]=>
27971 + string(7) "bar"baz"
27972 + ["hey"]=>
27973 + string(6) "got"it"
27974 + }
27975 + ["extras"]=>
27976 + array(1) {
27977 + ["comment"]=>
27978 + string(0) ""
27979 + }
27980 + ["flags"]=>
27981 + int(32)
27982 + ["expires"]=>
27983 + int(1)
27984 + ["path"]=>
27985 + string(1) "/"
27986 + ["domain"]=>
27987 + string(0) ""
27988 +}
27989 +Done
27990 --- /dev/null
27991 +++ b/ext/http/tests/parse_cookie_002.phpt
27992 @@ -0,0 +1,80 @@
27993 +--TEST--
27994 +parse cookie
27995 +--SKIPIF--
27996 +<?php
27997 +include 'skip.inc';
27998 +checkmin("5.2.5");
27999 +?>
28000 +--FILE--
28001 +<?php
28002 +echo "-TEST\n";
28003 +
28004 +var_dump(http_parse_cookie('foo')->cookies['foo']);
28005 +var_dump(http_parse_cookie('foo;')->cookies['foo']);
28006 +var_dump(http_parse_cookie('foo ')->cookies['foo']);
28007 +var_dump(http_parse_cookie('foo ;')->cookies['foo']);
28008 +var_dump(http_parse_cookie('foo ; ')->cookies['foo']);
28009 +var_dump(http_parse_cookie('foo=')->cookies['foo']);
28010 +var_dump(http_parse_cookie('foo=;')->cookies['foo']);
28011 +var_dump(http_parse_cookie('foo =')->cookies['foo']);
28012 +var_dump(http_parse_cookie('foo =;')->cookies['foo']);
28013 +var_dump(http_parse_cookie('foo= ')->cookies['foo']);
28014 +var_dump(http_parse_cookie('foo= ;')->cookies['foo']);
28015 +
28016 +var_dump(http_parse_cookie('foo=1')->cookies['foo']);
28017 +var_dump(http_parse_cookie('foo=1;')->cookies['foo']);
28018 +var_dump(http_parse_cookie('foo=1 ;')->cookies['foo']);
28019 +var_dump(http_parse_cookie('foo= 1;')->cookies['foo']);
28020 +var_dump(http_parse_cookie('foo = 1;')->cookies['foo']);
28021 +var_dump(http_parse_cookie('foo = 1 ;')->cookies['foo']);
28022 +var_dump(http_parse_cookie('foo=1')->cookies['foo']);
28023 +var_dump(http_parse_cookie('foo= 1')->cookies['foo']);
28024 +
28025 +var_dump(http_parse_cookie('foo="1"')->cookies['foo']);
28026 +var_dump(http_parse_cookie('foo="1" ')->cookies['foo']);
28027 +var_dump(http_parse_cookie('foo="1";')->cookies['foo']);
28028 +var_dump(http_parse_cookie('foo = "1" ;')->cookies['foo']);
28029 +var_dump(http_parse_cookie('foo= "1" ')->cookies['foo']);
28030 +
28031 +var_dump(http_parse_cookie('foo=""')->cookies['foo']);
28032 +var_dump(http_parse_cookie('foo="\""')->cookies['foo']);
28033 +var_dump(http_parse_cookie('foo=" "')->cookies['foo']);
28034 +var_dump(http_parse_cookie('foo= "')->cookies['foo']);
28035 +var_dump(http_parse_cookie('foo=" ')->cookies['foo']);
28036 +var_dump(http_parse_cookie('foo= " ')->cookies['foo']);
28037 +
28038 +echo "Done\n";
28039 +?>
28040 +--EXPECTF--
28041 +%aTEST
28042 +string(0) ""
28043 +string(0) ""
28044 +string(0) ""
28045 +string(0) ""
28046 +string(0) ""
28047 +string(0) ""
28048 +string(0) ""
28049 +string(0) ""
28050 +string(0) ""
28051 +string(0) ""
28052 +string(0) ""
28053 +string(1) "1"
28054 +string(1) "1"
28055 +string(1) "1"
28056 +string(1) "1"
28057 +string(1) "1"
28058 +string(1) "1"
28059 +string(1) "1"
28060 +string(1) "1"
28061 +string(1) "1"
28062 +string(1) "1"
28063 +string(1) "1"
28064 +string(1) "1"
28065 +string(1) "1"
28066 +string(0) ""
28067 +string(1) """
28068 +string(1) " "
28069 +string(1) """
28070 +string(1) """
28071 +string(1) """
28072 +Done
28073 --- /dev/null
28074 +++ b/ext/http/tests/parse_headers_001.phpt
28075 @@ -0,0 +1,41 @@
28076 +--TEST--
28077 +http_parse_headers()
28078 +--SKIPIF--
28079 +<?php
28080 +include 'skip.inc';
28081 +?>
28082 +--FILE--
28083 +<?php
28084 +echo "-TEST\n";
28085 +print_r(http_parse_headers(
28086 +"Host: localhost\r\n".
28087 +"Host: ambigious\r\n".
28088 +"Nospace:here\r\n".
28089 +"Muchspace: there \r\n".
28090 +"Empty:\r\n".
28091 +"Empty2: \r\n".
28092 +"Folded: one\r\n".
28093 +"\ttwo\r\n".
28094 +" three\r\n\r\n".
28095 +"stop\r\n"
28096 +));
28097 +?>
28098 +--EXPECTF--
28099 +%aTEST
28100 +Array
28101 +(
28102 + [Host] => Array
28103 + (
28104 + [0] => localhost
28105 + [1] => ambigious
28106 + )
28107 +
28108 + [Nospace] => here
28109 + [Muchspace] => there
28110 + [Empty] =>
28111 + [Empty2] =>
28112 + [Folded] => one
28113 + two
28114 + three
28115 +)
28116 +
28117 --- /dev/null
28118 +++ b/ext/http/tests/parse_message_001.phpt
28119 @@ -0,0 +1,18 @@
28120 +--TEST--
28121 +http_parse_message()
28122 +--SKIPIF--
28123 +<?php
28124 +include 'skip.inc';
28125 +checkurl('www.google.com');
28126 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), 'need curl support');
28127 +?>
28128 +--FILE--
28129 +<?php
28130 +echo "-TEST\n";
28131 +$m = http_parse_message(http_get('http://www.google.com'));
28132 +echo $m->body;
28133 +echo "Done\n";
28134 +--EXPECTF--
28135 +%aTEST
28136 +<HTML>%aThe document has moved%a</HTML>
28137 +Done
28138 --- /dev/null
28139 +++ b/ext/http/tests/parse_message_002.phpt
28140 @@ -0,0 +1,39 @@
28141 +--TEST--
28142 +identity encoding trap
28143 +--SKIPIF--
28144 +<?php
28145 +include 'skip.inc';
28146 +?>
28147 +--FILE--
28148 +<?php
28149 +echo "-TEST\n";
28150 +
28151 +$message =
28152 +"HTTP/1.1 200 Ok\n".
28153 +"Transfer-Encoding: identity\n".
28154 +"Content-Length: 3\n".
28155 +"Content-Type: text/plain\n\n".
28156 +"Hi!\n\n\n\n";
28157 +
28158 +print_r(http_parse_message($message));
28159 +
28160 +echo "Done\n";
28161 +--EXPECTF--
28162 +%aTEST
28163 +stdClass Object
28164 +(
28165 + [type] => 2
28166 + [httpVersion] => 1.1
28167 + [responseCode] => 200
28168 + [responseStatus] => Ok
28169 + [headers] => Array
28170 + (
28171 + [Transfer-Encoding] => identity
28172 + [Content-Length] => 3
28173 + [Content-Type] => text/plain
28174 + )
28175 +
28176 + [body] => Hi!
28177 + [parentMessage] =>
28178 +)
28179 +Done
28180 --- /dev/null
28181 +++ b/ext/http/tests/parse_message_003.phpt
28182 @@ -0,0 +1,31 @@
28183 +--TEST--
28184 +content range message
28185 +--SKIPIF--
28186 +<?php
28187 +include 'skip.inc';
28188 +?>
28189 +--FILE--
28190 +<?php
28191 +echo "-TEST\n";
28192 +
28193 +$message =
28194 +"HTTP/1.1 200 Ok\n".
28195 +"Content-Range: bytes: 0-1/5\n\n".
28196 +"OK\n";
28197 +
28198 +$msg = http_parse_message($message);
28199 +var_dump($msg->body);
28200 +
28201 +$message =
28202 +"HTTP/1.1 200 Ok\n".
28203 +"Content-Range: bytes 0-1/1\n\n".
28204 +"X\n";
28205 +
28206 +$msg = http_parse_message($message);
28207 +
28208 +echo "Done\n";
28209 +--EXPECTF--
28210 +%aTEST
28211 +string(2) "OK"
28212 +%a Invalid Content-Range header: bytes 0-1/1 in%a
28213 +Done
28214 --- /dev/null
28215 +++ b/ext/http/tests/parse_message_004.phpt
28216 @@ -0,0 +1,115 @@
28217 +--TEST--
28218 +http_parse_message() recursive
28219 +--SKIPIF--
28220 +<?php
28221 +include 'skip.inc';
28222 +?>
28223 +--FILE--
28224 +<?php
28225 +
28226 +echo "-TEST\n";
28227 +$message =
28228 +"HEAD / HTTP/1.1
28229 +Host: www.example.com
28230 +Accept: */*
28231 +HTTP/1.1 200 Ok
28232 +Server: Funky/1.0
28233 +Content-Length: 10
28234 +GET / HTTP/1.1
28235 +Host: www.example.com
28236 +Accept: */*
28237 +HTTP/1.1 200 Ok
28238 +Server: Funky/1.0
28239 +Content-Length: 10
28240 +
28241 +1234567890
28242 +";
28243 +
28244 +var_dump(http_parse_message($message));
28245 +
28246 +echo "Done\n";
28247 +?>
28248 +--EXPECTF--
28249 +%aTEST
28250 +object(stdClass)%a {
28251 + ["type"]=>
28252 + int(2)
28253 + ["httpVersion"]=>
28254 + float(1.1)
28255 + ["responseCode"]=>
28256 + int(200)
28257 + ["responseStatus"]=>
28258 + string(2) "Ok"
28259 + ["headers"]=>
28260 + array(2) {
28261 + ["Server"]=>
28262 + string(9) "Funky/1.0"
28263 + ["Content-Length"]=>
28264 + string(2) "10"
28265 + }
28266 + ["body"]=>
28267 + string(10) "1234567890"
28268 + ["parentMessage"]=>
28269 + object(stdClass)%a {
28270 + ["type"]=>
28271 + int(1)
28272 + ["httpVersion"]=>
28273 + float(1.1)
28274 + ["requestMethod"]=>
28275 + string(3) "GET"
28276 + ["requestUrl"]=>
28277 + string(1) "/"
28278 + ["headers"]=>
28279 + array(2) {
28280 + ["Host"]=>
28281 + string(15) "www.example.com"
28282 + ["Accept"]=>
28283 + string(3) "*/*"
28284 + }
28285 + ["body"]=>
28286 + string(0) ""
28287 + ["parentMessage"]=>
28288 + object(stdClass)%a {
28289 + ["type"]=>
28290 + int(2)
28291 + ["httpVersion"]=>
28292 + float(1.1)
28293 + ["responseCode"]=>
28294 + int(200)
28295 + ["responseStatus"]=>
28296 + string(2) "Ok"
28297 + ["headers"]=>
28298 + array(2) {
28299 + ["Server"]=>
28300 + string(9) "Funky/1.0"
28301 + ["Content-Length"]=>
28302 + string(2) "10"
28303 + }
28304 + ["body"]=>
28305 + string(0) ""
28306 + ["parentMessage"]=>
28307 + object(stdClass)%a {
28308 + ["type"]=>
28309 + int(1)
28310 + ["httpVersion"]=>
28311 + float(1.1)
28312 + ["requestMethod"]=>
28313 + string(4) "HEAD"
28314 + ["requestUrl"]=>
28315 + string(1) "/"
28316 + ["headers"]=>
28317 + array(2) {
28318 + ["Host"]=>
28319 + string(15) "www.example.com"
28320 + ["Accept"]=>
28321 + string(3) "*/*"
28322 + }
28323 + ["body"]=>
28324 + string(0) ""
28325 + ["parentMessage"]=>
28326 + NULL
28327 + }
28328 + }
28329 + }
28330 +}
28331 +Done
28332 --- /dev/null
28333 +++ b/ext/http/tests/parse_message_005.phpt
28334 @@ -0,0 +1,60 @@
28335 +--TEST--
28336 +http_parse_message() content range header w/(o) =
28337 +--SKIPIF--
28338 +<?php
28339 +include 'skip.inc';
28340 +?>
28341 +--FILE--
28342 +<?php
28343 +echo "-TEST\n";
28344 +print_r(http_parse_message(
28345 +"
28346 +HTTP/1.1 206
28347 +Server: Funky/1.0
28348 +Content-Range: bytes: 0-0/100
28349 +
28350 +1
28351 +
28352 +HTTP/1.1 206
28353 +Server: Funky/1.0
28354 +Content-Range: bytes 0-0/100
28355 +
28356 +1
28357 +
28358 +"
28359 +));
28360 +echo "Done\n";
28361 +?>
28362 +--EXPECTF--
28363 +%aTEST
28364 +stdClass Object
28365 +(
28366 + [type] => 2
28367 + [httpVersion] => 1.1
28368 + [responseCode] => 206
28369 + [responseStatus] =>
28370 + [headers] => Array
28371 + (
28372 + [Server] => Funky/1.0
28373 + [Content-Range] => bytes 0-0/100
28374 + )
28375 +
28376 + [body] => 1
28377 + [parentMessage] => stdClass Object
28378 + (
28379 + [type] => 2
28380 + [httpVersion] => 1.1
28381 + [responseCode] => 206
28382 + [responseStatus] =>
28383 + [headers] => Array
28384 + (
28385 + [Server] => Funky/1.0
28386 + [Content-Range] => bytes: 0-0/100
28387 + )
28388 +
28389 + [body] => 1
28390 + [parentMessage] =>
28391 + )
28392 +
28393 +)
28394 +Done
28395 --- /dev/null
28396 +++ b/ext/http/tests/parse_message_006.phpt
28397 @@ -0,0 +1,38 @@
28398 +--TEST--
28399 +mixed EOL trap
28400 +--SKIPIF--
28401 +<?php
28402 +include 'skip.inc';
28403 +?>
28404 +--FILE--
28405 +<?php
28406 +echo "-TEST\n";
28407 +
28408 +$message =
28409 +"HTTP/1.1 200 Ok\n".
28410 +"Header: Value\r\n".
28411 +"Connection: close\r\n".
28412 +"\n".
28413 +"Bug!";
28414 +
28415 +print_r(http_parse_message($message));
28416 +
28417 +echo "Done\n";
28418 +--EXPECTF--
28419 +%aTEST
28420 +stdClass Object
28421 +(
28422 + [type] => 2
28423 + [httpVersion] => 1.1
28424 + [responseCode] => 200
28425 + [responseStatus] => Ok
28426 + [headers] => Array
28427 + (
28428 + [Header] => Value
28429 + [Connection] => close
28430 + )
28431 +
28432 + [body] => Bug!
28433 + [parentMessage] =>
28434 +)
28435 +Done
28436 --- /dev/null
28437 +++ b/ext/http/tests/parse_params_001.phpt
28438 @@ -0,0 +1,75 @@
28439 +--TEST--
28440 +http_parse_params
28441 +--SKIPIF--
28442 +<?php
28443 +include 'skip.inc';
28444 +?>
28445 +--FILE--
28446 +<?php
28447 +echo "-TEST\n";
28448 +var_dump(http_parse_params('text/html; charset=iso-8859-1'));
28449 +var_dump(http_parse_params('text/html; charset="iso-8859-1"'));
28450 +var_dump(http_parse_params('attachment; filename="gol;got,a.ext"'));
28451 +var_dump(http_parse_params('public, must-revalidate, max-age=0'));
28452 +$p = http_parse_params('a'); var_dump($p->params[0]);
28453 +$p = http_parse_params('a=b'); var_dump($p->params[0]);
28454 +echo "Done\n";
28455 +?>
28456 +--EXPECTF--
28457 +%aTEST
28458 +object(stdClass)%a {
28459 + ["params"]=>
28460 + array(2) {
28461 + [0]=>
28462 + string(9) "text/html"
28463 + [1]=>
28464 + array(1) {
28465 + ["charset"]=>
28466 + string(10) "iso-8859-1"
28467 + }
28468 + }
28469 +}
28470 +object(stdClass)%a {
28471 + ["params"]=>
28472 + array(2) {
28473 + [0]=>
28474 + string(9) "text/html"
28475 + [1]=>
28476 + array(1) {
28477 + ["charset"]=>
28478 + string(10) "iso-8859-1"
28479 + }
28480 + }
28481 +}
28482 +object(stdClass)%a {
28483 + ["params"]=>
28484 + array(2) {
28485 + [0]=>
28486 + string(10) "attachment"
28487 + [1]=>
28488 + array(1) {
28489 + ["filename"]=>
28490 + string(13) "gol;got,a.ext"
28491 + }
28492 + }
28493 +}
28494 +object(stdClass)%a {
28495 + ["params"]=>
28496 + array(3) {
28497 + [0]=>
28498 + string(6) "public"
28499 + [1]=>
28500 + string(15) "must-revalidate"
28501 + [2]=>
28502 + array(1) {
28503 + ["max-age"]=>
28504 + string(1) "0"
28505 + }
28506 + }
28507 +}
28508 +string(1) "a"
28509 +array(1) {
28510 + ["a"]=>
28511 + string(1) "b"
28512 +}
28513 +Done
28514 --- /dev/null
28515 +++ b/ext/http/tests/persistent_handles_001.phpt
28516 @@ -0,0 +1,91 @@
28517 +--TEST--
28518 +persistent handles
28519 +--SKIPIF--
28520 +<?php
28521 +include 'skip.inc';
28522 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28523 +skipif(!function_exists('zend_thread_id'), "need ZTS build");
28524 +?>
28525 +--INI--
28526 +http.persistent.handles.limit=-1
28527 +http.persistent.handles.ident=GLOBAL
28528 +--FILE--
28529 +<?php
28530 +echo "-TEST\n";
28531 +
28532 +echo "No free handles!\n";
28533 +foreach (http_persistent_handles_count() as $provider => $idents) {
28534 + foreach ((array)$idents as $ident => $counts) {
28535 + if (!empty($counts["free"])) {
28536 + printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
28537 + }
28538 + }
28539 +}
28540 +
28541 +http_get("http://www.google.com/", null, $info[]);
28542 +
28543 +echo "One free request handle within GLOBAL: ";
28544 +var_dump(http_persistent_handles_count()->http_request["GLOBAL"]["free"]);
28545 +
28546 +echo "Reusing request handle: ";
28547 +http_get("http://www.google.com/", null, $info[]);
28548 +var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
28549 +
28550 +echo "Handles' been cleaned up:\n";
28551 +http_persistent_handles_clean();
28552 +print_r(http_persistent_handles_count());
28553 +
28554 +echo "Done\n";
28555 +?>
28556 +--EXPECTF--
28557 +%aTEST
28558 +No free handles!
28559 +One free request handle within GLOBAL: int(1)
28560 +Reusing request handle: bool(true)
28561 +float(%f)
28562 +float(%f)
28563 +Handles' been cleaned up:
28564 +stdClass Object
28565 +(
28566 + [http_request] => Array
28567 + (
28568 + [GLOBAL] => Array
28569 + (
28570 + [used] => 0
28571 + [free] => 0
28572 + )
28573 +
28574 + )
28575 +
28576 + [http_request_datashare] => Array
28577 + (
28578 + [GLOBAL] => Array
28579 + (
28580 + [used] => 0
28581 + [free] => 0
28582 + )
28583 +
28584 + )
28585 +
28586 + [http_request_datashare_lock] => Array
28587 + (
28588 + [GLOBAL] => Array
28589 + (
28590 + [used] => 0
28591 + [free] => 0
28592 + )
28593 +
28594 + )
28595 +
28596 + [http_request_pool] => Array
28597 + (
28598 + [GLOBAL] => Array
28599 + (
28600 + [used] => 0
28601 + [free] => 0
28602 + )
28603 +
28604 + )
28605 +
28606 +)
28607 +Done
28608 --- /dev/null
28609 +++ b/ext/http/tests/persistent_handles_002.phpt
28610 @@ -0,0 +1,83 @@
28611 +--TEST--
28612 +persistent handles
28613 +--SKIPIF--
28614 +<?php
28615 +include 'skip.inc';
28616 +checkmin("5.2.5");
28617 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28618 +skipif(function_exists('zend_thread_id'), "need non-ZTS build");
28619 +?>
28620 +--INI--
28621 +http.persistent.handles.limit=-1
28622 +http.persistent.handles.ident=GLOBAL
28623 +--FILE--
28624 +<?php
28625 +echo "-TEST\n";
28626 +
28627 +echo "No free handles!\n";
28628 +foreach (http_persistent_handles_count() as $provider => $idents) {
28629 + foreach ((array)$idents as $ident => $counts) {
28630 + if (!empty($counts["free"])) {
28631 + printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
28632 + }
28633 + }
28634 +}
28635 +
28636 +http_get("http://www.google.com/", null, $info[]);
28637 +
28638 +echo "One free request handle within GLOBAL: ";
28639 +$h = http_persistent_handles_count();
28640 +var_dump($h->http_request["GLOBAL"]["free"]);
28641 +
28642 +echo "Reusing request handle: ";
28643 +http_get("http://www.google.com/", null, $info[]);
28644 +var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
28645 +
28646 +echo "Handles' been cleaned up:\n";
28647 +http_persistent_handles_clean();
28648 +print_r(http_persistent_handles_count());
28649 +
28650 +echo "Done\n";
28651 +?>
28652 +--EXPECTF--
28653 +%aTEST
28654 +No free handles!
28655 +One free request handle within GLOBAL: int(1)
28656 +Reusing request handle: bool(true)
28657 +float(%f)
28658 +float(%f)
28659 +Handles' been cleaned up:
28660 +stdClass Object
28661 +(
28662 + [http_request] => Array
28663 + (
28664 + [GLOBAL] => Array
28665 + (
28666 + [used] => 0
28667 + [free] => 0
28668 + )
28669 +
28670 + )
28671 +
28672 + [http_request_datashare] => Array
28673 + (
28674 + [GLOBAL] => Array
28675 + (
28676 + [used] => 0
28677 + [free] => 0
28678 + )
28679 +
28680 + )
28681 +
28682 + [http_request_pool] => Array
28683 + (
28684 + [GLOBAL] => Array
28685 + (
28686 + [used] => 0
28687 + [free] => 0
28688 + )
28689 +
28690 + )
28691 +
28692 +)
28693 +Done
28694 --- /dev/null
28695 +++ b/ext/http/tests/persistent_handles_003.phpt
28696 @@ -0,0 +1,62 @@
28697 +--TEST--
28698 +persistent handles
28699 +--SKIPIF--
28700 +<?php
28701 +include 'skip.inc';
28702 +checkmax(4.4);
28703 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28704 +?>
28705 +--INI--
28706 +http.persistent.handles.limit=-1
28707 +http.persistent.handles.ident=GLOBAL
28708 +--FILE--
28709 +<?php
28710 +echo "-TEST\n";
28711 +
28712 +echo "No free handles!\n";
28713 +foreach (http_persistent_handles_count() as $provider => $idents) {
28714 + foreach ((array)$idents as $ident => $counts) {
28715 + if (!empty($counts["free"])) {
28716 + printf("%a, %a, %a\n", $provider, $ident, $counts["free"]);
28717 + }
28718 + }
28719 +}
28720 +
28721 +http_get("http://www.google.com/", null, $info[]);
28722 +
28723 +echo "One free request handle within GLOBAL: ";
28724 +$h = http_persistent_handles_count();
28725 +var_dump($h->http_request["GLOBAL"]["free"]);
28726 +
28727 +echo "Reusing request handle: ";
28728 +http_get("http://www.google.com/", null, $info[]);
28729 +var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]);
28730 +
28731 +echo "Handles' been cleaned up:\n";
28732 +http_persistent_handles_clean();
28733 +print_r(http_persistent_handles_count());
28734 +
28735 +echo "Done\n";
28736 +?>
28737 +--EXPECTF--
28738 +%aTEST
28739 +No free handles!
28740 +One free request handle within GLOBAL: int(1)
28741 +Reusing request handle: bool(true)
28742 +float(%f)
28743 +float(%f)
28744 +Handles' been cleaned up:
28745 +stdClass Object
28746 +(
28747 + [http_request] => Array
28748 + (
28749 + [GLOBAL] => Array
28750 + (
28751 + [used] => 0
28752 + [free] => 0
28753 + )
28754 +
28755 + )
28756 +
28757 +)
28758 +Done
28759 --- /dev/null
28760 +++ b/ext/http/tests/redirect_011.phpt
28761 @@ -0,0 +1,24 @@
28762 +--TEST--
28763 +http_redirect() with params
28764 +--SKIPIF--
28765 +<?php
28766 +include 'skip.inc';
28767 +checkcgi();
28768 +checkmin("5.2.5");
28769 +?>
28770 +--ENV--
28771 +HTTP_HOST=localhost
28772 +--FILE--
28773 +<?php
28774 +include 'log.inc';
28775 +log_prepare(_REDIR_LOG);
28776 +http_redirect('redirect', array('a' => 1, 'b' => 2));
28777 +?>
28778 +--EXPECTF--
28779 +Status: 302%s
28780 +X-Powered-By: PHP/%a
28781 +Location: http://localhost/redirect?a=1&b=2
28782 +Content-type: %a
28783 +
28784 +Redirecting to <a href="http://localhost/redirect?a=1&b=2">http://localhost/redirect?a=1&b=2</a>.
28785 +
28786 --- /dev/null
28787 +++ b/ext/http/tests/redirect_011_logging.phpt
28788 @@ -0,0 +1,21 @@
28789 +--TEST--
28790 +logging redirects
28791 +--SKIPIF--
28792 +<?php
28793 +include 'skip.inc';
28794 +checkcgi();
28795 +checkmin("5.2.5");
28796 +?>
28797 +--ENV--
28798 +HTTP_HOST=example.com
28799 +--FILE--
28800 +<?php
28801 +echo "-TEST\n";
28802 +include 'log.inc';
28803 +log_content(_REDIR_LOG);
28804 +echo "Done";
28805 +?>
28806 +--EXPECTF--
28807 +%aTEST
28808 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a>
28809 +Done
28810 --- /dev/null
28811 +++ b/ext/http/tests/redirect_012.phpt
28812 @@ -0,0 +1,27 @@
28813 +--TEST--
28814 +http_redirect() with session
28815 +--SKIPIF--
28816 +<?php
28817 +include 'skip.inc';
28818 +checkcgi();
28819 +checkmin("5.2.5");
28820 +checkext('session');
28821 +?>
28822 +--ENV--
28823 +HTTP_HOST=localhost
28824 +--FILE--
28825 +<?php
28826 +include 'log.inc';
28827 +log_prepare(_REDIR_LOG);
28828 +session_start();
28829 +http_redirect('redirect', array('a' => 1), true);
28830 +?>
28831 +--EXPECTF--
28832 +Status: 302%s
28833 +X-Powered-By: PHP/%a
28834 +Set-Cookie: PHPSESSID=%a; path=/
28835 +Expires: %a
28836 +Cache-Control: %a
28837 +Pragma: %a
28838 +Location: http://localhost/redirect?a=1&PHPSESSID=%a
28839 +Content-type: %a
28840 --- /dev/null
28841 +++ b/ext/http/tests/redirect_012_logging.phpt
28842 @@ -0,0 +1,22 @@
28843 +--TEST--
28844 +logging redirects
28845 +--SKIPIF--
28846 +<?php
28847 +include 'skip.inc';
28848 +checkcgi();
28849 +checkmin("5.2.5");
28850 +checkext("session");
28851 +?>
28852 +--ENV--
28853 +HTTP_HOST=example.com
28854 +--FILE--
28855 +<?php
28856 +echo "-TEST\n";
28857 +include 'log.inc';
28858 +log_content(_REDIR_LOG);
28859 +echo "Done";
28860 +?>
28861 +--EXPECTF--
28862 +%aTEST
28863 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a>
28864 +Done
28865 --- /dev/null
28866 +++ b/ext/http/tests/redirect_013.phpt
28867 @@ -0,0 +1,24 @@
28868 +--TEST--
28869 +http_redirect() permanent
28870 +--SKIPIF--
28871 +<?php
28872 +include 'skip.inc';
28873 +checkcgi();
28874 +checkmin("5.2.5");
28875 +?>
28876 +--ENV--
28877 +HTTP_HOST=localhost
28878 +--FILE--
28879 +<?php
28880 +include 'log.inc';
28881 +log_prepare(_REDIR_LOG);
28882 +http_redirect('redirect', null, false, HTTP_REDIRECT_PERM);
28883 +?>
28884 +--EXPECTF--
28885 +Status: 301%s
28886 +X-Powered-By: PHP/%a
28887 +Location: http://localhost/redirect
28888 +Content-type: %a
28889 +
28890 +Redirecting to <a href="http://localhost/redirect">http://localhost/redirect</a>.
28891 +
28892 --- /dev/null
28893 +++ b/ext/http/tests/redirect_013_logging.phpt
28894 @@ -0,0 +1,21 @@
28895 +--TEST--
28896 +logging redirects
28897 +--SKIPIF--
28898 +<?php
28899 +include 'skip.inc';
28900 +checkcgi();
28901 +checkmin("5.2.5");
28902 +?>
28903 +--ENV--
28904 +HTTP_HOST=example.com
28905 +--FILE--
28906 +<?php
28907 +echo "-TEST\n";
28908 +include 'log.inc';
28909 +log_content(_REDIR_LOG);
28910 +echo "Done";
28911 +?>
28912 +--EXPECTF--
28913 +%aTEST
28914 +%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [301-REDIRECT] Location: http%a <%a>
28915 +Done
28916 --- /dev/null
28917 +++ b/ext/http/tests/request_cookies.phpt
28918 @@ -0,0 +1,52 @@
28919 +--TEST--
28920 +urlencoded cookies
28921 +--SKIPIF--
28922 +<?php
28923 +include 'skip.inc';
28924 +checkver(5);
28925 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28926 +?>
28927 +--FILE--
28928 +<?php
28929 +echo "-TEST\n";
28930 +
28931 +$cookies = array("name" => "val=ue");
28932 +
28933 +$r = new HttpRequest("http://dev.iworks.at/ext-http/.print_request.php", HTTP_METH_GET, array("cookies" => $cookies));
28934 +$r->recordHistory = true;
28935 +$r->send();
28936 +$r->setOptions(array('encodecookies' => false));
28937 +$r->send();
28938 +echo $r->getHistory()->toString(true);
28939 +
28940 +echo "Done\n";
28941 +?>
28942 +--EXPECTF--
28943 +%aTEST
28944 +GET /ext-http/.print_request.php HTTP/1.1
28945 +User-Agent: %a
28946 +Host: dev.iworks.at
28947 +Accept: */*
28948 +Cookie: name=val%3Due
28949 +HTTP/1.1 200 OK
28950 +%a
28951 +
28952 +Array
28953 +(
28954 + [name] => val=ue
28955 +)
28956 +
28957 +GET /ext-http/.print_request.php HTTP/1.1
28958 +User-Agent: %a
28959 +Host: dev.iworks.at
28960 +Accept: */*
28961 +Cookie: name=val=ue;
28962 +HTTP/1.1 200 OK
28963 +%a
28964 +
28965 +Array
28966 +(
28967 + [name] => val=ue
28968 +)
28969 +
28970 +Done
28971 --- /dev/null
28972 +++ b/ext/http/tests/request_etag.phpt
28973 @@ -0,0 +1,21 @@
28974 +--TEST--
28975 +request etag
28976 +--SKIPIF--
28977 +<?php
28978 +include 'skip.inc';
28979 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
28980 +?>
28981 +--FILE--
28982 +<?php
28983 +echo "-TEST\n";
28984 +var_dump(http_get("http://dev.iworks.at/ext-http/etag", array("etag" => '"26ad3a-5-95eb19c0"')));
28985 +echo "Done\n";
28986 +?>
28987 +--EXPECTF--
28988 +%aTEST
28989 +string(%d) "HTTP/1.1 304 Not Modified
28990 +Date: %a
28991 +Server: %a
28992 +ETag: "26ad3a-5-95eb19c0"
28993 +"
28994 +Done
28995 \ No newline at end of file
28996 --- /dev/null
28997 +++ b/ext/http/tests/request_gzip.phpt
28998 @@ -0,0 +1,51 @@
28999 +--TEST--
29000 +GZIP request
29001 +--SKIPIF--
29002 +<?php
29003 +include 'skip.inc';
29004 +checkurl('dev.iworks.at');
29005 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), 'need curl support');
29006 +?>
29007 +--FILE--
29008 +<?php
29009 +echo "-TEST\n";
29010 +
29011 +var_dump(http_parse_message(http_get('http://dev.iworks.at/ext-http/.print_request.php?gzip=1', array('compress' => true))));
29012 +
29013 +echo "Done\n";
29014 +--EXPECTF--
29015 +%aTEST
29016 +object(stdClass)%a {
29017 + ["type"]=>
29018 + int(2)
29019 + ["httpVersion"]=>
29020 + float(1.1)
29021 + ["responseCode"]=>
29022 + int(200)
29023 + ["responseStatus"]=>
29024 + string(2) "OK"
29025 + ["headers"]=>
29026 + array(%d) {
29027 + %a
29028 + ["Vary"]=>
29029 + string(15) "Accept-Encoding"
29030 + ["Content-Length"]=>
29031 + string(2) "26"
29032 + ["Content-Type"]=>
29033 + string(9) "text/html"
29034 + ["X-Original-Content-Encoding"]=>
29035 + string(4) "gzip"
29036 + ["X-Original-Content-Length"]=>
29037 + string(2) "51"
29038 + }
29039 + ["body"]=>
29040 + string(26) "Array
29041 +(
29042 + [gzip] => 1
29043 +)
29044 +"
29045 + ["parentMessage"]=>
29046 + NULL
29047 +}
29048 +Done
29049 +
29050 --- /dev/null
29051 +++ b/ext/http/tests/request_methods.phpt
29052 @@ -0,0 +1,144 @@
29053 +--TEST--
29054 +request methods
29055 +--SKIPIF--
29056 +<?php
29057 +include 'skip.inc';
29058 +?>
29059 +--FILE--
29060 +<?php
29061 +echo "-TEST\n";
29062 +
29063 +for ($i = 0; $i <= HTTP_METH_ACL+1; ++$i) {
29064 + var_dump(http_request_method_exists($i));
29065 + echo $name = http_request_method_name($i), "\n";
29066 + var_dump(http_request_method_exists($name));
29067 +}
29068 +
29069 +for ($i = 0; $i < 5; ++$i) {
29070 + $n = http_request_method_register("M$i");
29071 + var_dump(http_request_method_exists($n));
29072 + var_dump(http_request_method_exists("M$i"));
29073 +}
29074 +for ($i = 0; $i < 5; ++$i) {
29075 + var_dump(http_request_method_unregister("M$i"));
29076 + var_dump(http_request_method_exists("M$i"));
29077 + var_dump(http_request_method_exists($i+HTTP_METH_ACL+1));
29078 +}
29079 +
29080 +echo "Done\n";
29081 +?>
29082 +--EXPECTF--
29083 +%aTEST
29084 +int(0)
29085 +UNKNOWN
29086 +int(0)
29087 +int(1)
29088 +GET
29089 +int(1)
29090 +int(2)
29091 +HEAD
29092 +int(2)
29093 +int(3)
29094 +POST
29095 +int(3)
29096 +int(4)
29097 +PUT
29098 +int(4)
29099 +int(5)
29100 +DELETE
29101 +int(5)
29102 +int(6)
29103 +OPTIONS
29104 +int(6)
29105 +int(7)
29106 +TRACE
29107 +int(7)
29108 +int(8)
29109 +CONNECT
29110 +int(8)
29111 +int(9)
29112 +PROPFIND
29113 +int(9)
29114 +int(10)
29115 +PROPPATCH
29116 +int(10)
29117 +int(11)
29118 +MKCOL
29119 +int(11)
29120 +int(12)
29121 +COPY
29122 +int(12)
29123 +int(13)
29124 +MOVE
29125 +int(13)
29126 +int(14)
29127 +LOCK
29128 +int(14)
29129 +int(15)
29130 +UNLOCK
29131 +int(15)
29132 +int(16)
29133 +VERSION-CONTROL
29134 +int(16)
29135 +int(17)
29136 +REPORT
29137 +int(17)
29138 +int(18)
29139 +CHECKOUT
29140 +int(18)
29141 +int(19)
29142 +CHECKIN
29143 +int(19)
29144 +int(20)
29145 +UNCHECKOUT
29146 +int(20)
29147 +int(21)
29148 +MKWORKSPACE
29149 +int(21)
29150 +int(22)
29151 +UPDATE
29152 +int(22)
29153 +int(23)
29154 +LABEL
29155 +int(23)
29156 +int(24)
29157 +MERGE
29158 +int(24)
29159 +int(25)
29160 +BASELINE-CONTROL
29161 +int(25)
29162 +int(26)
29163 +MKACTIVITY
29164 +int(26)
29165 +int(27)
29166 +ACL
29167 +int(27)
29168 +int(0)
29169 +UNKNOWN
29170 +int(0)
29171 +int(28)
29172 +int(28)
29173 +int(29)
29174 +int(29)
29175 +int(30)
29176 +int(30)
29177 +int(31)
29178 +int(31)
29179 +int(32)
29180 +int(32)
29181 +bool(true)
29182 +int(0)
29183 +int(0)
29184 +bool(true)
29185 +int(0)
29186 +int(0)
29187 +bool(true)
29188 +int(0)
29189 +int(0)
29190 +bool(true)
29191 +int(0)
29192 +int(0)
29193 +bool(true)
29194 +int(0)
29195 +int(0)
29196 +Done
29197 --- /dev/null
29198 +++ b/ext/http/tests/request_put_data.phpt
29199 @@ -0,0 +1,22 @@
29200 +--TEST--
29201 +http_put_data()
29202 +--SKIPIF--
29203 +<?php
29204 +include 'skip.inc';
29205 +skipif(!http_support(HTTP_SUPPORT_REQUESTS), "need request support");
29206 +?>
29207 +--FILE--
29208 +<?php
29209 +echo "-TEST\n";
29210 +
29211 +$data = str_repeat("abc", 6000/* > CURLBUF_SIZE */);
29212 +$resp = http_put_data("http://dev.iworks.at/ext-http/.print_put.php5", $data);
29213 +$mess = http_parse_message($resp);
29214 +var_dump($data === $mess->body);
29215 +
29216 +echo "Done\n";
29217 +?>
29218 +--EXPECTF--
29219 +%aTEST
29220 +bool(true)
29221 +Done
29222 --- /dev/null
29223 +++ b/ext/http/tests/send_data_001.phpt
29224 @@ -0,0 +1,24 @@
29225 +--TEST--
29226 +http_send_data() NIL-NUM range
29227 +--SKIPIF--
29228 +<?php
29229 +include 'skip.inc';
29230 +checkcgi();
29231 +checkmin("5.2.5");
29232 +?>
29233 +--ENV--
29234 +HTTP_RANGE=bytes=-5
29235 +--FILE--
29236 +<?php
29237 +http_send_content_type('text/plain');
29238 +http_send_data(str_repeat('123abc', 1000));
29239 +?>
29240 +--EXPECTF--
29241 +Status: 206%s
29242 +X-Powered-By: PHP/%s
29243 +Content-Type: text/plain
29244 +Accept-Ranges: bytes
29245 +Content-Range: bytes 5995-5999/6000
29246 +Content-Length: 5
29247 +
29248 +23abc
29249 --- /dev/null
29250 +++ b/ext/http/tests/send_data_002.phpt
29251 @@ -0,0 +1,24 @@
29252 +--TEST--
29253 +http_send_data() NUM-NUM range
29254 +--SKIPIF--
29255 +<?php
29256 +include 'skip.inc';
29257 +checkcgi();
29258 +checkmin("5.2.5");
29259 +?>
29260 +--ENV--
29261 +HTTP_RANGE=bytes=5-6
29262 +--FILE--
29263 +<?php
29264 +http_send_content_type('text/plain');
29265 +http_send_data(str_repeat('123abc', 1000));
29266 +?>
29267 +--EXPECTF--
29268 +Status: 206%s
29269 +X-Powered-By: PHP/%s
29270 +Content-Type: text/plain
29271 +Accept-Ranges: bytes
29272 +Content-Range: bytes 5-6/6000
29273 +Content-Length: 2
29274 +
29275 +c1
29276 --- /dev/null
29277 +++ b/ext/http/tests/send_data_003.phpt
29278 @@ -0,0 +1,24 @@
29279 +--TEST--
29280 +http_send_data() NUM-NIL range
29281 +--SKIPIF--
29282 +<?php
29283 +include 'skip.inc';
29284 +checkcgi();
29285 +checkmin("5.2.5");
29286 +?>
29287 +--ENV--
29288 +HTTP_RANGE=bytes=5981-
29289 +--FILE--
29290 +<?php
29291 +http_send_content_type('text/plain');
29292 +http_send_data(str_repeat('123abc', 1000));
29293 +?>
29294 +--EXPECTF--
29295 +Status: 206%s
29296 +X-Powered-By: PHP/%s
29297 +Content-Type: text/plain
29298 +Accept-Ranges: bytes
29299 +Content-Range: bytes 5981-5999/6000
29300 +Content-Length: 19
29301 +
29302 +c123abc123abc123abc
29303 --- /dev/null
29304 +++ b/ext/http/tests/send_data_004.phpt
29305 @@ -0,0 +1,22 @@
29306 +--TEST--
29307 +http_send_data() syntactically invalid range
29308 +--SKIPIF--
29309 +<?php
29310 +include 'skip.inc';
29311 +checkcgi();
29312 +checkmin(5);
29313 +?>
29314 +--ENV--
29315 +HTTP_RANGE=bytes=123,-wtf ?
29316 +--FILE--
29317 +<?php
29318 +http_send_content_type('text/plain');
29319 +http_send_data(str_repeat('123abc', 1000));
29320 +?>
29321 +--EXPECTF--
29322 +X-Powered-By: PHP/%s
29323 +Content-Type: text/plain
29324 +Accept-Ranges: bytes
29325 +Content-Length: 6000
29326 +
29327 +123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc
29328 \ No newline at end of file
29329 --- /dev/null
29330 +++ b/ext/http/tests/send_data_005.phpt
29331 @@ -0,0 +1,17 @@
29332 +--TEST--
29333 +http_send_data() oversized range
29334 +--SKIPIF--
29335 +<?php
29336 +include 'skip.inc';
29337 +checkcgi();
29338 +checkmin("5.2.5");
29339 +?>
29340 +--ENV--
29341 +HTTP_RANGE=bytes=5990-6000
29342 +--FILE--
29343 +<?php
29344 +http_send_content_type('text/plain');
29345 +http_send_data(str_repeat('123abc', 1000));
29346 +?>
29347 +--EXPECTF--
29348 +Status: 416%a
29349 \ No newline at end of file
29350 --- /dev/null
29351 +++ b/ext/http/tests/send_data_006.phpt
29352 @@ -0,0 +1,38 @@
29353 +--TEST--
29354 +http_send_data() multiple ranges
29355 +--SKIPIF--
29356 +<?php
29357 +include 'skip.inc';
29358 +checkcgi();
29359 +checkmin("5.2.5");
29360 +?>
29361 +--ENV--
29362 +HTTP_RANGE=bytes=0-3, 4-5,9-11
29363 +--FILE--
29364 +<?php
29365 +http_send_content_type('text/plain');
29366 +http_send_data(str_repeat('123abc', 1000));
29367 +?>
29368 +--EXPECTF--
29369 +Status: 206%s
29370 +X-Powered-By: PHP/%s
29371 +Accept-Ranges: bytes
29372 +Content-Type: multipart/byteranges; boundary=%d.%d
29373 +
29374 +
29375 +--%d.%d
29376 +Content-Type: text/plain
29377 +Content-Range: bytes 0-3/6000
29378 +
29379 +123a
29380 +--%d.%d
29381 +Content-Type: text/plain
29382 +Content-Range: bytes 4-5/6000
29383 +
29384 +bc
29385 +--%d.%d
29386 +Content-Type: text/plain
29387 +Content-Range: bytes 9-11/6000
29388 +
29389 +abc
29390 +--%d.%d--
29391 --- /dev/null
29392 +++ b/ext/http/tests/send_data_010.phpt
29393 @@ -0,0 +1,20 @@
29394 +--TEST--
29395 +http_send_data() HTTP_SENDBUF_SIZE long string
29396 +--SKIPIF--
29397 +<?php
29398 +include 'skip.inc';
29399 +checkcgi();
29400 +checkmin(5.1);
29401 +?>
29402 +--FILE--
29403 +<?php
29404 +http_throttle(0.01, 1);
29405 +http_send_data('00000000000000000000');
29406 +?>
29407 +--EXPECTF--
29408 +X-Powered-By: PHP/%s
29409 +Accept-Ranges: bytes
29410 +Content-Length: 20
29411 +Content-type: %s
29412 +
29413 +00000000000000000000
29414 --- /dev/null
29415 +++ b/ext/http/tests/send_data_011.phpt
29416 @@ -0,0 +1,22 @@
29417 +--TEST--
29418 +http_send_data() last modified caching
29419 +--SKIPIF--
29420 +<?php
29421 +include 'skip.inc';
29422 +checkcgi();
29423 +checkmin(5.1);
29424 +?>
29425 +--FILE--
29426 +<?php
29427 +http_cache_last_modified(-5);
29428 +http_send_data("abc\n");
29429 +?>
29430 +--EXPECTF--
29431 +X-Powered-By: PHP/%s
29432 +Cache-Control: private, must-revalidate, max-age=0
29433 +Last-Modified: %s, %d %s %d %d:%d:%d GMT
29434 +Accept-Ranges: bytes
29435 +Content-Length: 4
29436 +Content-type: %s
29437 +
29438 +abc
29439 --- /dev/null
29440 +++ b/ext/http/tests/send_failed_precond_001.phpt
29441 @@ -0,0 +1,23 @@
29442 +--TEST--
29443 +http_send() failed precondition
29444 +--SKIPIF--
29445 +<?php
29446 +include 'skip.inc';
29447 +checkcgi();
29448 +checkver(5.1);
29449 +?>
29450 +--ENV--
29451 +HTTP_RANGE=bytes=0-1
29452 +HTTP_IF_UNMODIFIED_SINCE=Thu, 01 Jan 1970 00:16:40 GMT
29453 +--FILE--
29454 +<?php
29455 +http_cache_last_modified();
29456 +http_send_file(__FILE__);
29457 +?>
29458 +--EXPECTF--
29459 +Status: 412%s
29460 +X-Powered-By: %s
29461 +Cache-Control: private, must-revalidate, max-age=0
29462 +Last-Modified: %s
29463 +Accept-Ranges: bytes
29464 +Content-type: text/html
29465 --- /dev/null
29466 +++ b/ext/http/tests/send_file_005.phpt
29467 @@ -0,0 +1,38 @@
29468 +--TEST--
29469 +http_send_file() multiple ranges
29470 +--SKIPIF--
29471 +<?php
29472 +include 'skip.inc';
29473 +checkcgi();
29474 +checkmin("5.2.5");
29475 +?>
29476 +--ENV--
29477 +HTTP_RANGE=bytes=0-3, 4-5,9-11
29478 +--FILE--
29479 +<?php
29480 +http_send_content_type('text/plain');
29481 +http_send_file('data.txt');
29482 +?>
29483 +--EXPECTF--
29484 +Status: 206%s
29485 +X-Powered-By: PHP/%s
29486 +Accept-Ranges: bytes
29487 +Content-Type: multipart/byteranges; boundary=%d.%d
29488 +
29489 +
29490 +--%d.%d
29491 +Content-Type: text/plain
29492 +Content-Range: bytes 0-3/1010
29493 +
29494 +0123
29495 +--%d.%d
29496 +Content-Type: text/plain
29497 +Content-Range: bytes 4-5/1010
29498 +
29499 +45
29500 +--%d.%d
29501 +Content-Type: text/plain
29502 +Content-Range: bytes 9-11/1010
29503 +
29504 +901
29505 +--%d.%d--
29506 --- /dev/null
29507 +++ b/ext/http/tests/send_file_008.phpt
29508 @@ -0,0 +1,28 @@
29509 +--TEST--
29510 +http_send_file()
29511 +--SKIPIF--
29512 +<?php
29513 +include 'skip.inc';
29514 +checkcgi();
29515 +checkmin(5.1);
29516 +?>
29517 +--FILE--
29518 +<?php
29519 +http_send_file('data.txt');
29520 +?>
29521 +--EXPECTF--
29522 +X-Powered-By: PHP/%s
29523 +Accept-Ranges: bytes
29524 +Content-Length: 1010
29525 +Content-type: %s
29526 +
29527 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29528 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29529 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29530 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29531 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29532 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29533 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29534 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29535 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29536 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29537 --- /dev/null
29538 +++ b/ext/http/tests/send_file_009.phpt
29539 @@ -0,0 +1,23 @@
29540 +--TEST--
29541 +http_send_file() NUM-NUM range
29542 +--SKIPIF--
29543 +<?php
29544 +include 'skip.inc';
29545 +checkcgi();
29546 +checkmin("5.2.5");
29547 +?>
29548 +--ENV--
29549 +HTTP_RANGE=bytes=5-9
29550 +--FILE--
29551 +<?php
29552 +http_send_file('data.txt');
29553 +?>
29554 +--EXPECTF--
29555 +Status: 206%s
29556 +X-Powered-By: PHP/%s
29557 +Accept-Ranges: bytes
29558 +Content-Range: bytes 5-9/1010
29559 +Content-Length: 5
29560 +Content-type: %s
29561 +
29562 +56789
29563 --- /dev/null
29564 +++ b/ext/http/tests/send_file_010.phpt
29565 @@ -0,0 +1,23 @@
29566 +--TEST--
29567 +http_send_file() NIL-NUM range
29568 +--SKIPIF--
29569 +<?php
29570 +include 'skip.inc';
29571 +checkcgi();
29572 +checkmin("5.2.5");
29573 +?>
29574 +--ENV--
29575 +HTTP_RANGE=bytes=-9
29576 +--FILE--
29577 +<?php
29578 +http_send_file('data.txt');
29579 +?>
29580 +--EXPECTF--
29581 +Status: 206%s
29582 +X-Powered-By: PHP/%s
29583 +Accept-Ranges: bytes
29584 +Content-Range: bytes 1001-1009/1010
29585 +Content-Length: 9
29586 +Content-type: %s
29587 +
29588 +23456789
29589 --- /dev/null
29590 +++ b/ext/http/tests/send_file_011.phpt
29591 @@ -0,0 +1,23 @@
29592 +--TEST--
29593 +http_send_file() NUM-NIL range
29594 +--SKIPIF--
29595 +<?php
29596 +include 'skip.inc';
29597 +checkcgi();
29598 +checkmin("5.2.5");
29599 +?>
29600 +--ENV--
29601 +HTTP_RANGE=bytes=1000-
29602 +--FILE--
29603 +<?php
29604 +http_send_file('data.txt');
29605 +?>
29606 +--EXPECTF--
29607 +Status: 206%s
29608 +X-Powered-By: PHP/%s
29609 +Accept-Ranges: bytes
29610 +Content-Range: bytes 1000-1009/1010
29611 +Content-Length: 10
29612 +Content-type: %s
29613 +
29614 +123456789
29615 --- /dev/null
29616 +++ b/ext/http/tests/send_file_012.phpt
29617 @@ -0,0 +1,30 @@
29618 +--TEST--
29619 +http_send_file() syntactically invalid range
29620 +--SKIPIF--
29621 +<?php
29622 +include 'skip.inc';
29623 +checkcgi();
29624 +checkmin(5.1);
29625 +?>
29626 +--ENV--
29627 +HTTP_RANGE=bytes=xxx
29628 +--FILE--
29629 +<?php
29630 +http_send_file('data.txt');
29631 +?>
29632 +--EXPECTF--
29633 +X-Powered-By: PHP/%s
29634 +Accept-Ranges: bytes
29635 +Content-Length: 1010
29636 +Content-type: %s
29637 +
29638 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29639 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29640 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29641 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29642 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29643 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29644 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29645 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29646 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29647 +0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
29648 --- /dev/null
29649 +++ b/ext/http/tests/send_file_013.phpt
29650 @@ -0,0 +1,19 @@
29651 +--TEST--
29652 +http_send_file() oversized range
29653 +--SKIPIF--
29654 +<?php
29655 +include 'skip.inc';
29656 +checkcgi();
29657 +checkmin("5.2.5");
29658 +?>
29659 +--ENV--
29660 +HTTP_RANGE=bytes=-1111
29661 +--FILE--
29662 +<?php
29663 +http_send_file('data.txt');
29664 +?>
29665 +--EXPECTF--
29666 +Status: 416
29667 +X-Powered-By: PHP/%s
29668 +Accept-Ranges: bytes
29669 +Content-type: %s
29670 --- /dev/null
29671 +++ b/ext/http/tests/send_ifrange_001.phpt
29672 @@ -0,0 +1,27 @@
29673 +--TEST--
29674 +http_send() If-Range
29675 +--SKIPIF--
29676 +<?php
29677 +include 'skip.inc';
29678 +checkcgi();
29679 +checkmin("5.2.5");
29680 +?>
29681 +--ENV--
29682 +HTTP_RANGE=bytes=0-1
29683 +HTTP_IF_RANGE="abc"
29684 +--FILE--
29685 +<?php
29686 +http_cache_etag('abc');
29687 +http_send_file(__FILE__);
29688 +?>
29689 +--EXPECTF--
29690 +Status: 206%s
29691 +X-Powered-By: %s
29692 +Cache-Control: private, must-revalidate, max-age=0
29693 +ETag: "abc"
29694 +Accept-Ranges: bytes
29695 +Content-Range: bytes 0-1/%d
29696 +Content-Length: 2
29697 +Content-type: text/html
29698 +
29699 +<?
29700 --- /dev/null
29701 +++ b/ext/http/tests/send_ifrange_003.phpt
29702 @@ -0,0 +1,25 @@
29703 +--TEST--
29704 +http_send() If-Range
29705 +--SKIPIF--
29706 +<?php
29707 +include 'skip.inc';
29708 +checkcgi();
29709 +checkmin("5.2.5");
29710 +?>
29711 +--ENV--
29712 +HTTP_RANGE=bytes=0-1
29713 +HTTP_IF_RANGE="abcd"
29714 +--FILE--
29715 +<?php
29716 +http_cache_etag('abc');
29717 +http_send_file(__FILE__);
29718 +?>
29719 +--EXPECTF--
29720 +X-Powered-By: %s
29721 +Cache-Control: private, must-revalidate, max-age=0
29722 +ETag: "abc"
29723 +Accept-Ranges: bytes
29724 +Content-Length: %d
29725 +Content-type: text/html
29726 +
29727 +%a
29728 --- /dev/null
29729 +++ b/ext/http/tests/skip.inc
29730 @@ -0,0 +1,15 @@
29731 +<?php
29732 +defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
29733 +if (!function_exists('fprintf')) {
29734 + function fprintf(){ $a=func_get_args(); $s=array_shift($a); return fwrite($s, call_user_func_array('sprintf',$a)); }
29735 +}
29736 +function skipif($if, $skip) { if ($if) { fprintf(STDOUT, "skip $skip"); exit(); }}
29737 +function checkcgi() { skipif(!strncasecmp('CLI', PHP_SAPI, 3), 'need CGI SAPI'); }
29738 +function checkext($ext) { skipif(!extension_loaded($ext), "need ext/$ext"); }
29739 +function checkmin($ver) { skipif(version_compare(PHP_VERSION, $ver) < 0, sprintf("need PHP >= v%s",$ver)); }
29740 +function checkmax($ver) { skipif(version_compare(PHP_VERSION, $ver) > 0, sprintf("need PHP <= v%s",$ver)); }
29741 +function checkurl($url) { skipif(!@fsockopen($url, 80), "$url not responsive"); }
29742 +function checkcls($cls) { skipif(!class_exists($cls), "need class $cls"); }
29743 +function checkver($ver) { checkmin($ver); }
29744 +checkext('http');
29745 +?>
29746 --- /dev/null
29747 +++ b/ext/http/tests/stream_filters_001.phpt
29748 @@ -0,0 +1,45 @@
29749 +--TEST--
29750 +stream filters
29751 +--SKIPIF--
29752 +<?php
29753 +include 'skip.inc';
29754 +checkmin("5.2.5");
29755 +?>
29756 +--FILE--
29757 +<?php
29758 +echo "-TEST\n";
29759 +
29760 +define('F', 'http.test_stream_filters');
29761 +
29762 +$f = fopen(F, 'w');
29763 +stream_filter_append($f, 'http.chunked_encode');
29764 +
29765 +fwrite($f, "Here ");
29766 +fwrite($f, "we");
29767 +fwrite($f, " go!\n");
29768 +fclose($f);
29769 +
29770 +var_dump(file_get_contents(F));
29771 +
29772 +$f = fopen(F, 'r');
29773 +stream_filter_append($f, 'http.chunked_decode');
29774 +var_dump(fread($f, 256));
29775 +fclose($f);
29776 +
29777 +unlink(F);
29778 +echo "Done\n";
29779 +?>
29780 +--EXPECTF--
29781 +%aTEST
29782 +string(30) "5
29783 +Here
29784 +2
29785 +we
29786 +5
29787 + go!
29788 +
29789 +0
29790 +"
29791 +string(12) "Here we go!
29792 +"
29793 +Done
29794 --- /dev/null
29795 +++ b/ext/http/tests/stream_filters_002.phpt
29796 @@ -0,0 +1,50 @@
29797 +--TEST--
29798 +gzip stream filters
29799 +--SKIPIF--
29800 +<?php
29801 +include 'skip.inc';
29802 +checkver(5);
29803 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib support");
29804 +?>
29805 +--FILE--
29806 +<?php
29807 +
29808 +echo "-TEST\n";
29809 +
29810 +$d = file_get_contents(__FILE__);
29811 +$n = tempnam(dirname(__FILE__), 'hsf');
29812 +
29813 +$f = fopen($n, 'wb');
29814 +stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_GZIP);
29815 +fwrite($f, $d);
29816 +fflush($f);
29817 +fwrite($f, $d);
29818 +fclose($f);
29819 +var_dump($d.$d == http_inflate(file_get_contents($n)));
29820 +
29821 +$f = fopen($n, 'wb');
29822 +stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE);
29823 +fwrite($f, $d);
29824 +fflush($f);
29825 +fwrite($f, $d);
29826 +fclose($f);
29827 +var_dump($d.$d == http_inflate(file_get_contents($n)));
29828 +
29829 +$f = fopen($n, 'wb');
29830 +stream_filter_append($f, 'http.deflate', STREAM_FILTER_WRITE, HTTP_DEFLATE_TYPE_RAW);
29831 +fwrite($f, $d);
29832 +fflush($f);
29833 +fwrite($f, $d);
29834 +fclose($f);
29835 +var_dump($d.$d == http_inflate(file_get_contents($n)));
29836 +
29837 +unlink($n);
29838 +
29839 +echo "Done\n";
29840 +?>
29841 +--EXPECTF--
29842 +%aTEST
29843 +bool(true)
29844 +bool(true)
29845 +bool(true)
29846 +Done
29847 --- /dev/null
29848 +++ b/ext/http/tests/stream_filters_003.phpt
29849 @@ -0,0 +1,42 @@
29850 +--TEST--
29851 +stream filter fun
29852 +--SKIPIF--
29853 +<?php
29854 +include 'skip.inc';
29855 +checkmin("5.2.5");
29856 +skipif(!http_support(HTTP_SUPPORT_ENCODINGS), "need zlib");
29857 +?>
29858 +--FILE--
29859 +<?php
29860 +echo "-TEST\n";
29861 +
29862 +define('OUT', fopen('php://output', 'w'));
29863 +
29864 +stream_filter_append(OUT, 'http.chunked_encode');
29865 +stream_filter_append(OUT, 'http.deflate');
29866 +stream_filter_append(OUT, 'http.chunked_encode');
29867 +stream_filter_append(OUT, 'http.deflate');
29868 +stream_filter_append(OUT, 'http.inflate');
29869 +stream_filter_append(OUT, 'http.chunked_decode');
29870 +stream_filter_append(OUT, 'http.inflate');
29871 +stream_filter_append(OUT, 'http.chunked_decode');
29872 +
29873 +$text = <<<SOME_TEXT
29874 +This is some stream filter fun; we'll see if it bails out or not.
29875 +The text should come out at the other end of the stream exactly like written to it.
29876 +Go figure!
29877 +SOME_TEXT;
29878 +
29879 +srand(time());
29880 +foreach (str_split($text, 5) as $part) {
29881 + fwrite(OUT, $part);
29882 + if (rand(0, 1)) {
29883 + fflush(OUT);
29884 + }
29885 +}
29886 +?>
29887 +--EXPECTF--
29888 +%aTEST
29889 +This is some stream filter fun; we'll see if it bails out or not.
29890 +The text should come out at the other end of the stream exactly like written to it.
29891 +Go figure!
29892 --- /dev/null
29893 +++ b/ext/http/tests/urls.txt
29894 @@ -0,0 +1,49 @@
29895 +http://www.microsoft.com
29896 +http://www.opensource.org
29897 +http://www.google.com
29898 +http://www.yahoo.com
29899 +http://www.ibm.com
29900 +http://www.mysql.com
29901 +http://www.oracle.com
29902 +http://www.ripe.net
29903 +http://www.iana.org
29904 +http://www.amazon.com
29905 +http://www.netcraft.com
29906 +http://www.heise.de
29907 +http://www.chip.de
29908 +http://www.ca.com
29909 +http://www.cnet.com
29910 +http://www.news.com
29911 +http://www.cnn.com
29912 +http://www.wikipedia.org
29913 +http://www.dell.com
29914 +http://www.hp.com
29915 +http://www.cert.org
29916 +http://www.mit.edu
29917 +http://www.nist.gov
29918 +http://www.ebay.com
29919 +http://www.playstation.com
29920 +http://www.uefa.com
29921 +http://www.ieee.org
29922 +http://www.apple.com
29923 +http://www.sony.com
29924 +http://www.symantec.com
29925 +http://www.zdnet.com
29926 +http://www.fujitsu.com
29927 +http://www.supermicro.com
29928 +http://www.hotmail.com
29929 +http://www.ecma.com
29930 +http://www.bbc.co.uk
29931 +http://news.google.com
29932 +http://www.foxnews.com
29933 +http://www.msn.com
29934 +http://www.wired.com
29935 +http://www.sky.com
29936 +http://www.usatoday.com
29937 +http://www.cbs.com
29938 +http://www.nbc.com
29939 +http://slashdot.org
29940 +http://www.bloglines.com
29941 +http://www.techweb.com
29942 +http://www.newslink.org
29943 +http://www.un.org
29944 \ No newline at end of file