2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
13 /* $Id: php_http_request_api.c 298591 2010-04-26 11:46:55Z mike $ */
17 #include <Zend/zend_interfaces.h>
19 #if defined(ZTS) && defined(PHP_HTTP_HAVE_SSL)
21 # define PHP_HTTP_NEED_OPENSSL_TSL
22 # include <openssl/crypto.h>
23 # else /* !PHP_WIN32 */
24 # if defined(PHP_HTTP_HAVE_OPENSSL)
25 # define PHP_HTTP_NEED_OPENSSL_TSL
26 # include <openssl/crypto.h>
27 # elif defined(PHP_HTTP_HAVE_GNUTLS)
28 # define PHP_HTTP_NEED_GNUTLS_TSL
32 "libcurl was compiled with SSL support, but configure could not determine which" \
33 "library was used; thus no SSL crypto locking callbacks will be set, which may " \
34 "cause random crashes on SSL requests"
35 # endif /* PHP_HTTP_HAVE_OPENSSL || PHP_HTTP_HAVE_GNUTLS */
36 # endif /* PHP_WIN32 */
37 #endif /* ZTS && PHP_HTTP_HAVE_SSL */
40 #ifdef PHP_HTTP_NEED_OPENSSL_TSL
41 static MUTEX_T
*php_http_openssl_tsl
= NULL
;
43 static void php_http_openssl_thread_lock(int mode
, int n
, const char * file
, int line
)
45 if (mode
& CRYPTO_LOCK
) {
46 tsrm_mutex_lock(php_http_openssl_tsl
[n
]);
48 tsrm_mutex_unlock(php_http_openssl_tsl
[n
]);
52 static ulong
php_http_openssl_thread_id(void)
54 return (ulong
) tsrm_thread_id();
57 #ifdef PHP_HTTP_NEED_GNUTLS_TSL
58 static int php_http_gnutls_mutex_create(void **m
)
60 if (*((MUTEX_T
*) m
) = tsrm_mutex_alloc()) {
67 static int php_http_gnutls_mutex_destroy(void **m
)
69 tsrm_mutex_free(*((MUTEX_T
*) m
));
73 static int php_http_gnutls_mutex_lock(void **m
)
75 return tsrm_mutex_lock(*((MUTEX_T
*) m
));
78 static int php_http_gnutls_mutex_unlock(void **m
)
80 return tsrm_mutex_unlock(*((MUTEX_T
*) m
));
83 static struct gcry_thread_cbs php_http_gnutls_tsl
= {
84 GCRY_THREAD_OPTION_USER
,
86 php_http_gnutls_mutex_create
,
87 php_http_gnutls_mutex_destroy
,
88 php_http_gnutls_mutex_lock
,
89 php_http_gnutls_mutex_unlock
94 /* safe curl wrappers */
95 #define init_curl_storage(ch) \
97 php_http_request_storage_t *st = pecalloc(1, sizeof(php_http_request_storage_t), 1); \
98 curl_easy_setopt(ch, CURLOPT_PRIVATE, st); \
99 curl_easy_setopt(ch, CURLOPT_ERRORBUFFER, st->errorbuffer); \
102 static void *safe_curl_init(void)
106 if ((ch
= curl_easy_init())) {
107 init_curl_storage(ch
);
112 static void *safe_curl_copy(void *p
)
116 if ((ch
= curl_easy_duphandle(p
))) {
117 init_curl_storage(ch
);
122 static void safe_curl_dtor(void *p
) {
123 php_http_request_storage_t
*st
= php_http_request_storage_get(p
);
125 curl_easy_cleanup(p
);
131 if (st
->cookiestore
) {
132 pefree(st
->cookiestore
, 1);
138 static inline zval
*php_http_request_option(php_http_request_t
*request
, HashTable
*options
, char *key
, size_t keylen
, int type
);
139 static inline zval
*php_http_request_option_cache(php_http_request_t
*r
, char *key
, size_t keylen
, ulong h
, zval
*opt
);
140 static inline int php_http_request_cookies_enabled(php_http_request_t
*r
);
142 static size_t php_http_curl_read_callback(void *, size_t, size_t, void *);
143 static int php_http_curl_progress_callback(void *, double, double, double, double);
144 static int php_http_curl_raw_callback(CURL
*, curl_infotype
, char *, size_t, void *);
145 static int php_http_curl_dummy_callback(char *data
, size_t n
, size_t l
, void *s
) { return n
*l
; }
146 static curlioerr
php_http_curl_ioctl_callback(CURL
*, curliocmd
, void *);
148 PHP_HTTP_API CURL
* php_http_curl_init(CURL
*ch
, php_http_request_t
*request TSRMLS_DC
)
150 if (ch
|| (SUCCESS
== php_http_persistent_handle_acquire(ZEND_STRL("http_request"), &ch TSRMLS_CC
))) {
152 curl_easy_setopt(ch
, CURLOPT_NOSIGNAL
, 1L);
154 curl_easy_setopt(ch
, CURLOPT_HEADER
, 0L);
155 curl_easy_setopt(ch
, CURLOPT_FILETIME
, 1L);
156 curl_easy_setopt(ch
, CURLOPT_AUTOREFERER
, 1L);
157 curl_easy_setopt(ch
, CURLOPT_VERBOSE
, 1L);
158 curl_easy_setopt(ch
, CURLOPT_HEADERFUNCTION
, NULL
);
159 curl_easy_setopt(ch
, CURLOPT_DEBUGFUNCTION
, php_http_curl_raw_callback
);
160 curl_easy_setopt(ch
, CURLOPT_READFUNCTION
, php_http_curl_read_callback
);
161 curl_easy_setopt(ch
, CURLOPT_IOCTLFUNCTION
, php_http_curl_ioctl_callback
);
162 curl_easy_setopt(ch
, CURLOPT_WRITEFUNCTION
, php_http_curl_dummy_callback
);
166 curl_easy_setopt(ch
, CURLOPT_DEBUGDATA
, request
);
168 /* attach curl handle */
170 /* set defaults (also in php_http_request_reset()) */
171 php_http_request_defaults(request
);
177 PHP_HTTP_API CURL
*php_http_curl_copy(CURL
*ch TSRMLS_DC
)
181 if (SUCCESS
== php_http_persistent_handle_accrete(ZEND_STRL("http_request"), ch
, © TSRMLS_CC
)) {
186 PHP_HTTP_API
void php_http_curl_free(CURL
**ch TSRMLS_DC
)
189 curl_easy_setopt(*ch
, CURLOPT_NOPROGRESS
, 1L);
190 curl_easy_setopt(*ch
, CURLOPT_PROGRESSFUNCTION
, NULL
);
191 curl_easy_setopt(*ch
, CURLOPT_VERBOSE
, 0L);
192 curl_easy_setopt(*ch
, CURLOPT_DEBUGFUNCTION
, NULL
);
194 php_http_persistent_handle_release(ZEND_STRL("http_request"), ch TSRMLS_CC
);
198 PHP_HTTP_API php_http_request_t
*php_http_request_init(php_http_request_t
*request
, CURL
*ch
, php_http_request_method_t meth
, const char *url TSRMLS_DC
)
200 php_http_request_t
*r
;
205 r
= emalloc(sizeof(php_http_request_t
));
207 memset(r
, 0, sizeof(php_http_request_t
));
210 r
->url
= (url
) ? php_http_url_absolute(url
, 0) : NULL
;
211 r
->meth
= (meth
> 0) ? meth
: PHP_HTTP_GET
;
213 r
->parser
.ctx
= php_http_message_parser_init(NULL TSRMLS_CC
);
214 r
->parser
.msg
= php_http_message_init(NULL
, 0 TSRMLS_CC
);
215 r
->parser
.buf
= php_http_buffer_init(NULL
);
217 php_http_buffer_init(&r
->_cache
.cookies
);
218 zend_hash_init(&r
->_cache
.options
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
220 TSRMLS_SET_CTX(r
->ts
);
225 PHP_HTTP_API
void php_http_request_dtor(php_http_request_t
*request
)
227 TSRMLS_FETCH_FROM_CTX(request
->ts
);
229 php_http_request_reset(request
);
230 php_http_curl_free(&request
->ch
);
231 php_http_message_body_free(&request
->body
);
232 php_http_message_parser_free(&request
->parser
.ctx
);
233 php_http_message_free(&request
->parser
.msg
);
234 php_http_buffer_free(&request
->parser
.buf
);
236 php_http_buffer_dtor(&request
->_cache
.cookies
);
237 zend_hash_destroy(&request
->_cache
.options
);
238 if (request
->_cache
.headers
) {
239 curl_slist_free_all(request
->_cache
.headers
);
240 request
->_cache
.headers
= NULL
;
242 if (request
->_progress
.callback
) {
243 zval_ptr_dtor(&request
->_progress
.callback
);
244 request
->_progress
.callback
= NULL
;
248 PHP_HTTP_API
void php_http_request_free(php_http_request_t
**request
)
251 TSRMLS_FETCH_FROM_CTX((*request
)->ts
);
252 php_http_request_dtor(*request
);
258 PHP_HTTP_API
void php_http_request_reset(php_http_request_t
*request
)
260 TSRMLS_FETCH_FROM_CTX(request
->ts
);
261 STR_SET(request
->url
, NULL
);
262 php_http_message_body_dtor(request
->body
);
263 php_http_request_defaults(request
);
266 php_http_request_storage_t
*st
= php_http_request_storage_get(request
->ch
);
273 if (st
->cookiestore
) {
274 pefree(st
->cookiestore
, 1);
275 st
->cookiestore
= NULL
;
277 st
->errorbuffer
[0] = '\0';
282 PHP_HTTP_API STATUS
php_http_request_enable_cookies(php_http_request_t
*request
)
285 TSRMLS_FETCH_FROM_CTX(request
->ts
);
287 PHP_HTTP_CHECK_CURL_INIT(request
->ch
, php_http_curl_init(request
->ch
, request TSRMLS_CC
), initialized
= 0);
288 if (initialized
&& (php_http_request_cookies_enabled(request
) || (CURLE_OK
== curl_easy_setopt(request
->ch
, CURLOPT_COOKIEFILE
, "")))) {
291 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST
, "Could not enable cookies for this session");
295 PHP_HTTP_API STATUS
php_http_request_reset_cookies(php_http_request_t
*request
, int session_only
)
298 TSRMLS_FETCH_FROM_CTX(request
->ts
);
300 PHP_HTTP_CHECK_CURL_INIT(request
->ch
, php_http_curl_init(request
->ch
, request TSRMLS_CC
), initialized
= 0);
302 if (!php_http_request_cookies_enabled(request
)) {
303 if (SUCCESS
!= php_http_request_enable_cookies(request
)) {
308 if (CURLE_OK
== curl_easy_setopt(request
->ch
, CURLOPT_COOKIELIST
, "SESS")) {
312 if (CURLE_OK
== curl_easy_setopt(request
->ch
, CURLOPT_COOKIELIST
, "ALL")) {
320 PHP_HTTP_API STATUS
php_http_request_flush_cookies(php_http_request_t
*request
)
323 TSRMLS_FETCH_FROM_CTX(request
->ts
);
325 PHP_HTTP_CHECK_CURL_INIT(request
->ch
, php_http_curl_init(request
->ch
, request TSRMLS_CC
), initialized
= 0);
327 if (!php_http_request_cookies_enabled(request
)) {
330 if (CURLE_OK
== curl_easy_setopt(request
->ch
, CURLOPT_COOKIELIST
, "FLUSH")) {
337 PHP_HTTP_API
void php_http_request_defaults(php_http_request_t
*request
)
340 PHP_HTTP_CURL_OPT(CURLOPT_NOPROGRESS
, 0L);
341 PHP_HTTP_CURL_OPT(CURLOPT_PROGRESSDATA
, request
);
342 PHP_HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION
, php_http_curl_progress_callback
);
343 PHP_HTTP_CURL_OPT(CURLOPT_URL
, NULL
);
344 #if PHP_HTTP_CURL_VERSION(7,19,4)
345 PHP_HTTP_CURL_OPT(CURLOPT_NOPROXY
, NULL
);
347 PHP_HTTP_CURL_OPT(CURLOPT_PROXY
, NULL
);
348 PHP_HTTP_CURL_OPT(CURLOPT_PROXYPORT
, 0L);
349 PHP_HTTP_CURL_OPT(CURLOPT_PROXYTYPE
, 0L);
350 /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
351 #if PHP_HTTP_CURL_VERSION(7,19,1)
352 PHP_HTTP_CURL_OPT(CURLOPT_PROXYUSERNAME
, NULL
);
353 PHP_HTTP_CURL_OPT(CURLOPT_PROXYPASSWORD
, NULL
);
355 PHP_HTTP_CURL_OPT(CURLOPT_PROXYAUTH
, 0L);
356 PHP_HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL
, 0L);
357 PHP_HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT
, 60L);
358 PHP_HTTP_CURL_OPT(CURLOPT_IPRESOLVE
, 0);
359 PHP_HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT
, 0L);
360 PHP_HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME
, 0L);
362 PHP_HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) 0);
363 PHP_HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) 0);
366 PHP_HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, 5L); */
367 PHP_HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT
, 0L);
368 PHP_HTTP_CURL_OPT(CURLOPT_FORBID_REUSE
, 0L);
369 PHP_HTTP_CURL_OPT(CURLOPT_INTERFACE
, NULL
);
370 PHP_HTTP_CURL_OPT(CURLOPT_PORT
, 0L);
371 #if PHP_HTTP_CURL_VERSION(7,19,0)
372 PHP_HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE
, 0L);
374 PHP_HTTP_CURL_OPT(CURLOPT_LOCALPORT
, 0L);
375 PHP_HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE
, 0L);
376 /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */
377 #if PHP_HTTP_CURL_VERSION(7,19,1)
378 PHP_HTTP_CURL_OPT(CURLOPT_USERNAME
, NULL
);
379 PHP_HTTP_CURL_OPT(CURLOPT_PASSWORD
, NULL
);
381 PHP_HTTP_CURL_OPT(CURLOPT_HTTPAUTH
, 0L);
382 PHP_HTTP_CURL_OPT(CURLOPT_ENCODING
, NULL
);
383 /* we do this ourself anyway */
384 PHP_HTTP_CURL_OPT(CURLOPT_HTTP_CONTENT_DECODING
, 0L);
385 PHP_HTTP_CURL_OPT(CURLOPT_HTTP_TRANSFER_DECODING
, 0L);
386 PHP_HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION
, 0L);
387 #if PHP_HTTP_CURL_VERSION(7,19,1)
388 PHP_HTTP_CURL_OPT(CURLOPT_POSTREDIR
, 0L);
390 PHP_HTTP_CURL_OPT(CURLOPT_POST301
, 0L);
392 PHP_HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH
, 0L);
393 PHP_HTTP_CURL_OPT(CURLOPT_REFERER
, NULL
);
394 PHP_HTTP_CURL_OPT(CURLOPT_USERAGENT
, "PECL::HTTP/" PHP_HTTP_EXT_VERSION
" (PHP/" PHP_VERSION
")");
395 PHP_HTTP_CURL_OPT(CURLOPT_HTTPHEADER
, NULL
);
396 PHP_HTTP_CURL_OPT(CURLOPT_COOKIE
, NULL
);
397 PHP_HTTP_CURL_OPT(CURLOPT_COOKIESESSION
, 0L);
398 /* these options would enable curl's cookie engine by default which we don't want
399 PHP_HTTP_CURL_OPT(CURLOPT_COOKIEFILE, NULL);
400 PHP_HTTP_CURL_OPT(CURLOPT_COOKIEJAR, NULL); */
401 PHP_HTTP_CURL_OPT(CURLOPT_COOKIELIST
, NULL
);
402 PHP_HTTP_CURL_OPT(CURLOPT_RANGE
, NULL
);
403 PHP_HTTP_CURL_OPT(CURLOPT_RESUME_FROM
, 0L);
404 PHP_HTTP_CURL_OPT(CURLOPT_MAXFILESIZE
, 0L);
405 PHP_HTTP_CURL_OPT(CURLOPT_TIMECONDITION
, 0L);
406 PHP_HTTP_CURL_OPT(CURLOPT_TIMEVALUE
, 0L);
407 PHP_HTTP_CURL_OPT(CURLOPT_TIMEOUT
, 0L);
408 PHP_HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT
, 3);
409 PHP_HTTP_CURL_OPT(CURLOPT_SSLCERT
, NULL
);
410 PHP_HTTP_CURL_OPT(CURLOPT_SSLCERTTYPE
, NULL
);
411 PHP_HTTP_CURL_OPT(CURLOPT_SSLCERTPASSWD
, NULL
);
412 PHP_HTTP_CURL_OPT(CURLOPT_SSLKEY
, NULL
);
413 PHP_HTTP_CURL_OPT(CURLOPT_SSLKEYTYPE
, NULL
);
414 PHP_HTTP_CURL_OPT(CURLOPT_SSLKEYPASSWD
, NULL
);
415 PHP_HTTP_CURL_OPT(CURLOPT_SSLENGINE
, NULL
);
416 PHP_HTTP_CURL_OPT(CURLOPT_SSLVERSION
, 0L);
417 PHP_HTTP_CURL_OPT(CURLOPT_SSL_VERIFYPEER
, 0L);
418 PHP_HTTP_CURL_OPT(CURLOPT_SSL_VERIFYHOST
, 0L);
419 PHP_HTTP_CURL_OPT(CURLOPT_SSL_CIPHER_LIST
, NULL
);
420 #if PHP_HTTP_CURL_VERSION(7,19,0)
421 PHP_HTTP_CURL_OPT(CURLOPT_ISSUERCERT
, NULL
);
422 #if defined(PHP_HTTP_HAVE_OPENSSL)
423 PHP_HTTP_CURL_OPT(CURLOPT_CRLFILE
, NULL
);
426 #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
427 PHP_HTTP_CURL_OPT(CURLOPT_CERTINFO
, NULL
);
429 #ifdef PHP_HTTP_CURL_CAINFO
430 PHP_HTTP_CURL_OPT(CURLOPT_CAINFO
, PHP_HTTP_CURL_CAINFO
);
432 PHP_HTTP_CURL_OPT(CURLOPT_CAINFO
, NULL
);
434 PHP_HTTP_CURL_OPT(CURLOPT_CAPATH
, NULL
);
435 PHP_HTTP_CURL_OPT(CURLOPT_RANDOM_FILE
, NULL
);
436 PHP_HTTP_CURL_OPT(CURLOPT_EGDSOCKET
, NULL
);
437 PHP_HTTP_CURL_OPT(CURLOPT_POSTFIELDS
, NULL
);
438 PHP_HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE
, 0L);
439 PHP_HTTP_CURL_OPT(CURLOPT_HTTPPOST
, NULL
);
440 PHP_HTTP_CURL_OPT(CURLOPT_IOCTLDATA
, NULL
);
441 PHP_HTTP_CURL_OPT(CURLOPT_READDATA
, NULL
);
442 PHP_HTTP_CURL_OPT(CURLOPT_INFILESIZE
, 0L);
443 PHP_HTTP_CURL_OPT(CURLOPT_HTTP_VERSION
, CURL_HTTP_VERSION_NONE
);
444 PHP_HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST
, NULL
);
445 PHP_HTTP_CURL_OPT(CURLOPT_NOBODY
, 0L);
446 PHP_HTTP_CURL_OPT(CURLOPT_POST
, 0L);
447 PHP_HTTP_CURL_OPT(CURLOPT_UPLOAD
, 0L);
448 PHP_HTTP_CURL_OPT(CURLOPT_HTTPGET
, 1L);
452 PHP_HTTP_API
void php_http_request_set_progress_callback(php_http_request_t
*request
, zval
*cb
)
454 if (request
->_progress
.callback
) {
455 zval_ptr_dtor(&request
->_progress
.callback
);
457 if ((request
->_progress
.callback
= cb
)) {
462 PHP_HTTP_API STATUS
php_http_request_prepare(php_http_request_t
*request
, HashTable
*options
)
465 zend_bool range_req
= 0;
466 php_http_request_storage_t
*storage
;
468 TSRMLS_FETCH_FROM_CTX(request
->ts
);
470 PHP_HTTP_CHECK_CURL_INIT(request
->ch
, php_http_curl_init(NULL
, request TSRMLS_CC
), return FAILURE
);
472 if (!(storage
= php_http_request_storage_get(request
->ch
))) {
475 storage
->errorbuffer
[0] = '\0';
478 pefree(storage
->url
, 1);
480 storage
->url
= pestrdup(request
->url
, 1);
481 PHP_HTTP_CURL_OPT(CURLOPT_URL
, storage
->url
);
483 /* progress callback */
484 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("onprogress"), -1))) {
485 php_http_request_set_progress_callback(request
, zoption
);
489 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("proxyhost"), IS_STRING
))) {
490 PHP_HTTP_CURL_OPT(CURLOPT_PROXY
, Z_STRVAL_P(zoption
));
492 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("proxytype"), IS_LONG
))) {
493 PHP_HTTP_CURL_OPT(CURLOPT_PROXYTYPE
, Z_LVAL_P(zoption
));
496 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("proxyport"), IS_LONG
))) {
497 PHP_HTTP_CURL_OPT(CURLOPT_PROXYPORT
, Z_LVAL_P(zoption
));
500 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("proxyauth"), IS_STRING
)) && Z_STRLEN_P(zoption
)) {
501 PHP_HTTP_CURL_OPT(CURLOPT_PROXYUSERPWD
, Z_STRVAL_P(zoption
));
504 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("proxyauthtype"), IS_LONG
))) {
505 PHP_HTTP_CURL_OPT(CURLOPT_PROXYAUTH
, Z_LVAL_P(zoption
));
508 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("proxytunnel"), IS_BOOL
)) && Z_BVAL_P(zoption
)) {
509 PHP_HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL
, 1L);
512 #if PHP_HTTP_CURL_VERSION(7,19,4)
513 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("noproxy"), IS_STRING
))) {
514 PHP_HTTP_CURL_OPT(CURLOPT_NOPROXY
, Z_STRVAL_P(zoption
));
519 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("dns_cache_timeout"), IS_LONG
))) {
520 PHP_HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT
, Z_LVAL_P(zoption
));
522 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("ipresolve"), IS_LONG
)) && Z_LVAL_P(zoption
)) {
523 PHP_HTTP_CURL_OPT(CURLOPT_IPRESOLVE
, Z_LVAL_P(zoption
));
527 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("low_speed_limit"), IS_LONG
))) {
528 PHP_HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT
, Z_LVAL_P(zoption
));
530 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("low_speed_time"), IS_LONG
))) {
531 PHP_HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME
, Z_LVAL_P(zoption
));
534 if ((zoption = php_http_request_option(request, options, ZEND_STRS("max_send_speed"), IS_LONG))) {
535 PHP_HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
537 if ((zoption = php_http_request_option(request, options, ZEND_STRS("max_recv_speed"), IS_LONG))) {
538 PHP_HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption));
542 if ((zoption = php_http_request_option(request, options, ZEND_STRS("maxconnects"), IS_LONG))) {
543 PHP_HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, Z_LVAL_P(zoption));
545 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("fresh_connect"), IS_BOOL
)) && Z_BVAL_P(zoption
)) {
546 PHP_HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT
, 1L);
548 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("forbid_reuse"), IS_BOOL
)) && Z_BVAL_P(zoption
)) {
549 PHP_HTTP_CURL_OPT(CURLOPT_FORBID_REUSE
, 1L);
552 /* outgoing interface */
553 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("interface"), IS_STRING
))) {
554 PHP_HTTP_CURL_OPT(CURLOPT_INTERFACE
, Z_STRVAL_P(zoption
));
556 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("portrange"), IS_ARRAY
))) {
559 zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption
));
560 if (SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_P(zoption
), (void *) &prs
)) {
561 zend_hash_move_forward(Z_ARRVAL_P(zoption
));
562 if (SUCCESS
== zend_hash_get_current_data(Z_ARRVAL_P(zoption
), (void *) &pre
)) {
563 zval
*prs_cpy
= php_http_zsep(IS_LONG
, *prs
);
564 zval
*pre_cpy
= php_http_zsep(IS_LONG
, *pre
);
566 if (Z_LVAL_P(prs_cpy
) && Z_LVAL_P(pre_cpy
)) {
567 PHP_HTTP_CURL_OPT(CURLOPT_LOCALPORT
, MIN(Z_LVAL_P(prs_cpy
), Z_LVAL_P(pre_cpy
)));
568 PHP_HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE
, labs(Z_LVAL_P(prs_cpy
)-Z_LVAL_P(pre_cpy
))+1L);
570 zval_ptr_dtor(&prs_cpy
);
571 zval_ptr_dtor(&pre_cpy
);
578 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("port"), IS_LONG
))) {
579 PHP_HTTP_CURL_OPT(CURLOPT_PORT
, Z_LVAL_P(zoption
));
582 /* RFC4007 zone_id */
583 #if PHP_HTTP_CURL_VERSION(7,19,0)
584 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("address_scope"), IS_LONG
))) {
585 PHP_HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE
, Z_LVAL_P(zoption
));
590 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("httpauth"), IS_STRING
)) && Z_STRLEN_P(zoption
)) {
591 PHP_HTTP_CURL_OPT(CURLOPT_USERPWD
, Z_STRVAL_P(zoption
));
593 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("httpauthtype"), IS_LONG
))) {
594 PHP_HTTP_CURL_OPT(CURLOPT_HTTPAUTH
, Z_LVAL_P(zoption
));
597 /* redirects, defaults to 0 */
598 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("redirect"), IS_LONG
))) {
599 PHP_HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION
, Z_LVAL_P(zoption
) ? 1L : 0L);
600 PHP_HTTP_CURL_OPT(CURLOPT_MAXREDIRS
, request
->_cache
.redirects
= Z_LVAL_P(zoption
));
601 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("unrestrictedauth"), IS_BOOL
))) {
602 PHP_HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH
, Z_LVAL_P(zoption
));
604 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("postredir"), IS_BOOL
))) {
605 #if PHP_HTTP_CURL_VERSION(7,19,1)
606 PHP_HTTP_CURL_OPT(CURLOPT_POSTREDIR
, Z_BVAL_P(zoption
) ? 1L : 0L);
608 PHP_HTTP_CURL_OPT(CURLOPT_POST301
, Z_BVAL_P(zoption
) ? 1L : 0L);
612 request
->_cache
.redirects
= 0;
615 /* retries, defaults to 0 */
616 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("retrycount"), IS_LONG
))) {
617 request
->_retry
.count
= Z_LVAL_P(zoption
);
618 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("retrydelay"), IS_DOUBLE
))) {
619 request
->_retry
.delay
= Z_DVAL_P(zoption
);
621 request
->_retry
.delay
= 0;
624 request
->_retry
.count
= 0;
628 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("referer"), IS_STRING
)) && Z_STRLEN_P(zoption
)) {
629 PHP_HTTP_CURL_OPT(CURLOPT_REFERER
, Z_STRVAL_P(zoption
));
632 /* useragent, default "PECL::HTTP/version (PHP/version)" */
633 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("useragent"), IS_STRING
))) {
634 /* allow to send no user agent, not even default one */
635 if (Z_STRLEN_P(zoption
)) {
636 PHP_HTTP_CURL_OPT(CURLOPT_USERAGENT
, Z_STRVAL_P(zoption
));
638 PHP_HTTP_CURL_OPT(CURLOPT_USERAGENT
, NULL
);
643 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("resume"), IS_LONG
)) && (Z_LVAL_P(zoption
) > 0)) {
645 PHP_HTTP_CURL_OPT(CURLOPT_RESUME_FROM
, Z_LVAL_P(zoption
));
647 /* or range of kind array(array(0,499), array(100,1499)) */
648 else if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("range"), IS_ARRAY
)) && zend_hash_num_elements(Z_ARRVAL_P(zoption
))) {
649 HashPosition pos1
, pos2
;
650 zval
**rr
, **rb
, **re
;
651 php_http_buffer_t rs
;
653 php_http_buffer_init(&rs
);
654 FOREACH_VAL(pos1
, zoption
, rr
) {
655 if (Z_TYPE_PP(rr
) == IS_ARRAY
) {
656 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(rr
), &pos2
);
657 if (SUCCESS
== zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr
), (void *) &rb
, &pos2
)) {
658 zend_hash_move_forward_ex(Z_ARRVAL_PP(rr
), &pos2
);
659 if (SUCCESS
== zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr
), (void *) &re
, &pos2
)) {
660 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))) &&
661 ((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)))) {
662 zval
*rbl
= php_http_zsep(IS_LONG
, *rb
);
663 zval
*rel
= php_http_zsep(IS_LONG
, *re
);
665 if ((Z_LVAL_P(rbl
) >= 0) && (Z_LVAL_P(rel
) >= 0)) {
666 php_http_buffer_appendf(&rs
, "%ld-%ld,", Z_LVAL_P(rbl
), Z_LVAL_P(rel
));
676 if (PHP_HTTP_BUFFER_LEN(&rs
)) {
679 /* ditch last comma */
680 PHP_HTTP_BUFFER_VAL(&rs
)[PHP_HTTP_BUFFER_LEN(&rs
)-- -1] = '\0';
682 MAKE_STD_ZVAL(cached_range
);
683 ZVAL_STRINGL(cached_range
, PHP_HTTP_BUFFER_VAL(&rs
), PHP_HTTP_BUFFER_LEN(&rs
), 0);
684 PHP_HTTP_CURL_OPT(CURLOPT_RANGE
, Z_STRVAL_P(php_http_request_option_cache(request
, ZEND_STRS("range"), 0, cached_range
)));
685 zval_ptr_dtor(&cached_range
);
689 /* additional headers, array('name' => 'value') */
690 if (request
->_cache
.headers
) {
691 curl_slist_free_all(request
->_cache
.headers
);
692 request
->_cache
.headers
= NULL
;
694 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("headers"), IS_ARRAY
))) {
695 php_http_array_hashkey_t header_key
= php_http_array_hashkey_init(0);
698 php_http_buffer_t header
;
700 php_http_buffer_init(&header
);
701 FOREACH_KEYVAL(pos
, zoption
, header_key
, header_val
) {
702 if (header_key
.type
== HASH_KEY_IS_STRING
) {
703 zval
*header_cpy
= php_http_zsep(IS_STRING
, *header_val
);
705 if (!strcasecmp(header_key
.str
, "range")) {
709 php_http_buffer_appendf(&header
, "%s: %s", header_key
.str
, Z_STRVAL_P(header_cpy
));
710 php_http_buffer_fix(&header
);
711 request
->_cache
.headers
= curl_slist_append(request
->_cache
.headers
, PHP_HTTP_BUFFER_VAL(&header
));
712 php_http_buffer_reset(&header
);
714 zval_ptr_dtor(&header_cpy
);
717 php_http_buffer_dtor(&header
);
720 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("etag"), IS_STRING
)) && Z_STRLEN_P(zoption
)) {
721 zend_bool is_quoted
= !((Z_STRVAL_P(zoption
)[0] != '"') || (Z_STRVAL_P(zoption
)[Z_STRLEN_P(zoption
)-1] != '"'));
722 php_http_buffer_t header
;
724 php_http_buffer_init(&header
);
725 php_http_buffer_appendf(&header
, is_quoted
?"%s: %s":"%s: \"%s\"", range_req
?"If-Match":"If-None-Match", Z_STRVAL_P(zoption
));
726 php_http_buffer_fix(&header
);
727 request
->_cache
.headers
= curl_slist_append(request
->_cache
.headers
, PHP_HTTP_BUFFER_VAL(&header
));
728 php_http_buffer_dtor(&header
);
731 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("compress"), IS_BOOL
)) && Z_LVAL_P(zoption
)) {
732 request
->_cache
.headers
= curl_slist_append(request
->_cache
.headers
, "Accept-Encoding: gzip;q=1.0,deflate;q=0.5");
734 PHP_HTTP_CURL_OPT(CURLOPT_HTTPHEADER
, request
->_cache
.headers
);
737 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("lastmodified"), IS_LONG
))) {
738 if (Z_LVAL_P(zoption
)) {
739 if (Z_LVAL_P(zoption
) > 0) {
740 PHP_HTTP_CURL_OPT(CURLOPT_TIMEVALUE
, Z_LVAL_P(zoption
));
742 PHP_HTTP_CURL_OPT(CURLOPT_TIMEVALUE
, (long) PHP_HTTP_G
->env
.request
.time
+ Z_LVAL_P(zoption
));
744 PHP_HTTP_CURL_OPT(CURLOPT_TIMECONDITION
, (long) (range_req
? CURL_TIMECOND_IFUNMODSINCE
: CURL_TIMECOND_IFMODSINCE
));
746 PHP_HTTP_CURL_OPT(CURLOPT_TIMECONDITION
, CURL_TIMECOND_NONE
);
750 /* cookies, array('name' => 'value') */
751 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("cookies"), IS_ARRAY
))) {
752 php_http_buffer_dtor(&request
->_cache
.cookies
);
753 if (zend_hash_num_elements(Z_ARRVAL_P(zoption
))) {
754 zval
*urlenc_cookies
= NULL
;
755 /* check whether cookies should not be urlencoded; default is to urlencode them */
756 if ((!(urlenc_cookies
= php_http_request_option(request
, options
, ZEND_STRS("encodecookies"), IS_BOOL
))) || Z_BVAL_P(urlenc_cookies
)) {
757 if (SUCCESS
== php_http_url_encode_hash_recursive(HASH_OF(zoption
), &request
->_cache
.cookies
, "; ", lenof("; "), NULL
, 0 TSRMLS_CC
)) {
758 php_http_buffer_fix(&request
->_cache
.cookies
);
759 PHP_HTTP_CURL_OPT(CURLOPT_COOKIE
, request
->_cache
.cookies
.data
);
763 php_http_array_hashkey_t cookie_key
= php_http_array_hashkey_init(0);
766 FOREACH_KEYVAL(pos
, zoption
, cookie_key
, cookie_val
) {
767 if (cookie_key
.type
== HASH_KEY_IS_STRING
) {
768 zval
*val
= php_http_zsep(IS_STRING
, *cookie_val
);
769 php_http_buffer_appendf(&request
->_cache
.cookies
, "%s=%s; ", cookie_key
.str
, Z_STRVAL_P(val
));
774 php_http_buffer_fix(&request
->_cache
.cookies
);
775 if (PHP_HTTP_BUFFER_LEN(&request
->_cache
.cookies
)) {
776 PHP_HTTP_CURL_OPT(CURLOPT_COOKIE
, PHP_HTTP_BUFFER_VAL(&request
->_cache
.cookies
));
782 /* don't load session cookies from cookiestore */
783 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("cookiesession"), IS_BOOL
)) && Z_BVAL_P(zoption
)) {
784 PHP_HTTP_CURL_OPT(CURLOPT_COOKIESESSION
, 1L);
787 /* cookiestore, read initial cookies from that file and store cookies back into that file */
788 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("cookiestore"), IS_STRING
))) {
789 if (Z_STRLEN_P(zoption
)) {
790 if (SUCCESS
!= php_check_open_basedir(Z_STRVAL_P(zoption
) TSRMLS_CC
)) {
794 if (storage
->cookiestore
) {
795 pefree(storage
->cookiestore
, 1);
797 storage
->cookiestore
= pestrndup(Z_STRVAL_P(zoption
), Z_STRLEN_P(zoption
), 1);
798 PHP_HTTP_CURL_OPT(CURLOPT_COOKIEFILE
, storage
->cookiestore
);
799 PHP_HTTP_CURL_OPT(CURLOPT_COOKIEJAR
, storage
->cookiestore
);
803 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("maxfilesize"), IS_LONG
))) {
804 PHP_HTTP_CURL_OPT(CURLOPT_MAXFILESIZE
, Z_LVAL_P(zoption
));
808 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("protocol"), IS_LONG
))) {
809 PHP_HTTP_CURL_OPT(CURLOPT_HTTP_VERSION
, Z_LVAL_P(zoption
));
812 /* timeout, defaults to 0 */
813 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("timeout"), IS_DOUBLE
))) {
814 PHP_HTTP_CURL_OPT(CURLOPT_TIMEOUT_MS
, (long)(Z_DVAL_P(zoption
)*1000));
816 /* connecttimeout, defaults to 0 */
817 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("connecttimeout"), IS_DOUBLE
))) {
818 PHP_HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT_MS
, (long)(Z_DVAL_P(zoption
)*1000));
822 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("ssl"), IS_ARRAY
))) {
823 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
827 FOREACH_KEYVAL(pos
, zoption
, key
, param
) {
828 if (key
.type
== HASH_KEY_IS_STRING
) {
829 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLCERT
, 0, 1);
830 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTTYPE
, 0, 0);
831 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTPASSWD
, 0, 0);
833 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLKEY
, 0, 0);
834 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYTYPE
, 0, 0);
835 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYPASSWD
, 0, 0);
837 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLENGINE
, 0, 0);
838 PHP_HTTP_CURL_OPT_LONG(CURLOPT_SSLVERSION
, 0);
840 PHP_HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYPEER
, 1);
841 PHP_HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYHOST
, 1);
842 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSL_CIPHER_LIST
, 1, 0);
844 PHP_HTTP_CURL_OPT_STRING(CURLOPT_CAINFO
, -3, 1);
845 PHP_HTTP_CURL_OPT_STRING(CURLOPT_CAPATH
, -3, 1);
846 PHP_HTTP_CURL_OPT_STRING(CURLOPT_RANDOM_FILE
, -3, 1);
847 PHP_HTTP_CURL_OPT_STRING(CURLOPT_EGDSOCKET
, -3, 1);
848 #if PHP_HTTP_CURL_VERSION(7,19,0)
849 PHP_HTTP_CURL_OPT_STRING(CURLOPT_ISSUERCERT
, -3, 1);
850 #if defined(PHP_HTTP_HAVE_OPENSSL)
851 PHP_HTTP_CURL_OPT_STRING(CURLOPT_CRLFILE
, -3, 1);
854 #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
855 PHP_HTTP_CURL_OPT_LONG(CURLOPT_CERTINFO
, -3);
862 switch (request
->meth
) {
864 PHP_HTTP_CURL_OPT(CURLOPT_HTTPGET
, 1L);
868 PHP_HTTP_CURL_OPT(CURLOPT_NOBODY
, 1L);
872 PHP_HTTP_CURL_OPT(CURLOPT_POST
, 1L);
876 PHP_HTTP_CURL_OPT(CURLOPT_UPLOAD
, 1L);
880 const char *meth
= php_http_request_method_name(request
->meth
);
883 PHP_HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST
, meth
);
885 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST_METHOD
, "Unsupported request method: %d (%s)", request
->meth
, request
->url
);
892 /* attach request body */
893 if (request
->body
&& (request
->meth
!= PHP_HTTP_GET
) && (request
->meth
!= PHP_HTTP_HEAD
) && (request
->meth
!= PHP_HTTP_OPTIONS
)) {
894 if (1 || request
->meth
== PHP_HTTP_PUT
) {
895 /* PUT/UPLOAD _needs_ READDATA */
896 PHP_HTTP_CURL_OPT(CURLOPT_IOCTLDATA
, request
);
897 PHP_HTTP_CURL_OPT(CURLOPT_READDATA
, request
);
898 PHP_HTTP_CURL_OPT(CURLOPT_INFILESIZE
, php_http_message_body_size(request
->body
));
901 //PHP_HTTP_CURL_OPT(CURLOPT_POSTFIELDS, request->body->real->data);
902 PHP_HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE
, php_http_message_body_size(request
->body
));
909 PHP_HTTP_API
void php_http_request_exec(php_http_request_t
*request
)
913 TSRMLS_FETCH_FROM_CTX(request
->ts
);
916 if (CURLE_OK
!= (result
= curl_easy_perform(request
->ch
))) {
917 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST
, "%s; %s (%s)", curl_easy_strerror(result
), php_http_request_storage_get(request
->ch
)->errorbuffer
, request
->url
);
919 add_property_long(EG(exception
), "curlCode", result
);
922 if (request
->_retry
.count
> tries
++) {
924 case CURLE_COULDNT_RESOLVE_PROXY
:
925 case CURLE_COULDNT_RESOLVE_HOST
:
926 case CURLE_COULDNT_CONNECT
:
927 case CURLE_WRITE_ERROR
:
928 case CURLE_READ_ERROR
:
929 case CURLE_OPERATION_TIMEDOUT
:
930 case CURLE_SSL_CONNECT_ERROR
:
931 case CURLE_GOT_NOTHING
:
932 case CURLE_SSL_ENGINE_SETFAILED
:
933 case CURLE_SEND_ERROR
:
934 case CURLE_RECV_ERROR
:
935 case CURLE_SSL_ENGINE_INITFAILED
:
936 case CURLE_LOGIN_DENIED
:
937 if (request
->_retry
.delay
>= PHP_HTTP_DIFFSEC
) {
938 php_http_sleep(request
->_retry
.delay
);
948 static size_t php_http_curl_read_callback(void *data
, size_t len
, size_t n
, void *ctx
)
950 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
951 TSRMLS_FETCH_FROM_CTX(request
->ts
);
954 return php_stream_read(php_http_message_body_stream(request
->body
), data
, len
* n
);
959 static int php_http_curl_progress_callback(void *ctx
, double dltotal
, double dlnow
, double ultotal
, double ulnow
)
961 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
963 request
->_progress
.state
.dl
.total
= dltotal
;
964 request
->_progress
.state
.dl
.now
= dlnow
;
965 request
->_progress
.state
.ul
.total
= ultotal
;
966 request
->_progress
.state
.ul
.now
= ulnow
;
968 if (request
->_progress
.callback
) {
970 TSRMLS_FETCH_FROM_CTX(request
->ts
);
975 MAKE_STD_ZVAL(param
);
977 add_assoc_double(param
, "dltotal", request
->_progress
.state
.dl
.total
);
978 add_assoc_double(param
, "dlnow", request
->_progress
.state
.dl
.now
);
979 add_assoc_double(param
, "ultotal", request
->_progress
.state
.ul
.total
);
980 add_assoc_double(param
, "ulnow", request
->_progress
.state
.ul
.now
);
982 with_error_handling(EH_NORMAL
, NULL
) {
983 request
->_progress
.in_cb
= 1;
984 call_user_function(EG(function_table
), NULL
, request
->_progress
.callback
, &retval
, 1, ¶m TSRMLS_CC
);
985 request
->_progress
.in_cb
= 0;
986 } end_error_handling();
988 zval_ptr_dtor(¶m
);
995 static curlioerr
php_http_curl_ioctl_callback(CURL
*ch
, curliocmd cmd
, void *ctx
)
997 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
998 TSRMLS_FETCH_FROM_CTX(request
->ts
);
1000 if (cmd
!= CURLIOCMD_RESTARTREAD
) {
1001 return CURLIOE_UNKNOWNCMD
;
1004 if (request
->body
) {
1005 if (SUCCESS
== php_stream_rewind(php_http_message_body_stream(request
->body
))) {
1010 return CURLIOE_FAILRESTART
;
1013 static int php_http_curl_raw_callback(CURL
*ch
, curl_infotype type
, char *data
, size_t length
, void *ctx
)
1015 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
1019 case CURLINFO_HEADER_IN
:
1020 case CURLINFO_DATA_IN
:
1021 case CURLINFO_HEADER_OUT
:
1022 case CURLINFO_DATA_OUT
:
1023 php_http_buffer_append(request
->parser
.buf
, data
, length
);
1024 if (PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE
== php_http_message_parser_parse(request
->parser
.ctx
, request
->parser
.buf
, request
->_cache
.redirects
?PHP_HTTP_MESSAGE_PARSER_EMPTY_REDIRECTS
:0, &request
->parser
.msg
)) {
1035 const char _sym
[] = "><><><";
1037 for (fprintf(stderr
, "%c ", _sym
[type
-1]); length
--; data
++) {
1038 fprintf(stderr
, PHP_HTTP_IS_CTYPE(print
, *data
)?"%c":"\\x%02X", (int) *data
);
1039 if (*data
== '\n' && length
) {
1040 fprintf(stderr
, "\n%c ", _sym
[type
-1]);
1043 fprintf(stderr
, "\n");
1045 fprintf(stderr
, "# %s", data
);
1053 static inline zval
*php_http_request_option(php_http_request_t
*r
, HashTable
*options
, char *key
, size_t keylen
, int type
)
1055 TSRMLS_FETCH_FROM_CTX(r
->ts
);
1059 ulong h
= zend_hash_func(key
, keylen
);
1061 if (SUCCESS
== zend_hash_quick_find(options
, key
, keylen
, h
, (void *) &zoption
)) {
1062 zval
*option
, *cached
;
1064 option
= php_http_zsep(type
, *zoption
);
1065 cached
= php_http_request_option_cache(r
, key
, keylen
, h
, option
);
1067 zval_ptr_dtor(&option
);
1075 static inline zval
*php_http_request_option_cache(php_http_request_t
*r
, char *key
, size_t keylen
, ulong h
, zval
*opt
)
1077 TSRMLS_FETCH_FROM_CTX(r
->ts
);
1081 zend_hash_quick_update(&r
->_cache
.options
, key
, keylen
, h
, &opt
, sizeof(zval
*), NULL
);
1083 zend_hash_update(&r
->_cache
.options
, key
, keylen
, &opt
, sizeof(zval
*), NULL
);
1089 static inline int php_http_request_cookies_enabled(php_http_request_t
*request
) {
1090 php_http_request_storage_t
*st
;
1092 if (request
->ch
&& (st
= php_http_request_storage_get(request
->ch
)) && st
->cookiestore
) {
1093 /* cookies are enabled */
1101 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpRequest, method, 0, req_args)
1102 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpRequest, method, 0)
1103 #define PHP_HTTP_REQUEST_ME(method, visibility) PHP_ME(HttpRequest, method, PHP_HTTP_ARGS(HttpRequest, method), visibility)
1104 #define PHP_HTTP_REQUEST_ALIAS(method, func) PHP_HTTP_STATIC_ME_ALIAS(method, func, PHP_HTTP_ARGS(HttpRequest, method))
1105 #define PHP_HTTP_REQUEST_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpRequest_##al), PHP_HTTP_ARGS(HttpRequest, al), vis)
1107 PHP_HTTP_BEGIN_ARGS(__construct
, 0)
1108 PHP_HTTP_ARG_VAL(url
, 0)
1109 PHP_HTTP_ARG_VAL(method
, 0)
1110 PHP_HTTP_ARG_VAL(options
, 0)
1113 PHP_HTTP_BEGIN_ARGS(factory
, 0)
1114 PHP_HTTP_ARG_VAL(url
, 0)
1115 PHP_HTTP_ARG_VAL(method
, 0)
1116 PHP_HTTP_ARG_VAL(options
, 0)
1117 PHP_HTTP_ARG_VAL(class_name
, 0)
1120 PHP_HTTP_EMPTY_ARGS(getOptions
);
1121 PHP_HTTP_BEGIN_ARGS(setOptions
, 0)
1122 PHP_HTTP_ARG_VAL(options
, 0)
1125 PHP_HTTP_EMPTY_ARGS(getSslOptions
);
1126 PHP_HTTP_BEGIN_ARGS(setSslOptions
, 0)
1127 PHP_HTTP_ARG_VAL(ssl_options
, 0)
1130 PHP_HTTP_BEGIN_ARGS(addSslOptions
, 0)
1131 PHP_HTTP_ARG_VAL(ssl_optins
, 0)
1134 PHP_HTTP_EMPTY_ARGS(getHeaders
);
1135 PHP_HTTP_BEGIN_ARGS(setHeaders
, 0)
1136 PHP_HTTP_ARG_VAL(headers
, 0)
1139 PHP_HTTP_BEGIN_ARGS(addHeaders
, 1)
1140 PHP_HTTP_ARG_VAL(headers
, 0)
1143 PHP_HTTP_EMPTY_ARGS(getCookies
);
1144 PHP_HTTP_BEGIN_ARGS(setCookies
, 0)
1145 PHP_HTTP_ARG_VAL(cookies
, 0)
1148 PHP_HTTP_BEGIN_ARGS(addCookies
, 1)
1149 PHP_HTTP_ARG_VAL(cookies
, 0)
1152 PHP_HTTP_EMPTY_ARGS(enableCookies
);
1153 PHP_HTTP_BEGIN_ARGS(resetCookies
, 0)
1154 PHP_HTTP_ARG_VAL(session_only
, 0)
1156 PHP_HTTP_EMPTY_ARGS(flushCookies
);
1158 PHP_HTTP_EMPTY_ARGS(getUrl
);
1159 PHP_HTTP_BEGIN_ARGS(setUrl
, 1)
1160 PHP_HTTP_ARG_VAL(url
, 0)
1163 PHP_HTTP_EMPTY_ARGS(getMethod
);
1164 PHP_HTTP_BEGIN_ARGS(setMethod
, 1)
1165 PHP_HTTP_ARG_VAL(request_method
, 0)
1168 PHP_HTTP_EMPTY_ARGS(getContentType
);
1169 PHP_HTTP_BEGIN_ARGS(setContentType
, 1)
1170 PHP_HTTP_ARG_VAL(content_type
, 0)
1173 PHP_HTTP_EMPTY_ARGS(getQueryData
);
1174 PHP_HTTP_BEGIN_ARGS(setQueryData
, 0)
1175 PHP_HTTP_ARG_VAL(query_data
, 0)
1178 PHP_HTTP_BEGIN_ARGS(addQueryData
, 1)
1179 PHP_HTTP_ARG_VAL(query_data
, 0)
1183 PHP_HTTP_EMPTY_ARGS(getBody
);
1184 PHP_HTTP_BEGIN_ARGS(setBody
, 0)
1185 PHP_HTTP_ARG_OBJ(http
\\message
\\Body
, body
, 0)
1188 PHP_HTTP_BEGIN_ARGS(addBody
, 1)
1189 PHP_HTTP_ARG_OBJ(http
\\message
\\Body
, body
, 0)
1192 PHP_HTTP_BEGIN_ARGS(getResponseCookies
, 0)
1193 PHP_HTTP_ARG_VAL(flags
, 0)
1194 PHP_HTTP_ARG_VAL(allowed_extras
, 0)
1197 PHP_HTTP_EMPTY_ARGS(getResponseBody
);
1198 PHP_HTTP_EMPTY_ARGS(getResponseCode
);
1199 PHP_HTTP_EMPTY_ARGS(getResponseStatus
);
1200 PHP_HTTP_BEGIN_ARGS(getResponseInfo
, 0)
1201 PHP_HTTP_ARG_VAL(name
, 0)
1204 PHP_HTTP_BEGIN_ARGS(getResponseHeader
, 0)
1205 PHP_HTTP_ARG_VAL(header_name
, 0)
1208 PHP_HTTP_EMPTY_ARGS(getMessageClass
);
1209 PHP_HTTP_BEGIN_ARGS(setMessageClass
, 1)
1210 PHP_HTTP_ARG_VAL(message_class_name
, 0)
1213 PHP_HTTP_EMPTY_ARGS(getResponseMessage
);
1214 PHP_HTTP_EMPTY_ARGS(getRawResponseMessage
);
1215 PHP_HTTP_EMPTY_ARGS(getRequestMessage
);
1216 PHP_HTTP_EMPTY_ARGS(getRawRequestMessage
);
1217 PHP_HTTP_EMPTY_ARGS(getHistory
);
1218 PHP_HTTP_EMPTY_ARGS(clearHistory
);
1219 PHP_HTTP_EMPTY_ARGS(send
);
1221 PHP_HTTP_BEGIN_ARGS(get
, 1)
1222 PHP_HTTP_ARG_VAL(url
, 0)
1223 PHP_HTTP_ARG_VAL(options
, 0)
1224 PHP_HTTP_ARG_VAL(info
, 1)
1227 PHP_HTTP_BEGIN_ARGS(head
, 1)
1228 PHP_HTTP_ARG_VAL(url
, 0)
1229 PHP_HTTP_ARG_VAL(options
, 0)
1230 PHP_HTTP_ARG_VAL(info
, 1)
1233 PHP_HTTP_BEGIN_ARGS(postData
, 2)
1234 PHP_HTTP_ARG_VAL(url
, 0)
1235 PHP_HTTP_ARG_VAL(data
, 0)
1236 PHP_HTTP_ARG_VAL(options
, 0)
1237 PHP_HTTP_ARG_VAL(info
, 1)
1240 PHP_HTTP_BEGIN_ARGS(postFields
, 2)
1241 PHP_HTTP_ARG_VAL(url
, 0)
1242 PHP_HTTP_ARG_VAL(data
, 0)
1243 PHP_HTTP_ARG_VAL(options
, 0)
1244 PHP_HTTP_ARG_VAL(info
, 1)
1247 PHP_HTTP_BEGIN_ARGS(putData
, 2)
1248 PHP_HTTP_ARG_VAL(url
, 0)
1249 PHP_HTTP_ARG_VAL(data
, 0)
1250 PHP_HTTP_ARG_VAL(options
, 0)
1251 PHP_HTTP_ARG_VAL(info
, 1)
1254 PHP_HTTP_BEGIN_ARGS(putFile
, 2)
1255 PHP_HTTP_ARG_VAL(url
, 0)
1256 PHP_HTTP_ARG_VAL(file
, 0)
1257 PHP_HTTP_ARG_VAL(options
, 0)
1258 PHP_HTTP_ARG_VAL(info
, 1)
1261 PHP_HTTP_BEGIN_ARGS(putStream
, 2)
1262 PHP_HTTP_ARG_VAL(url
, 0)
1263 PHP_HTTP_ARG_VAL(stream
, 0)
1264 PHP_HTTP_ARG_VAL(options
, 0)
1265 PHP_HTTP_ARG_VAL(info
, 1)
1268 PHP_HTTP_BEGIN_ARGS(methodRegister
, 1)
1269 PHP_HTTP_ARG_VAL(method_name
, 0)
1272 PHP_HTTP_BEGIN_ARGS(methodUnregister
, 1)
1273 PHP_HTTP_ARG_VAL(method
, 0)
1276 PHP_HTTP_BEGIN_ARGS(methodName
, 1)
1277 PHP_HTTP_ARG_VAL(method_id
, 0)
1280 PHP_HTTP_BEGIN_ARGS(methodExists
, 1)
1281 PHP_HTTP_ARG_VAL(method
, 0)
1284 #ifdef HAVE_CURL_FORMGET
1285 PHP_HTTP_BEGIN_ARGS(encodeBody
, 2)
1286 PHP_HTTP_ARG_VAL(fields
, 0)
1287 PHP_HTTP_ARG_VAL(files
, 0)
1291 zend_class_entry
*php_http_request_class_entry
;
1292 zend_function_entry php_http_request_method_entry
[] = {
1293 PHP_HTTP_REQUEST_ME(__construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
1295 PHP_HTTP_REQUEST_ME(setOptions
, ZEND_ACC_PUBLIC
)
1296 PHP_HTTP_REQUEST_ME(getOptions
, ZEND_ACC_PUBLIC
)
1297 PHP_HTTP_REQUEST_ME(setSslOptions
, ZEND_ACC_PUBLIC
)
1298 PHP_HTTP_REQUEST_ME(getSslOptions
, ZEND_ACC_PUBLIC
)
1299 PHP_HTTP_REQUEST_ME(addSslOptions
, ZEND_ACC_PUBLIC
)
1301 PHP_HTTP_REQUEST_ME(addHeaders
, ZEND_ACC_PUBLIC
)
1302 PHP_HTTP_REQUEST_ME(getHeaders
, ZEND_ACC_PUBLIC
)
1303 PHP_HTTP_REQUEST_ME(setHeaders
, ZEND_ACC_PUBLIC
)
1305 PHP_HTTP_REQUEST_ME(addCookies
, ZEND_ACC_PUBLIC
)
1306 PHP_HTTP_REQUEST_ME(getCookies
, ZEND_ACC_PUBLIC
)
1307 PHP_HTTP_REQUEST_ME(setCookies
, ZEND_ACC_PUBLIC
)
1309 PHP_HTTP_REQUEST_ME(enableCookies
, ZEND_ACC_PUBLIC
)
1310 PHP_HTTP_REQUEST_ME(resetCookies
, ZEND_ACC_PUBLIC
)
1311 PHP_HTTP_REQUEST_ME(flushCookies
, ZEND_ACC_PUBLIC
)
1313 PHP_HTTP_REQUEST_ME(setMethod
, ZEND_ACC_PUBLIC
)
1314 PHP_HTTP_REQUEST_ME(getMethod
, ZEND_ACC_PUBLIC
)
1316 PHP_HTTP_REQUEST_ME(setUrl
, ZEND_ACC_PUBLIC
)
1317 PHP_HTTP_REQUEST_ME(getUrl
, ZEND_ACC_PUBLIC
)
1319 PHP_HTTP_REQUEST_ME(setContentType
, ZEND_ACC_PUBLIC
)
1320 PHP_HTTP_REQUEST_ME(getContentType
, ZEND_ACC_PUBLIC
)
1322 PHP_HTTP_REQUEST_ME(setQueryData
, ZEND_ACC_PUBLIC
)
1323 PHP_HTTP_REQUEST_ME(getQueryData
, ZEND_ACC_PUBLIC
)
1324 PHP_HTTP_REQUEST_ME(addQueryData
, ZEND_ACC_PUBLIC
)
1326 PHP_HTTP_REQUEST_ME(setBody
, ZEND_ACC_PUBLIC
)
1327 PHP_HTTP_REQUEST_ME(getBody
, ZEND_ACC_PUBLIC
)
1328 PHP_HTTP_REQUEST_ME(addBody
, ZEND_ACC_PUBLIC
)
1330 PHP_HTTP_REQUEST_ME(send
, ZEND_ACC_PUBLIC
)
1332 PHP_HTTP_REQUEST_ME(getResponseHeader
, ZEND_ACC_PUBLIC
)
1333 PHP_HTTP_REQUEST_ME(getResponseCookies
, ZEND_ACC_PUBLIC
)
1334 PHP_HTTP_REQUEST_ME(getResponseCode
, ZEND_ACC_PUBLIC
)
1335 PHP_HTTP_REQUEST_ME(getResponseStatus
, ZEND_ACC_PUBLIC
)
1336 PHP_HTTP_REQUEST_ME(getResponseBody
, ZEND_ACC_PUBLIC
)
1337 PHP_HTTP_REQUEST_ME(getResponseInfo
, ZEND_ACC_PUBLIC
)
1338 PHP_HTTP_REQUEST_ME(getResponseMessage
, ZEND_ACC_PUBLIC
)
1339 PHP_HTTP_REQUEST_ME(getRequestMessage
, ZEND_ACC_PUBLIC
)
1340 PHP_HTTP_REQUEST_ME(getHistory
, ZEND_ACC_PUBLIC
)
1341 PHP_HTTP_REQUEST_ME(clearHistory
, ZEND_ACC_PUBLIC
)
1343 PHP_HTTP_REQUEST_ME(getMessageClass
, ZEND_ACC_PUBLIC
)
1344 PHP_HTTP_REQUEST_ME(setMessageClass
, ZEND_ACC_PUBLIC
)
1346 EMPTY_FUNCTION_ENTRY
1348 static zend_object_handlers php_http_request_object_handlers
;
1350 zend_object_value
php_http_request_object_new(zend_class_entry
*ce TSRMLS_DC
)
1352 return php_http_request_object_new_ex(ce
, NULL
, NULL
);
1355 zend_object_value
php_http_request_object_new_ex(zend_class_entry
*ce
, CURL
*ch
, php_http_request_object_t
**ptr TSRMLS_DC
)
1357 zend_object_value ov
;
1358 php_http_request_object_t
*o
;
1360 o
= ecalloc(1, sizeof(php_http_request_object_t
));
1361 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
1362 object_properties_init((zend_object
*) o
, ce
);
1364 o
->request
= php_http_request_init(NULL
, ch
, 0, NULL TSRMLS_CC
);
1370 ov
.handle
= zend_objects_store_put(o
, NULL
, php_http_request_object_free
, NULL TSRMLS_CC
);
1371 ov
.handlers
= &php_http_request_object_handlers
;
1376 zend_object_value
php_http_request_object_clone(zval
*this_ptr TSRMLS_DC
)
1378 zend_object_value new_ov
;
1379 php_http_request_object_t
*new_obj
, *old_obj
= zend_object_store_get_object(this_ptr TSRMLS_CC
);
1381 new_ov
= php_http_request_object_new_ex(old_obj
->zo
.ce
, NULL
, &new_obj TSRMLS_CC
);
1382 if (old_obj
->request
->ch
) {
1383 php_http_curl_init(php_http_curl_copy(old_obj
->request
->ch
), new_obj
->request TSRMLS_CC
);
1386 zend_objects_clone_members(&new_obj
->zo
, new_ov
, &old_obj
->zo
, Z_OBJ_HANDLE_P(this_ptr
) TSRMLS_CC
);
1392 void php_http_request_object_free(void *object TSRMLS_DC
)
1394 php_http_request_object_t
*o
= (php_http_request_object_t
*) object
;
1396 php_http_request_free(&o
->request
);
1397 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
1401 static inline void php_http_request_object_check_request_content_type(zval
*this_ptr TSRMLS_DC
)
1403 zval
*ctype
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("contentType"), 0 TSRMLS_CC
);
1405 if (Z_STRLEN_P(ctype
)) {
1406 zval
**headers
, *opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1408 if ( (Z_TYPE_P(opts
) == IS_ARRAY
) &&
1409 (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), ZEND_STRS("headers"), (void *) &headers
)) &&
1410 (Z_TYPE_PP(headers
) == IS_ARRAY
)) {
1413 /* only override if not already set */
1414 if ((SUCCESS
!= zend_hash_find(Z_ARRVAL_PP(headers
), ZEND_STRS("Content-Type"), (void *) &ct_header
))) {
1415 add_assoc_stringl(*headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1417 /* or not a string, zero length string or a string of spaces */
1418 if ((Z_TYPE_PP(ct_header
) != IS_STRING
) || !Z_STRLEN_PP(ct_header
)) {
1419 add_assoc_stringl(*headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1421 int i
, only_space
= 1;
1423 /* check for spaces only */
1424 for (i
= 0; i
< Z_STRLEN_PP(ct_header
); ++i
) {
1425 if (!PHP_HTTP_IS_CTYPE(space
, Z_STRVAL_PP(ct_header
)[i
])) {
1431 add_assoc_stringl(*headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1437 MAKE_STD_ZVAL(headers
);
1438 array_init(headers
);
1439 add_assoc_stringl(headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1440 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addheaders", NULL
, headers
);
1441 zval_ptr_dtor(&headers
);
1446 static inline zend_object_value
php_http_request_object_message(zval
*this_ptr
, php_http_message_t
*msg TSRMLS_DC
)
1448 zend_object_value ov
;
1449 zval
*zcn
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("messageClass"), 0 TSRMLS_CC
);
1450 zend_class_entry
*class_entry
;
1453 && (class_entry
= zend_fetch_class(Z_STRVAL_P(zcn
), Z_STRLEN_P(zcn
), 0 TSRMLS_CC
))
1454 && (SUCCESS
== php_http_new(&ov
, class_entry
, (php_http_new_t
) php_http_message_object_new_ex
, php_http_message_class_entry
, msg
, NULL TSRMLS_CC
))) {
1457 return php_http_message_object_new_ex(php_http_message_class_entry
, msg
, NULL TSRMLS_CC
);
1461 STATUS
php_http_request_object_requesthandler(php_http_request_object_t
*obj
, zval
*this_ptr TSRMLS_DC
)
1463 STATUS status
= SUCCESS
;
1464 zval
*zurl
, *zmeth
, *zbody
, *zqdata
, *zoptions
;
1465 php_http_message_body_t
*body
= NULL
;
1466 php_url
*tmp
, qdu
= {0};
1468 php_http_request_reset(obj
->request
);
1469 PHP_HTTP_CHECK_CURL_INIT(obj
->request
->ch
, php_http_curl_init(NULL
, obj
->request TSRMLS_CC
), return FAILURE
);
1470 php_http_request_object_check_request_content_type(getThis() TSRMLS_CC
);
1472 zmeth
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("method"), 0 TSRMLS_CC
);
1473 obj
->request
->meth
= Z_LVAL_P(zmeth
);
1475 zurl
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("url"), 0 TSRMLS_CC
);
1476 zqdata
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), 0 TSRMLS_CC
);
1477 if (Z_STRLEN_P(zqdata
)) {
1478 qdu
.query
= Z_STRVAL_P(zqdata
);
1480 php_http_url(0, tmp
= php_url_parse(Z_STRVAL_P(zurl
)), &qdu
, NULL
, &obj
->request
->url
, NULL TSRMLS_CC
);
1483 zbody
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), 0 TSRMLS_CC
);
1484 if (Z_TYPE_P(zbody
) == IS_OBJECT
) {
1485 body
= ((php_http_message_body_object_t
*)zend_object_store_get_object(zbody TSRMLS_CC
))->body
;
1487 obj
->request
->body
= body
;
1489 zoptions
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1490 php_http_request_prepare(obj
->request
, Z_ARRVAL_P(zoptions
));
1492 /* check if there's a onProgress method and add it as progress callback if one isn't already set */
1493 if (zend_hash_exists(&Z_OBJCE_P(getThis())->function_table
, ZEND_STRS("onprogress"))) {
1496 if ((Z_TYPE_P(zoptions
) != IS_ARRAY
)
1497 || (SUCCESS
!= zend_hash_find(Z_ARRVAL_P(zoptions
), ZEND_STRS("onprogress"), (void *) &entry
)
1498 || (!zend_is_callable(*entry
, 0, NULL TSRMLS_CC
)))) {
1501 Z_ADDREF_P(getThis());
1502 add_next_index_zval(pcb
, getThis());
1503 add_next_index_stringl(pcb
, "onprogress", lenof("onprogress"), 1);
1504 php_http_request_set_progress_callback(obj
->request
, pcb
);
1505 zval_ptr_dtor(&pcb
);
1512 STATUS
php_http_request_object_responsehandler(php_http_request_object_t
*obj
, zval
*this_ptr TSRMLS_DC
)
1514 STATUS ret
= SUCCESS
;
1516 php_http_message_t
*msg
;
1518 /* always fetch info */
1519 MAKE_STD_ZVAL(info
);
1521 php_http_request_info(obj
->request
, Z_ARRVAL_P(info
));
1522 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseInfo"), info TSRMLS_CC
);
1523 zval_ptr_dtor(&info
);
1525 /* update history * /
1526 if (i_zend_is_true(zend_read_property(php_http_request_class_entry, getThis(), ZEND_STRL("recordHistory"), 0 TSRMLS_CC))) {
1527 zval *new_hist, *old_hist = zend_read_property(php_http_request_class_entry, getThis(), ZEND_STRL("history"), 0 TSRMLS_CC);
1528 zend_object_value ov = php_http_request_object_message(getThis(), obj->request->message_parser.message TSRMLS_CC);
1530 MAKE_STD_ZVAL(new_hist);
1531 ZVAL_OBJVAL(new_hist, ov, 0);
1533 if (Z_TYPE_P(old_hist) == IS_OBJECT) {
1534 php_http_message_object_prepend(new_hist, old_hist, 0 TSRMLS_CC);
1537 zend_update_property(php_http_request_class_entry, getThis(), ZEND_STRL("history"), new_hist TSRMLS_CC);
1538 zval_ptr_dtor(&new_hist);
1541 // if ((msg = obj->request->_current.request)) {
1542 // /* update request message */
1545 // MAKE_STD_ZVAL(message);
1546 // ZVAL_OBJVAL(message, php_http_request_object_message(getThis(), msg TSRMLS_CC), 1);
1547 // zend_update_property(php_http_request_class_entry, getThis(), ZEND_STRL("requestMessage"), message TSRMLS_CC);
1549 // fprintf(stderr, "RESPONSE MESSAGE: %p\n", obj->request->parser.msg);
1550 if ((msg
= obj
->request
->parser
.msg
)) {
1551 /* update properties with response info */
1554 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("responseCode"), msg
->http
.info
.response
.code TSRMLS_CC
);
1555 zend_update_property_string(php_http_request_class_entry
, getThis(), ZEND_STRL("responseStatus"), STR_PTR(msg
->http
.info
.response
.status
) TSRMLS_CC
);
1557 MAKE_STD_ZVAL(message
);
1558 ZVAL_OBJVAL(message
, php_http_request_object_message(getThis(), msg TSRMLS_CC
), 0);
1559 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), message TSRMLS_CC
);
1560 zval_ptr_dtor(&message
);
1561 obj
->request
->parser
.msg
= php_http_message_init(NULL
, 0 TSRMLS_CC
);
1563 /* update properties with empty values */
1566 MAKE_STD_ZVAL(znull
);
1568 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), znull TSRMLS_CC
);
1569 zval_ptr_dtor(&znull
);
1571 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("responseCode"), 0 TSRMLS_CC
);
1572 zend_update_property_string(php_http_request_class_entry
, getThis(), ZEND_STRL("responseStatus"), "" TSRMLS_CC
);
1575 php_http_request_set_progress_callback(obj
->request
, NULL
);
1577 if (!EG(exception
) && zend_hash_exists(&Z_OBJCE_P(getThis())->function_table
, ZEND_STRS("onfinish"))) {
1580 MAKE_STD_ZVAL(param
);
1581 ZVAL_BOOL(param
, ret
== SUCCESS
);
1582 with_error_handling(EH_NORMAL
, NULL
) {
1583 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "onfinish", NULL
, param
);
1584 } end_error_handling();
1585 zval_ptr_dtor(¶m
);
1591 static int apply_pretty_key(void *pDest
, int num_args
, va_list args
, zend_hash_key
*hash_key
)
1593 if (hash_key
->arKey
&& hash_key
->nKeyLength
> 1) {
1594 hash_key
->h
= zend_hash_func(php_http_pretty_key(hash_key
->arKey
, hash_key
->nKeyLength
- 1, 1, 0), hash_key
->nKeyLength
);
1596 return ZEND_HASH_APPLY_KEEP
;
1599 static inline void php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS
, char *key
, size_t len
, int overwrite
, int prettify_keys
)
1601 zval
*old_opts
, *new_opts
, *opts
= NULL
, **entry
= NULL
;
1603 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a/!", &opts
)) {
1607 MAKE_STD_ZVAL(new_opts
);
1608 array_init(new_opts
);
1609 old_opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1610 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
1611 array_copy(Z_ARRVAL_P(old_opts
), Z_ARRVAL_P(new_opts
));
1614 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(new_opts
), key
, len
, (void *) &entry
)) {
1616 zend_hash_clean(Z_ARRVAL_PP(entry
));
1618 if (opts
&& zend_hash_num_elements(Z_ARRVAL_P(opts
))) {
1620 array_copy(Z_ARRVAL_P(opts
), Z_ARRVAL_PP(entry
));
1622 array_join(Z_ARRVAL_P(opts
), Z_ARRVAL_PP(entry
), 0, prettify_keys
? ARRAY_JOIN_PRETTIFY
: 0);
1626 if (prettify_keys
) {
1627 zend_hash_apply_with_arguments(Z_ARRVAL_P(opts
) TSRMLS_CC
, apply_pretty_key
, 0, NULL
);
1630 add_assoc_zval_ex(new_opts
, key
, len
, opts
);
1632 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
1633 zval_ptr_dtor(&new_opts
);
1638 static inline void php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAMETERS
, char *key
, size_t len
)
1640 if (SUCCESS
== zend_parse_parameters_none()) {
1641 zval
*opts
, **options
;
1643 opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1644 array_init(return_value
);
1646 if ( (Z_TYPE_P(opts
) == IS_ARRAY
) &&
1647 (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), key
, len
, (void *) &options
))) {
1648 convert_to_array(*options
);
1649 array_copy(Z_ARRVAL_PP(options
), Z_ARRVAL_P(return_value
));
1655 PHP_METHOD(HttpRequest
, __construct
)
1657 char *url_str
= NULL
;
1660 zval
*options
= NULL
;
1662 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
1663 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|sla!", &url_str
, &url_len
, &meth
, &options
)) {
1665 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("url"), url_str
, url_len TSRMLS_CC
);
1668 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("method"), meth TSRMLS_CC
);
1671 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "setoptions", NULL
, options
);
1674 } end_error_handling();
1677 PHP_METHOD(HttpRequest
, setOptions
)
1679 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
1681 zval
*opts
= NULL
, *old_opts
, *new_opts
, *add_opts
, **opt
;
1683 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a!/", &opts
)) {
1687 MAKE_STD_ZVAL(new_opts
);
1688 array_init(new_opts
);
1690 if (!opts
|| !zend_hash_num_elements(Z_ARRVAL_P(opts
))) {
1691 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
1692 zval_ptr_dtor(&new_opts
);
1696 MAKE_STD_ZVAL(add_opts
);
1697 array_init(add_opts
);
1698 /* some options need extra attention -- thus cannot use array_merge() directly */
1699 FOREACH_KEYVAL(pos
, opts
, key
, opt
) {
1700 if (key
.type
== HASH_KEY_IS_STRING
) {
1701 #define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
1702 if (KEYMATCH(key
, "headers")) {
1703 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addheaders", NULL
, *opt
);
1704 } else if (KEYMATCH(key
, "cookies")) {
1705 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addcookies", NULL
, *opt
);
1706 } else if (KEYMATCH(key
, "ssl")) {
1707 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addssloptions", NULL
, *opt
);
1708 } else if (KEYMATCH(key
, "url") || KEYMATCH(key
, "uri")) {
1709 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "seturl", NULL
, *opt
);
1710 } else if (KEYMATCH(key
, "method")) {
1711 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "setmethod", NULL
, *opt
);
1712 } else if (KEYMATCH(key
, "flushcookies")) {
1713 if (i_zend_is_true(*opt
)) {
1714 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1716 php_http_request_flush_cookies(obj
->request
);
1718 } else if (KEYMATCH(key
, "resetcookies")) {
1719 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1721 php_http_request_reset_cookies(obj
->request
, (zend_bool
) i_zend_is_true(*opt
));
1722 } else if (KEYMATCH(key
, "enablecookies")) {
1723 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1725 php_http_request_enable_cookies(obj
->request
);
1726 } else if (KEYMATCH(key
, "recordHistory")) {
1727 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("recordHistory"), *opt TSRMLS_CC
);
1728 } else if (KEYMATCH(key
, "messageClass")) {
1729 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "setmessageclass", NULL
, *opt
);
1730 } else if (Z_TYPE_PP(opt
) == IS_NULL
) {
1731 old_opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1732 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
1733 zend_hash_del(Z_ARRVAL_P(old_opts
), key
.str
, key
.len
);
1737 add_assoc_zval_ex(add_opts
, key
.str
, key
.len
, *opt
);
1742 old_opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1743 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
1744 array_copy(Z_ARRVAL_P(old_opts
), Z_ARRVAL_P(new_opts
));
1746 array_join(Z_ARRVAL_P(add_opts
), Z_ARRVAL_P(new_opts
), 0, 0);
1747 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
1748 zval_ptr_dtor(&new_opts
);
1749 zval_ptr_dtor(&add_opts
);
1756 PHP_METHOD(HttpRequest
, getOptions
)
1758 if (SUCCESS
== zend_parse_parameters_none()) {
1759 RETURN_PROP(php_http_request_class_entry
, "options");
1764 PHP_METHOD(HttpRequest
, setSslOptions
)
1766 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("ssl"), 1, 0);
1769 PHP_METHOD(HttpRequest
, addSslOptions
)
1771 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("ssl"), 0, 0);
1774 PHP_METHOD(HttpRequest
, getSslOptions
)
1776 php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("ssl"));
1779 PHP_METHOD(HttpRequest
, addHeaders
)
1781 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("headers"), 0, 1);
1784 PHP_METHOD(HttpRequest
, setHeaders
)
1786 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("headers"), 1, 1);
1789 PHP_METHOD(HttpRequest
, getHeaders
)
1791 php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("headers"));
1794 PHP_METHOD(HttpRequest
, setCookies
)
1796 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("cookies"), 1, 0);
1799 PHP_METHOD(HttpRequest
, addCookies
)
1801 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("cookies"), 0, 0);
1804 PHP_METHOD(HttpRequest
, getCookies
)
1806 php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("cookies"));
1809 PHP_METHOD(HttpRequest
, enableCookies
)
1811 if (SUCCESS
== zend_parse_parameters_none()){
1812 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1814 RETURN_SUCCESS(php_http_request_enable_cookies(obj
->request
));
1819 PHP_METHOD(HttpRequest
, resetCookies
)
1821 zend_bool session_only
= 0;
1823 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|b", &session_only
)) {
1824 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1825 RETURN_SUCCESS(php_http_request_reset_cookies(obj
->request
, session_only
));
1830 PHP_METHOD(HttpRequest
, flushCookies
)
1832 if (SUCCESS
== zend_parse_parameters_none()) {
1833 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1835 RETURN_SUCCESS(php_http_request_flush_cookies(obj
->request
));
1840 PHP_METHOD(HttpRequest
, setUrl
)
1842 char *url_str
= NULL
;
1845 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &url_len
, &url_len
)) {
1846 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("url"), url_str
, url_len TSRMLS_CC
);
1852 PHP_METHOD(HttpRequest
, getUrl
)
1854 if (SUCCESS
== zend_parse_parameters_none()) {
1855 RETURN_PROP(php_http_request_class_entry
, "url");
1860 PHP_METHOD(HttpRequest
, setMethod
)
1864 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &meth
)) {
1865 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("method"), meth TSRMLS_CC
);
1871 PHP_METHOD(HttpRequest
, getMethod
)
1873 if (SUCCESS
== zend_parse_parameters_none()) {
1874 RETURN_PROP(php_http_request_class_entry
, "method");
1879 PHP_METHOD(HttpRequest
, setContentType
)
1884 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &ctype
, &ct_len
)) {
1886 PHP_HTTP_CHECK_CONTENT_TYPE(ctype
, RETURN_FALSE
);
1888 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("contentType"), ctype
, ct_len TSRMLS_CC
);
1894 PHP_METHOD(HttpRequest
, getContentType
)
1896 if (SUCCESS
== zend_parse_parameters_none()) {
1897 RETURN_PROP(php_http_request_class_entry
, "contentType");
1902 PHP_METHOD(HttpRequest
, setQueryData
)
1906 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z!", &qdata
)) {
1907 if ((!qdata
) || Z_TYPE_P(qdata
) == IS_NULL
) {
1908 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), "", 0 TSRMLS_CC
);
1909 } else if ((Z_TYPE_P(qdata
) == IS_ARRAY
) || (Z_TYPE_P(qdata
) == IS_OBJECT
)) {
1910 char *query_data_str
= NULL
;
1911 size_t query_data_len
;
1913 if (SUCCESS
!= php_http_url_encode_hash(HASH_OF(qdata
), 0, NULL
, 0, &query_data_str
, &query_data_len TSRMLS_CC
)) {
1917 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), query_data_str
, query_data_len TSRMLS_CC
);
1918 efree(query_data_str
);
1920 zval
*data
= php_http_zsep(IS_STRING
, qdata
);
1922 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), Z_STRVAL_P(data
), Z_STRLEN_P(data
) TSRMLS_CC
);
1923 zval_ptr_dtor(&data
);
1930 PHP_METHOD(HttpRequest
, getQueryData
)
1932 if (SUCCESS
== zend_parse_parameters_none()) {
1933 RETURN_PROP(php_http_request_class_entry
, "queryData");
1938 PHP_METHOD(HttpRequest
, addQueryData
)
1942 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &qdata
)) {
1943 char *query_data_str
= NULL
;
1944 size_t query_data_len
= 0;
1945 zval
*old_qdata
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), 0 TSRMLS_CC
);
1947 if (SUCCESS
!= php_http_url_encode_hash(HASH_OF(qdata
), 1, Z_STRVAL_P(old_qdata
), Z_STRLEN_P(old_qdata
), &query_data_str
, &query_data_len TSRMLS_CC
)) {
1951 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), query_data_str
, query_data_len TSRMLS_CC
);
1952 efree(query_data_str
);
1960 PHP_METHOD(HttpRequest
, setBody
)
1964 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|O!", &body
, php_http_message_body_class_entry
)) {
1965 if (body
&& Z_TYPE_P(body
) != IS_NULL
) {
1966 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), body TSRMLS_CC
);
1968 zend_update_property_null(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody") TSRMLS_CC
);
1975 PHP_METHOD(HttpRequest
, addBody
)
1979 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &new_body
, php_http_message_body_class_entry
)) {
1980 zval
*old_body
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), 0 TSRMLS_CC
);
1982 if (Z_TYPE_P(old_body
) == IS_OBJECT
) {
1983 php_http_message_body_object_t
*old_obj
= zend_object_store_get_object(old_body TSRMLS_CC
);
1984 php_http_message_body_object_t
*new_obj
= zend_object_store_get_object(new_body TSRMLS_CC
);
1986 php_http_message_body_to_callback(old_obj
->body
, (php_http_pass_callback_t
) php_http_message_body_append
, new_obj
->body
, 0, 0);
1988 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), new_body TSRMLS_CC
);
1995 PHP_METHOD(HttpRequest
, getBody
)
1997 if (SUCCESS
== zend_parse_parameters_none()) {
1998 RETURN_PROP(php_http_request_class_entry
, "requestBody");
2003 PHP_METHOD(HttpRequest
, getResponseHeader
)
2006 char *header_name
= NULL
;
2009 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &header_name
, &header_len
)) {
2010 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2012 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2013 php_http_message_object_t
*msg
= zend_object_store_get_object(message TSRMLS_CC
);
2016 if ((header
= php_http_message_header(msg
->message
, header_name
, header_len
+ 1, 0))) {
2017 RETURN_ZVAL(header
, 1, 1);
2020 array_init(return_value
);
2021 zend_hash_copy(Z_ARRVAL_P(return_value
), &msg
->message
->hdrs
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
2029 PHP_METHOD(HttpRequest
, getResponseCookies
)
2032 zval
*allowed_extras_array
= NULL
;
2034 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|la!", &flags
, &allowed_extras_array
)) {
2036 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
2037 char **allowed_extras
= NULL
;
2038 zval
**header
= NULL
, **entry
= NULL
, *message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2039 HashPosition pos
, pos1
, pos2
;
2041 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2042 php_http_message_object_t
*msg
= zend_object_store_get_object(message TSRMLS_CC
);
2044 array_init(return_value
);
2046 if (allowed_extras_array
) {
2047 allowed_extras
= ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array
)) + 1, sizeof(char *));
2048 FOREACH_VAL(pos
, allowed_extras_array
, entry
) {
2049 zval
*data
= php_http_zsep(IS_STRING
, *entry
);
2050 allowed_extras
[i
++] = estrndup(Z_STRVAL_P(data
), Z_STRLEN_P(data
));
2051 zval_ptr_dtor(&data
);
2055 FOREACH_HASH_KEYVAL(pos1
, &msg
->message
->hdrs
, key
, header
) {
2056 if (key
.type
== HASH_KEY_IS_STRING
&& !strcasecmp(key
.str
, "Set-Cookie")) {
2057 php_http_cookie_list_t
*list
;
2059 if (Z_TYPE_PP(header
) == IS_ARRAY
) {
2060 zval
**single_header
;
2062 FOREACH_VAL(pos2
, *header
, single_header
) {
2063 zval
*data
= php_http_zsep(IS_STRING
, *single_header
);
2065 if ((list
= php_http_cookie_list_parse(NULL
, Z_STRVAL_P(data
), flags
, allowed_extras TSRMLS_CC
))) {
2068 MAKE_STD_ZVAL(cookie
);
2069 ZVAL_OBJVAL(cookie
, php_http_cookie_object_new_ex(php_http_cookie_class_entry
, list
, NULL TSRMLS_CC
), 0);
2070 add_next_index_zval(return_value
, cookie
);
2072 zval_ptr_dtor(&data
);
2075 zval
*data
= php_http_zsep(IS_STRING
, *header
);
2076 if ((list
= php_http_cookie_list_parse(NULL
, Z_STRVAL_P(data
), flags
, allowed_extras TSRMLS_CC
))) {
2079 MAKE_STD_ZVAL(cookie
);
2080 ZVAL_OBJVAL(cookie
, php_http_cookie_object_new_ex(php_http_cookie_class_entry
, list
, NULL TSRMLS_CC
), 0);
2081 add_next_index_zval(return_value
, cookie
);
2083 zval_ptr_dtor(&data
);
2088 if (allowed_extras
) {
2089 for (i
= 0; allowed_extras
[i
]; ++i
) {
2090 efree(allowed_extras
[i
]);
2092 efree(allowed_extras
);
2101 PHP_METHOD(HttpRequest
, getResponseBody
)
2103 if (SUCCESS
== zend_parse_parameters_none()) {
2104 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2106 RETURN_OBJVAL(((php_http_message_object_t
*)zend_object_store_get_object(message TSRMLS_CC
))->body
, 1);
2111 PHP_METHOD(HttpRequest
, getResponseCode
)
2113 if (SUCCESS
== zend_parse_parameters_none()) {
2114 RETURN_PROP(php_http_request_class_entry
, "responseCode");
2119 PHP_METHOD(HttpRequest
, getResponseStatus
)
2121 if (SUCCESS
== zend_parse_parameters_none()) {
2122 RETURN_PROP(php_http_request_class_entry
, "responseStatus");
2127 PHP_METHOD(HttpRequest
, getResponseInfo
)
2129 char *info_name
= NULL
;
2132 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &info_name
, &info_len
)) {
2133 zval
**infop
, *info
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseInfo"), 0 TSRMLS_CC
);
2135 if (Z_TYPE_P(info
) != IS_ARRAY
) {
2139 if (info_len
&& info_name
) {
2140 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(info
), php_http_pretty_key(info_name
, info_len
, 0, 0), info_len
+ 1, (void *) &infop
)) {
2141 RETURN_ZVAL(*infop
, 1, 0);
2143 php_http_error(HE_NOTICE
, PHP_HTTP_E_INVALID_PARAM
, "Could not find response info named %s", info_name
);
2147 RETURN_ZVAL(info
, 1, 0);
2153 PHP_METHOD(HttpRequest
, getResponseMessage
)
2155 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2156 if (SUCCESS
== zend_parse_parameters_none()) {
2157 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2159 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2160 RETVAL_OBJECT(message
, 1);
2162 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "HttpRequest does not contain a response message");
2165 } end_error_handling();
2168 PHP_METHOD(HttpRequest
, getRequestMessage
)
2170 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2171 if (SUCCESS
== zend_parse_parameters_none()) {
2172 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestMessage"), 0 TSRMLS_CC
);
2174 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2175 RETVAL_OBJECT(message
, 1);
2177 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "HttpRequest does not contain a request message");
2180 } end_error_handling();
2183 PHP_METHOD(HttpRequest
, getHistory
)
2185 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2186 if (SUCCESS
== zend_parse_parameters_none()) {
2187 zval
*hist
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("history"), 0 TSRMLS_CC
);
2189 if (Z_TYPE_P(hist
) == IS_OBJECT
) {
2190 RETVAL_OBJECT(hist
, 1);
2192 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "The history is empty");
2195 } end_error_handling();
2198 PHP_METHOD(HttpRequest
, clearHistory
)
2200 if (SUCCESS
== zend_parse_parameters_none()) {
2201 zend_update_property_null(php_http_request_class_entry
, getThis(), ZEND_STRL("history") TSRMLS_CC
);
2207 PHP_METHOD(HttpRequest
, getMessageClass
)
2209 if (SUCCESS
== zend_parse_parameters_none()) {
2210 RETURN_PROP(php_http_request_class_entry
, "messageClass");
2215 PHP_METHOD(HttpRequest
, setMessageClass
)
2220 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &cn
, &cl
)) {
2221 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("messageClass"), cn
, cl TSRMLS_CC
);
2225 PHP_METHOD(HttpRequest
, send
)
2229 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2230 if (SUCCESS
== zend_parse_parameters_none()) {
2231 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2234 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool");
2235 } else if (SUCCESS
== php_http_request_object_requesthandler(obj
, getThis() TSRMLS_CC
)) {
2236 php_http_request_exec(obj
->request
);
2237 if (SUCCESS
== php_http_request_object_responsehandler(obj
, getThis() TSRMLS_CC
)) {
2238 RETVAL_PROP(php_http_request_class_entry
, "responseMessage");
2240 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST
, "Failed to handle response");
2243 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST
, "Failed to handle request");
2246 } end_error_handling();
2249 PHP_MINIT_FUNCTION(http_request
)
2251 #ifdef PHP_HTTP_NEED_OPENSSL_TSL
2252 /* mod_ssl, libpq or ext/curl might already have set thread lock callbacks */
2253 if (!CRYPTO_get_id_callback()) {
2254 int i
, c
= CRYPTO_num_locks();
2256 php_http_openssl_tsl
= malloc(c
* sizeof(MUTEX_T
));
2258 for (i
= 0; i
< c
; ++i
) {
2259 php_http_openssl_tsl
[i
] = tsrm_mutex_alloc();
2262 CRYPTO_set_id_callback(php_http_openssl_thread_id
);
2263 CRYPTO_set_locking_callback(php_http_openssl_thread_lock
);
2266 #ifdef PHP_HTTP_NEED_GNUTLS_TSL
2267 gcry_control(GCRYCTL_SET_THREAD_CBS
, &php_http_gnutls_tsl
);
2270 if (CURLE_OK
!= curl_global_init(CURL_GLOBAL_ALL
)) {
2274 if (SUCCESS
!= php_http_persistent_handle_provide(ZEND_STRL("http_request"), safe_curl_init
, safe_curl_dtor
, safe_curl_copy
)) {
2278 PHP_HTTP_REGISTER_CLASS(http
, Request
, http_request
, php_http_object_class_entry
, 0);
2279 php_http_request_class_entry
->create_object
= php_http_request_object_new
;
2280 memcpy(&php_http_request_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
2281 php_http_request_object_handlers
.clone_obj
= php_http_request_object_clone
;
2283 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("options"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2284 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("responseInfo"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2285 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("responseMessage"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2286 zend_declare_property_long(php_http_request_class_entry
, ZEND_STRL("responseCode"), 0, ZEND_ACC_PRIVATE TSRMLS_CC
);
2287 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("responseStatus"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2288 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("requestMessage"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2289 zend_declare_property_long(php_http_request_class_entry
, ZEND_STRL("method"), PHP_HTTP_GET
, ZEND_ACC_PRIVATE TSRMLS_CC
);
2290 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("url"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2291 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("contentType"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2292 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("requestBody"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2293 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("queryData"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2294 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("history"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2295 zend_declare_property_bool(php_http_request_class_entry
, ZEND_STRL("recordHistory"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2296 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("messageClass"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2299 * HTTP Protocol Version Constants
2301 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_1_0"), CURL_HTTP_VERSION_1_0 TSRMLS_CC
);
2302 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_1_1"), CURL_HTTP_VERSION_1_1 TSRMLS_CC
);
2303 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_NONE"), CURL_HTTP_VERSION_NONE TSRMLS_CC
); /* to be removed */
2304 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_ANY"), CURL_HTTP_VERSION_NONE TSRMLS_CC
);
2307 * SSL Version Constants
2309 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_TLSv1"), CURL_SSLVERSION_TLSv1 TSRMLS_CC
);
2310 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_SSLv2"), CURL_SSLVERSION_SSLv2 TSRMLS_CC
);
2311 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_SSLv3"), CURL_SSLVERSION_SSLv3 TSRMLS_CC
);
2312 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_ANY"), CURL_SSLVERSION_DEFAULT TSRMLS_CC
);
2315 * DNS IPvX resolving
2317 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("IPRESOLVE_V4"), CURL_IPRESOLVE_V4 TSRMLS_CC
);
2318 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("IPRESOLVE_V6"), CURL_IPRESOLVE_V6 TSRMLS_CC
);
2319 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("IPRESOLVE_ANY"), CURL_IPRESOLVE_WHATEVER TSRMLS_CC
);
2324 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_BASIC"), CURLAUTH_BASIC TSRMLS_CC
);
2325 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_DIGEST"), CURLAUTH_DIGEST TSRMLS_CC
);
2326 #if PHP_HTTP_CURL_VERSION(7,19,3)
2327 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_DIGEST_IE"), CURLAUTH_DIGEST_IE TSRMLS_CC
);
2329 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_NTLM"), CURLAUTH_NTLM TSRMLS_CC
);
2330 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_GSSNEG"), CURLAUTH_GSSNEGOTIATE TSRMLS_CC
);
2331 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_ANY"), CURLAUTH_ANY TSRMLS_CC
);
2334 * Proxy Type Constants
2336 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS4"), CURLPROXY_SOCKS4 TSRMLS_CC
);
2337 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS4A"), CURLPROXY_SOCKS5 TSRMLS_CC
);
2338 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS5_HOSTNAME"), CURLPROXY_SOCKS5 TSRMLS_CC
);
2339 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS5"), CURLPROXY_SOCKS5 TSRMLS_CC
);
2340 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_HTTP"), CURLPROXY_HTTP TSRMLS_CC
);
2341 # if PHP_HTTP_CURL_VERSION(7,19,4)
2342 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_HTTP_1_0"), CURLPROXY_HTTP_1_0 TSRMLS_CC
);
2346 * Post Redirection Constants
2348 #if PHP_HTTP_CURL_VERSION(7,19,1)
2349 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("POSTREDIR_301"), CURL_REDIR_POST_301 TSRMLS_CC
);
2350 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("POSTREDIR_302"), CURL_REDIR_POST_302 TSRMLS_CC
);
2351 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("POSTREDIR_ALL"), CURL_REDIR_POST_ALL TSRMLS_CC
);
2357 PHP_MSHUTDOWN_FUNCTION(http_request
)
2359 curl_global_cleanup();
2360 #ifdef PHP_HTTP_NEED_OPENSSL_TSL
2361 if (php_http_openssl_tsl
) {
2362 int i
, c
= CRYPTO_num_locks();
2364 CRYPTO_set_id_callback(NULL
);
2365 CRYPTO_set_locking_callback(NULL
);
2367 for (i
= 0; i
< c
; ++i
) {
2368 tsrm_mutex_free(php_http_openssl_tsl
[i
]);
2371 free(php_http_openssl_tsl
);
2372 php_http_openssl_tsl
= NULL
;
2383 * vim600: noet sw=4 ts=4 fdm=marker
2384 * vim<600: noet sw=4 ts=4