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
, 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);
613 /* retries, defaults to 0 */
614 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("retrycount"), IS_LONG
))) {
615 request
->_retry
.count
= Z_LVAL_P(zoption
);
616 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("retrydelay"), IS_DOUBLE
))) {
617 request
->_retry
.delay
= Z_DVAL_P(zoption
);
619 request
->_retry
.delay
= 0;
622 request
->_retry
.count
= 0;
626 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("referer"), IS_STRING
)) && Z_STRLEN_P(zoption
)) {
627 PHP_HTTP_CURL_OPT(CURLOPT_REFERER
, Z_STRVAL_P(zoption
));
630 /* useragent, default "PECL::HTTP/version (PHP/version)" */
631 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("useragent"), IS_STRING
))) {
632 /* allow to send no user agent, not even default one */
633 if (Z_STRLEN_P(zoption
)) {
634 PHP_HTTP_CURL_OPT(CURLOPT_USERAGENT
, Z_STRVAL_P(zoption
));
636 PHP_HTTP_CURL_OPT(CURLOPT_USERAGENT
, NULL
);
641 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("resume"), IS_LONG
)) && (Z_LVAL_P(zoption
) > 0)) {
643 PHP_HTTP_CURL_OPT(CURLOPT_RESUME_FROM
, Z_LVAL_P(zoption
));
645 /* or range of kind array(array(0,499), array(100,1499)) */
646 else if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("range"), IS_ARRAY
)) && zend_hash_num_elements(Z_ARRVAL_P(zoption
))) {
647 HashPosition pos1
, pos2
;
648 zval
**rr
, **rb
, **re
;
649 php_http_buffer_t rs
;
651 php_http_buffer_init(&rs
);
652 FOREACH_VAL(pos1
, zoption
, rr
) {
653 if (Z_TYPE_PP(rr
) == IS_ARRAY
) {
654 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(rr
), &pos2
);
655 if (SUCCESS
== zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr
), (void *) &rb
, &pos2
)) {
656 zend_hash_move_forward_ex(Z_ARRVAL_PP(rr
), &pos2
);
657 if (SUCCESS
== zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr
), (void *) &re
, &pos2
)) {
658 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))) &&
659 ((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)))) {
660 zval
*rbl
= php_http_zsep(IS_LONG
, *rb
);
661 zval
*rel
= php_http_zsep(IS_LONG
, *re
);
663 if ((Z_LVAL_P(rbl
) >= 0) && (Z_LVAL_P(rel
) >= 0)) {
664 php_http_buffer_appendf(&rs
, "%ld-%ld,", Z_LVAL_P(rbl
), Z_LVAL_P(rel
));
674 if (PHP_HTTP_BUFFER_LEN(&rs
)) {
677 /* ditch last comma */
678 PHP_HTTP_BUFFER_VAL(&rs
)[PHP_HTTP_BUFFER_LEN(&rs
)-- -1] = '\0';
680 MAKE_STD_ZVAL(cached_range
);
681 ZVAL_STRINGL(cached_range
, PHP_HTTP_BUFFER_VAL(&rs
), PHP_HTTP_BUFFER_LEN(&rs
), 0);
682 PHP_HTTP_CURL_OPT(CURLOPT_RANGE
, Z_STRVAL_P(php_http_request_option_cache(request
, ZEND_STRS("range"), 0, cached_range
)));
683 zval_ptr_dtor(&cached_range
);
687 /* additional headers, array('name' => 'value') */
688 if (request
->_cache
.headers
) {
689 curl_slist_free_all(request
->_cache
.headers
);
690 request
->_cache
.headers
= NULL
;
692 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("headers"), IS_ARRAY
))) {
693 php_http_array_hashkey_t header_key
= php_http_array_hashkey_init(0);
696 php_http_buffer_t header
;
698 php_http_buffer_init(&header
);
699 FOREACH_KEYVAL(pos
, zoption
, header_key
, header_val
) {
700 if (header_key
.type
== HASH_KEY_IS_STRING
) {
701 zval
*header_cpy
= php_http_zsep(IS_STRING
, *header_val
);
703 if (!strcasecmp(header_key
.str
, "range")) {
707 php_http_buffer_appendf(&header
, "%s: %s", header_key
.str
, Z_STRVAL_P(header_cpy
));
708 php_http_buffer_fix(&header
);
709 request
->_cache
.headers
= curl_slist_append(request
->_cache
.headers
, PHP_HTTP_BUFFER_VAL(&header
));
710 php_http_buffer_reset(&header
);
712 zval_ptr_dtor(&header_cpy
);
715 php_http_buffer_dtor(&header
);
718 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("etag"), IS_STRING
)) && Z_STRLEN_P(zoption
)) {
719 zend_bool is_quoted
= !((Z_STRVAL_P(zoption
)[0] != '"') || (Z_STRVAL_P(zoption
)[Z_STRLEN_P(zoption
)-1] != '"'));
720 php_http_buffer_t header
;
722 php_http_buffer_init(&header
);
723 php_http_buffer_appendf(&header
, is_quoted
?"%s: %s":"%s: \"%s\"", range_req
?"If-Match":"If-None-Match", Z_STRVAL_P(zoption
));
724 php_http_buffer_fix(&header
);
725 request
->_cache
.headers
= curl_slist_append(request
->_cache
.headers
, PHP_HTTP_BUFFER_VAL(&header
));
726 php_http_buffer_dtor(&header
);
729 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("compress"), IS_BOOL
)) && Z_LVAL_P(zoption
)) {
730 request
->_cache
.headers
= curl_slist_append(request
->_cache
.headers
, "Accept-Encoding: gzip;q=1.0,deflate;q=0.5");
732 PHP_HTTP_CURL_OPT(CURLOPT_HTTPHEADER
, request
->_cache
.headers
);
735 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("lastmodified"), IS_LONG
))) {
736 if (Z_LVAL_P(zoption
)) {
737 if (Z_LVAL_P(zoption
) > 0) {
738 PHP_HTTP_CURL_OPT(CURLOPT_TIMEVALUE
, Z_LVAL_P(zoption
));
740 PHP_HTTP_CURL_OPT(CURLOPT_TIMEVALUE
, (long) PHP_HTTP_G
->env
.request
.time
+ Z_LVAL_P(zoption
));
742 PHP_HTTP_CURL_OPT(CURLOPT_TIMECONDITION
, (long) (range_req
? CURL_TIMECOND_IFUNMODSINCE
: CURL_TIMECOND_IFMODSINCE
));
744 PHP_HTTP_CURL_OPT(CURLOPT_TIMECONDITION
, CURL_TIMECOND_NONE
);
748 /* cookies, array('name' => 'value') */
749 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("cookies"), IS_ARRAY
))) {
750 php_http_buffer_dtor(&request
->_cache
.cookies
);
751 if (zend_hash_num_elements(Z_ARRVAL_P(zoption
))) {
752 zval
*urlenc_cookies
= NULL
;
753 /* check whether cookies should not be urlencoded; default is to urlencode them */
754 if ((!(urlenc_cookies
= php_http_request_option(request
, options
, ZEND_STRS("encodecookies"), IS_BOOL
))) || Z_BVAL_P(urlenc_cookies
)) {
755 if (SUCCESS
== php_http_url_encode_hash_recursive(HASH_OF(zoption
), &request
->_cache
.cookies
, "; ", lenof("; "), NULL
, 0 TSRMLS_CC
)) {
756 php_http_buffer_fix(&request
->_cache
.cookies
);
757 PHP_HTTP_CURL_OPT(CURLOPT_COOKIE
, request
->_cache
.cookies
.data
);
761 php_http_array_hashkey_t cookie_key
= php_http_array_hashkey_init(0);
764 FOREACH_KEYVAL(pos
, zoption
, cookie_key
, cookie_val
) {
765 if (cookie_key
.type
== HASH_KEY_IS_STRING
) {
766 zval
*val
= php_http_zsep(IS_STRING
, *cookie_val
);
767 php_http_buffer_appendf(&request
->_cache
.cookies
, "%s=%s; ", cookie_key
.str
, Z_STRVAL_P(val
));
772 php_http_buffer_fix(&request
->_cache
.cookies
);
773 if (PHP_HTTP_BUFFER_LEN(&request
->_cache
.cookies
)) {
774 PHP_HTTP_CURL_OPT(CURLOPT_COOKIE
, PHP_HTTP_BUFFER_VAL(&request
->_cache
.cookies
));
780 /* don't load session cookies from cookiestore */
781 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("cookiesession"), IS_BOOL
)) && Z_BVAL_P(zoption
)) {
782 PHP_HTTP_CURL_OPT(CURLOPT_COOKIESESSION
, 1L);
785 /* cookiestore, read initial cookies from that file and store cookies back into that file */
786 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("cookiestore"), IS_STRING
))) {
787 if (Z_STRLEN_P(zoption
)) {
788 if (SUCCESS
!= php_check_open_basedir(Z_STRVAL_P(zoption
) TSRMLS_CC
)) {
792 if (storage
->cookiestore
) {
793 pefree(storage
->cookiestore
, 1);
795 storage
->cookiestore
= pestrndup(Z_STRVAL_P(zoption
), Z_STRLEN_P(zoption
), 1);
796 PHP_HTTP_CURL_OPT(CURLOPT_COOKIEFILE
, storage
->cookiestore
);
797 PHP_HTTP_CURL_OPT(CURLOPT_COOKIEJAR
, storage
->cookiestore
);
801 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("maxfilesize"), IS_LONG
))) {
802 PHP_HTTP_CURL_OPT(CURLOPT_MAXFILESIZE
, Z_LVAL_P(zoption
));
806 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("protocol"), IS_LONG
))) {
807 PHP_HTTP_CURL_OPT(CURLOPT_HTTP_VERSION
, Z_LVAL_P(zoption
));
810 /* timeout, defaults to 0 */
811 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("timeout"), IS_DOUBLE
))) {
812 PHP_HTTP_CURL_OPT(CURLOPT_TIMEOUT_MS
, (long)(Z_DVAL_P(zoption
)*1000));
814 /* connecttimeout, defaults to 0 */
815 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("connecttimeout"), IS_DOUBLE
))) {
816 PHP_HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT_MS
, (long)(Z_DVAL_P(zoption
)*1000));
820 if ((zoption
= php_http_request_option(request
, options
, ZEND_STRS("ssl"), IS_ARRAY
))) {
821 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
825 FOREACH_KEYVAL(pos
, zoption
, key
, param
) {
826 if (key
.type
== HASH_KEY_IS_STRING
) {
827 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLCERT
, 0, 1);
828 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTTYPE
, 0, 0);
829 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTPASSWD
, 0, 0);
831 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLKEY
, 0, 0);
832 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYTYPE
, 0, 0);
833 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYPASSWD
, 0, 0);
835 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSLENGINE
, 0, 0);
836 PHP_HTTP_CURL_OPT_LONG(CURLOPT_SSLVERSION
, 0);
838 PHP_HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYPEER
, 1);
839 PHP_HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYHOST
, 1);
840 PHP_HTTP_CURL_OPT_STRING(CURLOPT_SSL_CIPHER_LIST
, 1, 0);
842 PHP_HTTP_CURL_OPT_STRING(CURLOPT_CAINFO
, -3, 1);
843 PHP_HTTP_CURL_OPT_STRING(CURLOPT_CAPATH
, -3, 1);
844 PHP_HTTP_CURL_OPT_STRING(CURLOPT_RANDOM_FILE
, -3, 1);
845 PHP_HTTP_CURL_OPT_STRING(CURLOPT_EGDSOCKET
, -3, 1);
846 #if PHP_HTTP_CURL_VERSION(7,19,0)
847 PHP_HTTP_CURL_OPT_STRING(CURLOPT_ISSUERCERT
, -3, 1);
848 #if defined(PHP_HTTP_HAVE_OPENSSL)
849 PHP_HTTP_CURL_OPT_STRING(CURLOPT_CRLFILE
, -3, 1);
852 #if PHP_HTTP_CURL_VERSION(7,19,1) && defined(PHP_HTTP_HAVE_OPENSSL)
853 PHP_HTTP_CURL_OPT_LONG(CURLOPT_CERTINFO
, -3);
860 switch (request
->meth
) {
862 PHP_HTTP_CURL_OPT(CURLOPT_HTTPGET
, 1L);
866 PHP_HTTP_CURL_OPT(CURLOPT_NOBODY
, 1L);
870 PHP_HTTP_CURL_OPT(CURLOPT_POST
, 1L);
874 PHP_HTTP_CURL_OPT(CURLOPT_UPLOAD
, 1L);
878 const char *meth
= php_http_request_method_name(request
->meth
);
881 PHP_HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST
, meth
);
883 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST_METHOD
, "Unsupported request method: %d (%s)", request
->meth
, request
->url
);
890 /* attach request body */
891 if (request
->body
&& (request
->meth
!= PHP_HTTP_GET
) && (request
->meth
!= PHP_HTTP_HEAD
) && (request
->meth
!= PHP_HTTP_OPTIONS
)) {
892 if (1 || request
->meth
== PHP_HTTP_PUT
) {
893 /* PUT/UPLOAD _needs_ READDATA */
894 PHP_HTTP_CURL_OPT(CURLOPT_IOCTLDATA
, request
);
895 PHP_HTTP_CURL_OPT(CURLOPT_READDATA
, request
);
896 PHP_HTTP_CURL_OPT(CURLOPT_INFILESIZE
, php_http_message_body_size(request
->body
));
899 //PHP_HTTP_CURL_OPT(CURLOPT_POSTFIELDS, request->body->real->data);
900 PHP_HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE
, php_http_message_body_size(request
->body
));
907 PHP_HTTP_API
void php_http_request_exec(php_http_request_t
*request
)
911 TSRMLS_FETCH_FROM_CTX(request
->ts
);
914 if (CURLE_OK
!= (result
= curl_easy_perform(request
->ch
))) {
915 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
);
917 add_property_long(EG(exception
), "curlCode", result
);
920 if (request
->_retry
.count
> tries
++) {
922 case CURLE_COULDNT_RESOLVE_PROXY
:
923 case CURLE_COULDNT_RESOLVE_HOST
:
924 case CURLE_COULDNT_CONNECT
:
925 case CURLE_WRITE_ERROR
:
926 case CURLE_READ_ERROR
:
927 case CURLE_OPERATION_TIMEDOUT
:
928 case CURLE_SSL_CONNECT_ERROR
:
929 case CURLE_GOT_NOTHING
:
930 case CURLE_SSL_ENGINE_SETFAILED
:
931 case CURLE_SEND_ERROR
:
932 case CURLE_RECV_ERROR
:
933 case CURLE_SSL_ENGINE_INITFAILED
:
934 case CURLE_LOGIN_DENIED
:
935 if (request
->_retry
.delay
>= PHP_HTTP_DIFFSEC
) {
936 php_http_sleep(request
->_retry
.delay
);
946 static size_t php_http_curl_read_callback(void *data
, size_t len
, size_t n
, void *ctx
)
948 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
949 TSRMLS_FETCH_FROM_CTX(request
->ts
);
952 return php_stream_read(php_http_message_body_stream(request
->body
), data
, len
* n
);
957 static int php_http_curl_progress_callback(void *ctx
, double dltotal
, double dlnow
, double ultotal
, double ulnow
)
959 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
961 request
->_progress
.state
.dl
.total
= dltotal
;
962 request
->_progress
.state
.dl
.now
= dlnow
;
963 request
->_progress
.state
.ul
.total
= ultotal
;
964 request
->_progress
.state
.ul
.now
= ulnow
;
966 if (request
->_progress
.callback
) {
968 TSRMLS_FETCH_FROM_CTX(request
->ts
);
973 MAKE_STD_ZVAL(param
);
975 add_assoc_double(param
, "dltotal", request
->_progress
.state
.dl
.total
);
976 add_assoc_double(param
, "dlnow", request
->_progress
.state
.dl
.now
);
977 add_assoc_double(param
, "ultotal", request
->_progress
.state
.ul
.total
);
978 add_assoc_double(param
, "ulnow", request
->_progress
.state
.ul
.now
);
980 with_error_handling(EH_NORMAL
, NULL
) {
981 request
->_progress
.in_cb
= 1;
982 call_user_function(EG(function_table
), NULL
, request
->_progress
.callback
, &retval
, 1, ¶m TSRMLS_CC
);
983 request
->_progress
.in_cb
= 0;
984 } end_error_handling();
986 zval_ptr_dtor(¶m
);
993 static curlioerr
php_http_curl_ioctl_callback(CURL
*ch
, curliocmd cmd
, void *ctx
)
995 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
996 TSRMLS_FETCH_FROM_CTX(request
->ts
);
998 if (cmd
!= CURLIOCMD_RESTARTREAD
) {
999 return CURLIOE_UNKNOWNCMD
;
1002 if (request
->body
) {
1003 if (SUCCESS
== php_stream_rewind(php_http_message_body_stream(request
->body
))) {
1008 return CURLIOE_FAILRESTART
;
1011 static int php_http_curl_raw_callback(CURL
*ch
, curl_infotype type
, char *data
, size_t length
, void *ctx
)
1013 php_http_request_t
*request
= (php_http_request_t
*) ctx
;
1017 case CURLINFO_HEADER_IN
:
1018 case CURLINFO_DATA_IN
:
1019 case CURLINFO_HEADER_OUT
:
1020 case CURLINFO_DATA_OUT
:
1021 php_http_buffer_append(request
->parser
.buf
, data
, length
);
1022 if (PHP_HTTP_MESSAGE_PARSER_STATE_FAILURE
== php_http_message_parser_parse(request
->parser
.ctx
, request
->parser
.buf
, 0, &request
->parser
.msg
)) {
1033 const char _sym
[] = "><><><";
1035 for (fprintf(stderr
, "%c ", _sym
[type
-1]); length
--; data
++) {
1036 fprintf(stderr
, PHP_HTTP_IS_CTYPE(print
, *data
)?"%c":"\\x%02X", (int) *data
);
1037 if (*data
== '\n' && length
) {
1038 fprintf(stderr
, "\n%c ", _sym
[type
-1]);
1041 fprintf(stderr
, "\n");
1043 fprintf(stderr
, "# %s", data
);
1051 static inline zval
*php_http_request_option(php_http_request_t
*r
, HashTable
*options
, char *key
, size_t keylen
, int type
)
1053 TSRMLS_FETCH_FROM_CTX(r
->ts
);
1057 ulong h
= zend_hash_func(key
, keylen
);
1059 if (SUCCESS
== zend_hash_quick_find(options
, key
, keylen
, h
, (void *) &zoption
)) {
1060 zval
*option
, *cached
;
1062 option
= php_http_zsep(type
, *zoption
);
1063 cached
= php_http_request_option_cache(r
, key
, keylen
, h
, option
);
1065 zval_ptr_dtor(&option
);
1073 static inline zval
*php_http_request_option_cache(php_http_request_t
*r
, char *key
, size_t keylen
, ulong h
, zval
*opt
)
1075 TSRMLS_FETCH_FROM_CTX(r
->ts
);
1079 zend_hash_quick_update(&r
->_cache
.options
, key
, keylen
, h
, &opt
, sizeof(zval
*), NULL
);
1081 zend_hash_update(&r
->_cache
.options
, key
, keylen
, &opt
, sizeof(zval
*), NULL
);
1087 static inline int php_http_request_cookies_enabled(php_http_request_t
*request
) {
1088 php_http_request_storage_t
*st
;
1090 if (request
->ch
&& (st
= php_http_request_storage_get(request
->ch
)) && st
->cookiestore
) {
1091 /* cookies are enabled */
1099 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpRequest, method, 0, req_args)
1100 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpRequest, method, 0)
1101 #define PHP_HTTP_REQUEST_ME(method, visibility) PHP_ME(HttpRequest, method, PHP_HTTP_ARGS(HttpRequest, method), visibility)
1102 #define PHP_HTTP_REQUEST_ALIAS(method, func) PHP_HTTP_STATIC_ME_ALIAS(method, func, PHP_HTTP_ARGS(HttpRequest, method))
1103 #define PHP_HTTP_REQUEST_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpRequest_##al), PHP_HTTP_ARGS(HttpRequest, al), vis)
1105 PHP_HTTP_BEGIN_ARGS(__construct
, 0)
1106 PHP_HTTP_ARG_VAL(url
, 0)
1107 PHP_HTTP_ARG_VAL(method
, 0)
1108 PHP_HTTP_ARG_VAL(options
, 0)
1111 PHP_HTTP_BEGIN_ARGS(factory
, 0)
1112 PHP_HTTP_ARG_VAL(url
, 0)
1113 PHP_HTTP_ARG_VAL(method
, 0)
1114 PHP_HTTP_ARG_VAL(options
, 0)
1115 PHP_HTTP_ARG_VAL(class_name
, 0)
1118 PHP_HTTP_EMPTY_ARGS(getOptions
);
1119 PHP_HTTP_BEGIN_ARGS(setOptions
, 0)
1120 PHP_HTTP_ARG_VAL(options
, 0)
1123 PHP_HTTP_EMPTY_ARGS(getSslOptions
);
1124 PHP_HTTP_BEGIN_ARGS(setSslOptions
, 0)
1125 PHP_HTTP_ARG_VAL(ssl_options
, 0)
1128 PHP_HTTP_BEGIN_ARGS(addSslOptions
, 0)
1129 PHP_HTTP_ARG_VAL(ssl_optins
, 0)
1132 PHP_HTTP_EMPTY_ARGS(getHeaders
);
1133 PHP_HTTP_BEGIN_ARGS(setHeaders
, 0)
1134 PHP_HTTP_ARG_VAL(headers
, 0)
1137 PHP_HTTP_BEGIN_ARGS(addHeaders
, 1)
1138 PHP_HTTP_ARG_VAL(headers
, 0)
1141 PHP_HTTP_EMPTY_ARGS(getCookies
);
1142 PHP_HTTP_BEGIN_ARGS(setCookies
, 0)
1143 PHP_HTTP_ARG_VAL(cookies
, 0)
1146 PHP_HTTP_BEGIN_ARGS(addCookies
, 1)
1147 PHP_HTTP_ARG_VAL(cookies
, 0)
1150 PHP_HTTP_EMPTY_ARGS(enableCookies
);
1151 PHP_HTTP_BEGIN_ARGS(resetCookies
, 0)
1152 PHP_HTTP_ARG_VAL(session_only
, 0)
1154 PHP_HTTP_EMPTY_ARGS(flushCookies
);
1156 PHP_HTTP_EMPTY_ARGS(getUrl
);
1157 PHP_HTTP_BEGIN_ARGS(setUrl
, 1)
1158 PHP_HTTP_ARG_VAL(url
, 0)
1161 PHP_HTTP_EMPTY_ARGS(getMethod
);
1162 PHP_HTTP_BEGIN_ARGS(setMethod
, 1)
1163 PHP_HTTP_ARG_VAL(request_method
, 0)
1166 PHP_HTTP_EMPTY_ARGS(getContentType
);
1167 PHP_HTTP_BEGIN_ARGS(setContentType
, 1)
1168 PHP_HTTP_ARG_VAL(content_type
, 0)
1171 PHP_HTTP_EMPTY_ARGS(getQueryData
);
1172 PHP_HTTP_BEGIN_ARGS(setQueryData
, 0)
1173 PHP_HTTP_ARG_VAL(query_data
, 0)
1176 PHP_HTTP_BEGIN_ARGS(addQueryData
, 1)
1177 PHP_HTTP_ARG_VAL(query_data
, 0)
1181 PHP_HTTP_EMPTY_ARGS(getBody
);
1182 PHP_HTTP_BEGIN_ARGS(setBody
, 0)
1183 PHP_HTTP_ARG_OBJ(http
\\message
\\Body
, body
, 0)
1186 PHP_HTTP_BEGIN_ARGS(addBody
, 1)
1187 PHP_HTTP_ARG_OBJ(http
\\message
\\Body
, body
, 0)
1190 PHP_HTTP_BEGIN_ARGS(getResponseCookies
, 0)
1191 PHP_HTTP_ARG_VAL(flags
, 0)
1192 PHP_HTTP_ARG_VAL(allowed_extras
, 0)
1195 PHP_HTTP_EMPTY_ARGS(getResponseBody
);
1196 PHP_HTTP_EMPTY_ARGS(getResponseCode
);
1197 PHP_HTTP_EMPTY_ARGS(getResponseStatus
);
1198 PHP_HTTP_BEGIN_ARGS(getResponseInfo
, 0)
1199 PHP_HTTP_ARG_VAL(name
, 0)
1202 PHP_HTTP_BEGIN_ARGS(getResponseHeader
, 0)
1203 PHP_HTTP_ARG_VAL(header_name
, 0)
1206 PHP_HTTP_EMPTY_ARGS(getMessageClass
);
1207 PHP_HTTP_BEGIN_ARGS(setMessageClass
, 1)
1208 PHP_HTTP_ARG_VAL(message_class_name
, 0)
1211 PHP_HTTP_EMPTY_ARGS(getResponseMessage
);
1212 PHP_HTTP_EMPTY_ARGS(getRawResponseMessage
);
1213 PHP_HTTP_EMPTY_ARGS(getRequestMessage
);
1214 PHP_HTTP_EMPTY_ARGS(getRawRequestMessage
);
1215 PHP_HTTP_EMPTY_ARGS(getHistory
);
1216 PHP_HTTP_EMPTY_ARGS(clearHistory
);
1217 PHP_HTTP_EMPTY_ARGS(send
);
1219 PHP_HTTP_BEGIN_ARGS(get
, 1)
1220 PHP_HTTP_ARG_VAL(url
, 0)
1221 PHP_HTTP_ARG_VAL(options
, 0)
1222 PHP_HTTP_ARG_VAL(info
, 1)
1225 PHP_HTTP_BEGIN_ARGS(head
, 1)
1226 PHP_HTTP_ARG_VAL(url
, 0)
1227 PHP_HTTP_ARG_VAL(options
, 0)
1228 PHP_HTTP_ARG_VAL(info
, 1)
1231 PHP_HTTP_BEGIN_ARGS(postData
, 2)
1232 PHP_HTTP_ARG_VAL(url
, 0)
1233 PHP_HTTP_ARG_VAL(data
, 0)
1234 PHP_HTTP_ARG_VAL(options
, 0)
1235 PHP_HTTP_ARG_VAL(info
, 1)
1238 PHP_HTTP_BEGIN_ARGS(postFields
, 2)
1239 PHP_HTTP_ARG_VAL(url
, 0)
1240 PHP_HTTP_ARG_VAL(data
, 0)
1241 PHP_HTTP_ARG_VAL(options
, 0)
1242 PHP_HTTP_ARG_VAL(info
, 1)
1245 PHP_HTTP_BEGIN_ARGS(putData
, 2)
1246 PHP_HTTP_ARG_VAL(url
, 0)
1247 PHP_HTTP_ARG_VAL(data
, 0)
1248 PHP_HTTP_ARG_VAL(options
, 0)
1249 PHP_HTTP_ARG_VAL(info
, 1)
1252 PHP_HTTP_BEGIN_ARGS(putFile
, 2)
1253 PHP_HTTP_ARG_VAL(url
, 0)
1254 PHP_HTTP_ARG_VAL(file
, 0)
1255 PHP_HTTP_ARG_VAL(options
, 0)
1256 PHP_HTTP_ARG_VAL(info
, 1)
1259 PHP_HTTP_BEGIN_ARGS(putStream
, 2)
1260 PHP_HTTP_ARG_VAL(url
, 0)
1261 PHP_HTTP_ARG_VAL(stream
, 0)
1262 PHP_HTTP_ARG_VAL(options
, 0)
1263 PHP_HTTP_ARG_VAL(info
, 1)
1266 PHP_HTTP_BEGIN_ARGS(methodRegister
, 1)
1267 PHP_HTTP_ARG_VAL(method_name
, 0)
1270 PHP_HTTP_BEGIN_ARGS(methodUnregister
, 1)
1271 PHP_HTTP_ARG_VAL(method
, 0)
1274 PHP_HTTP_BEGIN_ARGS(methodName
, 1)
1275 PHP_HTTP_ARG_VAL(method_id
, 0)
1278 PHP_HTTP_BEGIN_ARGS(methodExists
, 1)
1279 PHP_HTTP_ARG_VAL(method
, 0)
1282 #ifdef HAVE_CURL_FORMGET
1283 PHP_HTTP_BEGIN_ARGS(encodeBody
, 2)
1284 PHP_HTTP_ARG_VAL(fields
, 0)
1285 PHP_HTTP_ARG_VAL(files
, 0)
1289 zend_class_entry
*php_http_request_class_entry
;
1290 zend_function_entry php_http_request_method_entry
[] = {
1291 PHP_HTTP_REQUEST_ME(__construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
1293 PHP_HTTP_REQUEST_ME(setOptions
, ZEND_ACC_PUBLIC
)
1294 PHP_HTTP_REQUEST_ME(getOptions
, ZEND_ACC_PUBLIC
)
1295 PHP_HTTP_REQUEST_ME(setSslOptions
, ZEND_ACC_PUBLIC
)
1296 PHP_HTTP_REQUEST_ME(getSslOptions
, ZEND_ACC_PUBLIC
)
1297 PHP_HTTP_REQUEST_ME(addSslOptions
, ZEND_ACC_PUBLIC
)
1299 PHP_HTTP_REQUEST_ME(addHeaders
, ZEND_ACC_PUBLIC
)
1300 PHP_HTTP_REQUEST_ME(getHeaders
, ZEND_ACC_PUBLIC
)
1301 PHP_HTTP_REQUEST_ME(setHeaders
, ZEND_ACC_PUBLIC
)
1303 PHP_HTTP_REQUEST_ME(addCookies
, ZEND_ACC_PUBLIC
)
1304 PHP_HTTP_REQUEST_ME(getCookies
, ZEND_ACC_PUBLIC
)
1305 PHP_HTTP_REQUEST_ME(setCookies
, ZEND_ACC_PUBLIC
)
1307 PHP_HTTP_REQUEST_ME(enableCookies
, ZEND_ACC_PUBLIC
)
1308 PHP_HTTP_REQUEST_ME(resetCookies
, ZEND_ACC_PUBLIC
)
1309 PHP_HTTP_REQUEST_ME(flushCookies
, ZEND_ACC_PUBLIC
)
1311 PHP_HTTP_REQUEST_ME(setMethod
, ZEND_ACC_PUBLIC
)
1312 PHP_HTTP_REQUEST_ME(getMethod
, ZEND_ACC_PUBLIC
)
1314 PHP_HTTP_REQUEST_ME(setUrl
, ZEND_ACC_PUBLIC
)
1315 PHP_HTTP_REQUEST_ME(getUrl
, ZEND_ACC_PUBLIC
)
1317 PHP_HTTP_REQUEST_ME(setContentType
, ZEND_ACC_PUBLIC
)
1318 PHP_HTTP_REQUEST_ME(getContentType
, ZEND_ACC_PUBLIC
)
1320 PHP_HTTP_REQUEST_ME(setQueryData
, ZEND_ACC_PUBLIC
)
1321 PHP_HTTP_REQUEST_ME(getQueryData
, ZEND_ACC_PUBLIC
)
1322 PHP_HTTP_REQUEST_ME(addQueryData
, ZEND_ACC_PUBLIC
)
1324 PHP_HTTP_REQUEST_ME(setBody
, ZEND_ACC_PUBLIC
)
1325 PHP_HTTP_REQUEST_ME(getBody
, ZEND_ACC_PUBLIC
)
1326 PHP_HTTP_REQUEST_ME(addBody
, ZEND_ACC_PUBLIC
)
1328 PHP_HTTP_REQUEST_ME(send
, ZEND_ACC_PUBLIC
)
1330 PHP_HTTP_REQUEST_ME(getResponseHeader
, ZEND_ACC_PUBLIC
)
1331 PHP_HTTP_REQUEST_ME(getResponseCookies
, ZEND_ACC_PUBLIC
)
1332 PHP_HTTP_REQUEST_ME(getResponseCode
, ZEND_ACC_PUBLIC
)
1333 PHP_HTTP_REQUEST_ME(getResponseStatus
, ZEND_ACC_PUBLIC
)
1334 PHP_HTTP_REQUEST_ME(getResponseBody
, ZEND_ACC_PUBLIC
)
1335 PHP_HTTP_REQUEST_ME(getResponseInfo
, ZEND_ACC_PUBLIC
)
1336 PHP_HTTP_REQUEST_ME(getResponseMessage
, ZEND_ACC_PUBLIC
)
1337 PHP_HTTP_REQUEST_ME(getRequestMessage
, ZEND_ACC_PUBLIC
)
1338 PHP_HTTP_REQUEST_ME(getHistory
, ZEND_ACC_PUBLIC
)
1339 PHP_HTTP_REQUEST_ME(clearHistory
, ZEND_ACC_PUBLIC
)
1341 PHP_HTTP_REQUEST_ME(getMessageClass
, ZEND_ACC_PUBLIC
)
1342 PHP_HTTP_REQUEST_ME(setMessageClass
, ZEND_ACC_PUBLIC
)
1344 EMPTY_FUNCTION_ENTRY
1346 static zend_object_handlers php_http_request_object_handlers
;
1348 zend_object_value
php_http_request_object_new(zend_class_entry
*ce TSRMLS_DC
)
1350 return php_http_request_object_new_ex(ce
, NULL
, NULL
);
1353 zend_object_value
php_http_request_object_new_ex(zend_class_entry
*ce
, CURL
*ch
, php_http_request_object_t
**ptr TSRMLS_DC
)
1355 zend_object_value ov
;
1356 php_http_request_object_t
*o
;
1358 o
= ecalloc(1, sizeof(php_http_request_object_t
));
1359 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
1360 object_properties_init((zend_object
*) o
, ce
);
1362 o
->request
= php_http_request_init(NULL
, ch
, 0, NULL TSRMLS_CC
);
1368 ov
.handle
= zend_objects_store_put(o
, NULL
, php_http_request_object_free
, NULL TSRMLS_CC
);
1369 ov
.handlers
= &php_http_request_object_handlers
;
1374 zend_object_value
php_http_request_object_clone(zval
*this_ptr TSRMLS_DC
)
1376 zend_object_value new_ov
;
1377 php_http_request_object_t
*new_obj
, *old_obj
= zend_object_store_get_object(this_ptr TSRMLS_CC
);
1379 new_ov
= php_http_request_object_new_ex(old_obj
->zo
.ce
, NULL
, &new_obj TSRMLS_CC
);
1380 if (old_obj
->request
->ch
) {
1381 php_http_curl_init(php_http_curl_copy(old_obj
->request
->ch
), new_obj
->request TSRMLS_CC
);
1384 zend_objects_clone_members(&new_obj
->zo
, new_ov
, &old_obj
->zo
, Z_OBJ_HANDLE_P(this_ptr
) TSRMLS_CC
);
1390 void php_http_request_object_free(void *object TSRMLS_DC
)
1392 php_http_request_object_t
*o
= (php_http_request_object_t
*) object
;
1394 php_http_request_free(&o
->request
);
1395 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
1399 static inline void php_http_request_object_check_request_content_type(zval
*this_ptr TSRMLS_DC
)
1401 zval
*ctype
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("contentType"), 0 TSRMLS_CC
);
1403 if (Z_STRLEN_P(ctype
)) {
1404 zval
**headers
, *opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1406 if ( (Z_TYPE_P(opts
) == IS_ARRAY
) &&
1407 (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), ZEND_STRS("headers"), (void *) &headers
)) &&
1408 (Z_TYPE_PP(headers
) == IS_ARRAY
)) {
1411 /* only override if not already set */
1412 if ((SUCCESS
!= zend_hash_find(Z_ARRVAL_PP(headers
), ZEND_STRS("Content-Type"), (void *) &ct_header
))) {
1413 add_assoc_stringl(*headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1415 /* or not a string, zero length string or a string of spaces */
1416 if ((Z_TYPE_PP(ct_header
) != IS_STRING
) || !Z_STRLEN_PP(ct_header
)) {
1417 add_assoc_stringl(*headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1419 int i
, only_space
= 1;
1421 /* check for spaces only */
1422 for (i
= 0; i
< Z_STRLEN_PP(ct_header
); ++i
) {
1423 if (!PHP_HTTP_IS_CTYPE(space
, Z_STRVAL_PP(ct_header
)[i
])) {
1429 add_assoc_stringl(*headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1435 MAKE_STD_ZVAL(headers
);
1436 array_init(headers
);
1437 add_assoc_stringl(headers
, "Content-Type", Z_STRVAL_P(ctype
), Z_STRLEN_P(ctype
), 1);
1438 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addheaders", NULL
, headers
);
1439 zval_ptr_dtor(&headers
);
1444 static inline zend_object_value
php_http_request_object_message(zval
*this_ptr
, php_http_message_t
*msg TSRMLS_DC
)
1446 zend_object_value ov
;
1447 zval
*zcn
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("messageClass"), 0 TSRMLS_CC
);
1448 zend_class_entry
*class_entry
;
1451 && (class_entry
= zend_fetch_class(Z_STRVAL_P(zcn
), Z_STRLEN_P(zcn
), 0 TSRMLS_CC
))
1452 && (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
))) {
1455 return php_http_message_object_new_ex(php_http_message_class_entry
, msg
, NULL TSRMLS_CC
);
1459 STATUS
php_http_request_object_requesthandler(php_http_request_object_t
*obj
, zval
*this_ptr TSRMLS_DC
)
1461 STATUS status
= SUCCESS
;
1462 zval
*zurl
, *zmeth
, *zbody
, *zqdata
, *zoptions
;
1463 php_http_message_body_t
*body
= NULL
;
1464 php_url
*tmp
, qdu
= {0};
1466 php_http_request_reset(obj
->request
);
1467 PHP_HTTP_CHECK_CURL_INIT(obj
->request
->ch
, php_http_curl_init(NULL
, obj
->request TSRMLS_CC
), return FAILURE
);
1468 php_http_request_object_check_request_content_type(getThis() TSRMLS_CC
);
1470 zmeth
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("method"), 0 TSRMLS_CC
);
1471 obj
->request
->meth
= Z_LVAL_P(zmeth
);
1473 zurl
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("url"), 0 TSRMLS_CC
);
1474 zqdata
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), 0 TSRMLS_CC
);
1475 if (Z_STRLEN_P(zqdata
)) {
1476 qdu
.query
= Z_STRVAL_P(zqdata
);
1478 php_http_url(0, tmp
= php_url_parse(Z_STRVAL_P(zurl
)), &qdu
, NULL
, &obj
->request
->url
, NULL TSRMLS_CC
);
1481 zbody
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), 0 TSRMLS_CC
);
1482 if (Z_TYPE_P(zbody
) == IS_OBJECT
) {
1483 body
= ((php_http_message_body_object_t
*)zend_object_store_get_object(zbody TSRMLS_CC
))->body
;
1485 obj
->request
->body
= body
;
1487 zoptions
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1488 php_http_request_prepare(obj
->request
, Z_ARRVAL_P(zoptions
));
1490 /* check if there's a onProgress method and add it as progress callback if one isn't already set */
1491 if (zend_hash_exists(&Z_OBJCE_P(getThis())->function_table
, ZEND_STRS("onprogress"))) {
1494 if ((Z_TYPE_P(zoptions
) != IS_ARRAY
)
1495 || (SUCCESS
!= zend_hash_find(Z_ARRVAL_P(zoptions
), ZEND_STRS("onprogress"), (void *) &entry
)
1496 || (!zend_is_callable(*entry
, 0, NULL TSRMLS_CC
)))) {
1499 Z_ADDREF_P(getThis());
1500 add_next_index_zval(pcb
, getThis());
1501 add_next_index_stringl(pcb
, "onprogress", lenof("onprogress"), 1);
1502 php_http_request_set_progress_callback(obj
->request
, pcb
);
1503 zval_ptr_dtor(&pcb
);
1510 STATUS
php_http_request_object_responsehandler(php_http_request_object_t
*obj
, zval
*this_ptr TSRMLS_DC
)
1512 STATUS ret
= SUCCESS
;
1514 php_http_message_t
*msg
;
1516 /* always fetch info */
1517 MAKE_STD_ZVAL(info
);
1519 php_http_request_info(obj
->request
, Z_ARRVAL_P(info
));
1520 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseInfo"), info TSRMLS_CC
);
1521 zval_ptr_dtor(&info
);
1523 /* update history * /
1524 if (i_zend_is_true(zend_read_property(php_http_request_class_entry, getThis(), ZEND_STRL("recordHistory"), 0 TSRMLS_CC))) {
1525 zval *new_hist, *old_hist = zend_read_property(php_http_request_class_entry, getThis(), ZEND_STRL("history"), 0 TSRMLS_CC);
1526 zend_object_value ov = php_http_request_object_message(getThis(), obj->request->message_parser.message TSRMLS_CC);
1528 MAKE_STD_ZVAL(new_hist);
1529 ZVAL_OBJVAL(new_hist, ov, 0);
1531 if (Z_TYPE_P(old_hist) == IS_OBJECT) {
1532 php_http_message_object_prepend(new_hist, old_hist, 0 TSRMLS_CC);
1535 zend_update_property(php_http_request_class_entry, getThis(), ZEND_STRL("history"), new_hist TSRMLS_CC);
1536 zval_ptr_dtor(&new_hist);
1539 // if ((msg = obj->request->_current.request)) {
1540 // /* update request message */
1543 // MAKE_STD_ZVAL(message);
1544 // ZVAL_OBJVAL(message, php_http_request_object_message(getThis(), msg TSRMLS_CC), 1);
1545 // zend_update_property(php_http_request_class_entry, getThis(), ZEND_STRL("requestMessage"), message TSRMLS_CC);
1547 // fprintf(stderr, "RESPONSE MESSAGE: %p\n", obj->request->parser.msg);
1548 if ((msg
= obj
->request
->parser
.msg
)) {
1549 /* update properties with response info */
1552 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("responseCode"), msg
->http
.info
.response
.code TSRMLS_CC
);
1553 zend_update_property_string(php_http_request_class_entry
, getThis(), ZEND_STRL("responseStatus"), STR_PTR(msg
->http
.info
.response
.status
) TSRMLS_CC
);
1555 MAKE_STD_ZVAL(message
);
1556 ZVAL_OBJVAL(message
, php_http_request_object_message(getThis(), msg TSRMLS_CC
), 0);
1557 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), message TSRMLS_CC
);
1558 zval_ptr_dtor(&message
);
1559 obj
->request
->parser
.msg
= php_http_message_init(NULL
, 0 TSRMLS_CC
);
1561 /* update properties with empty values */
1564 MAKE_STD_ZVAL(znull
);
1566 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), znull TSRMLS_CC
);
1567 zval_ptr_dtor(&znull
);
1569 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("responseCode"), 0 TSRMLS_CC
);
1570 zend_update_property_string(php_http_request_class_entry
, getThis(), ZEND_STRL("responseStatus"), "" TSRMLS_CC
);
1573 php_http_request_set_progress_callback(obj
->request
, NULL
);
1575 if (!EG(exception
) && zend_hash_exists(&Z_OBJCE_P(getThis())->function_table
, ZEND_STRS("onfinish"))) {
1578 MAKE_STD_ZVAL(param
);
1579 ZVAL_BOOL(param
, ret
== SUCCESS
);
1580 with_error_handling(EH_NORMAL
, NULL
) {
1581 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "onfinish", NULL
, param
);
1582 } end_error_handling();
1583 zval_ptr_dtor(¶m
);
1589 static int apply_pretty_key(void *pDest
, int num_args
, va_list args
, zend_hash_key
*hash_key
)
1591 if (hash_key
->arKey
&& hash_key
->nKeyLength
> 1) {
1592 hash_key
->h
= zend_hash_func(php_http_pretty_key(hash_key
->arKey
, hash_key
->nKeyLength
- 1, 1, 0), hash_key
->nKeyLength
);
1594 return ZEND_HASH_APPLY_KEEP
;
1597 static inline void php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS
, char *key
, size_t len
, int overwrite
, int prettify_keys
)
1599 zval
*old_opts
, *new_opts
, *opts
= NULL
, **entry
= NULL
;
1601 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a/!", &opts
)) {
1605 MAKE_STD_ZVAL(new_opts
);
1606 array_init(new_opts
);
1607 old_opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1608 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
1609 array_copy(Z_ARRVAL_P(old_opts
), Z_ARRVAL_P(new_opts
));
1612 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(new_opts
), key
, len
, (void *) &entry
)) {
1614 zend_hash_clean(Z_ARRVAL_PP(entry
));
1616 if (opts
&& zend_hash_num_elements(Z_ARRVAL_P(opts
))) {
1618 array_copy(Z_ARRVAL_P(opts
), Z_ARRVAL_PP(entry
));
1620 array_join(Z_ARRVAL_P(opts
), Z_ARRVAL_PP(entry
), 0, prettify_keys
? ARRAY_JOIN_PRETTIFY
: 0);
1624 if (prettify_keys
) {
1625 zend_hash_apply_with_arguments(Z_ARRVAL_P(opts
) TSRMLS_CC
, apply_pretty_key
, 0, NULL
);
1628 add_assoc_zval_ex(new_opts
, key
, len
, opts
);
1630 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
1631 zval_ptr_dtor(&new_opts
);
1636 static inline void php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAMETERS
, char *key
, size_t len
)
1638 if (SUCCESS
== zend_parse_parameters_none()) {
1639 zval
*opts
, **options
;
1641 opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1642 array_init(return_value
);
1644 if ( (Z_TYPE_P(opts
) == IS_ARRAY
) &&
1645 (SUCCESS
== zend_hash_find(Z_ARRVAL_P(opts
), key
, len
, (void *) &options
))) {
1646 convert_to_array(*options
);
1647 array_copy(Z_ARRVAL_PP(options
), Z_ARRVAL_P(return_value
));
1653 PHP_METHOD(HttpRequest
, __construct
)
1655 char *url_str
= NULL
;
1658 zval
*options
= NULL
;
1660 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
1661 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|sla!", &url_str
, &url_len
, &meth
, &options
)) {
1663 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("url"), url_str
, url_len TSRMLS_CC
);
1666 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("method"), meth TSRMLS_CC
);
1669 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "setoptions", NULL
, options
);
1672 } end_error_handling();
1675 PHP_METHOD(HttpRequest
, setOptions
)
1677 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
1679 zval
*opts
= NULL
, *old_opts
, *new_opts
, *add_opts
, **opt
;
1681 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a!/", &opts
)) {
1685 MAKE_STD_ZVAL(new_opts
);
1686 array_init(new_opts
);
1688 if (!opts
|| !zend_hash_num_elements(Z_ARRVAL_P(opts
))) {
1689 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
1690 zval_ptr_dtor(&new_opts
);
1694 MAKE_STD_ZVAL(add_opts
);
1695 array_init(add_opts
);
1696 /* some options need extra attention -- thus cannot use array_merge() directly */
1697 FOREACH_KEYVAL(pos
, opts
, key
, opt
) {
1698 if (key
.type
== HASH_KEY_IS_STRING
) {
1699 #define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
1700 if (KEYMATCH(key
, "headers")) {
1701 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addheaders", NULL
, *opt
);
1702 } else if (KEYMATCH(key
, "cookies")) {
1703 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addcookies", NULL
, *opt
);
1704 } else if (KEYMATCH(key
, "ssl")) {
1705 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "addssloptions", NULL
, *opt
);
1706 } else if (KEYMATCH(key
, "url") || KEYMATCH(key
, "uri")) {
1707 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "seturl", NULL
, *opt
);
1708 } else if (KEYMATCH(key
, "method")) {
1709 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "setmethod", NULL
, *opt
);
1710 } else if (KEYMATCH(key
, "flushcookies")) {
1711 if (i_zend_is_true(*opt
)) {
1712 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1714 php_http_request_flush_cookies(obj
->request
);
1716 } else if (KEYMATCH(key
, "resetcookies")) {
1717 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1719 php_http_request_reset_cookies(obj
->request
, (zend_bool
) i_zend_is_true(*opt
));
1720 } else if (KEYMATCH(key
, "enablecookies")) {
1721 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1723 php_http_request_enable_cookies(obj
->request
);
1724 } else if (KEYMATCH(key
, "recordHistory")) {
1725 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("recordHistory"), *opt TSRMLS_CC
);
1726 } else if (KEYMATCH(key
, "messageClass")) {
1727 zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "setmessageclass", NULL
, *opt
);
1728 } else if (Z_TYPE_PP(opt
) == IS_NULL
) {
1729 old_opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1730 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
1731 zend_hash_del(Z_ARRVAL_P(old_opts
), key
.str
, key
.len
);
1735 add_assoc_zval_ex(add_opts
, key
.str
, key
.len
, *opt
);
1740 old_opts
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1741 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
1742 array_copy(Z_ARRVAL_P(old_opts
), Z_ARRVAL_P(new_opts
));
1744 array_join(Z_ARRVAL_P(add_opts
), Z_ARRVAL_P(new_opts
), 0, 0);
1745 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
1746 zval_ptr_dtor(&new_opts
);
1747 zval_ptr_dtor(&add_opts
);
1754 PHP_METHOD(HttpRequest
, getOptions
)
1756 if (SUCCESS
== zend_parse_parameters_none()) {
1757 RETURN_PROP(php_http_request_class_entry
, "options");
1762 PHP_METHOD(HttpRequest
, setSslOptions
)
1764 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("ssl"), 1, 0);
1767 PHP_METHOD(HttpRequest
, addSslOptions
)
1769 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("ssl"), 0, 0);
1772 PHP_METHOD(HttpRequest
, getSslOptions
)
1774 php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("ssl"));
1777 PHP_METHOD(HttpRequest
, addHeaders
)
1779 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("headers"), 0, 1);
1782 PHP_METHOD(HttpRequest
, setHeaders
)
1784 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("headers"), 1, 1);
1787 PHP_METHOD(HttpRequest
, getHeaders
)
1789 php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("headers"));
1792 PHP_METHOD(HttpRequest
, setCookies
)
1794 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("cookies"), 1, 0);
1797 PHP_METHOD(HttpRequest
, addCookies
)
1799 php_http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("cookies"), 0, 0);
1802 PHP_METHOD(HttpRequest
, getCookies
)
1804 php_http_request_object_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU
, ZEND_STRS("cookies"));
1807 PHP_METHOD(HttpRequest
, enableCookies
)
1809 if (SUCCESS
== zend_parse_parameters_none()){
1810 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1812 RETURN_SUCCESS(php_http_request_enable_cookies(obj
->request
));
1817 PHP_METHOD(HttpRequest
, resetCookies
)
1819 zend_bool session_only
= 0;
1821 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|b", &session_only
)) {
1822 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1823 RETURN_SUCCESS(php_http_request_reset_cookies(obj
->request
, session_only
));
1828 PHP_METHOD(HttpRequest
, flushCookies
)
1830 if (SUCCESS
== zend_parse_parameters_none()) {
1831 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1833 RETURN_SUCCESS(php_http_request_flush_cookies(obj
->request
));
1838 PHP_METHOD(HttpRequest
, setUrl
)
1840 char *url_str
= NULL
;
1843 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &url_len
, &url_len
)) {
1844 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("url"), url_str
, url_len TSRMLS_CC
);
1850 PHP_METHOD(HttpRequest
, getUrl
)
1852 if (SUCCESS
== zend_parse_parameters_none()) {
1853 RETURN_PROP(php_http_request_class_entry
, "url");
1858 PHP_METHOD(HttpRequest
, setMethod
)
1862 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "l", &meth
)) {
1863 zend_update_property_long(php_http_request_class_entry
, getThis(), ZEND_STRL("method"), meth TSRMLS_CC
);
1869 PHP_METHOD(HttpRequest
, getMethod
)
1871 if (SUCCESS
== zend_parse_parameters_none()) {
1872 RETURN_PROP(php_http_request_class_entry
, "method");
1877 PHP_METHOD(HttpRequest
, setContentType
)
1882 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &ctype
, &ct_len
)) {
1884 PHP_HTTP_CHECK_CONTENT_TYPE(ctype
, RETURN_FALSE
);
1886 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("contentType"), ctype
, ct_len TSRMLS_CC
);
1892 PHP_METHOD(HttpRequest
, getContentType
)
1894 if (SUCCESS
== zend_parse_parameters_none()) {
1895 RETURN_PROP(php_http_request_class_entry
, "contentType");
1900 PHP_METHOD(HttpRequest
, setQueryData
)
1904 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z!", &qdata
)) {
1905 if ((!qdata
) || Z_TYPE_P(qdata
) == IS_NULL
) {
1906 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), "", 0 TSRMLS_CC
);
1907 } else if ((Z_TYPE_P(qdata
) == IS_ARRAY
) || (Z_TYPE_P(qdata
) == IS_OBJECT
)) {
1908 char *query_data_str
= NULL
;
1909 size_t query_data_len
;
1911 if (SUCCESS
!= php_http_url_encode_hash(HASH_OF(qdata
), 0, NULL
, 0, &query_data_str
, &query_data_len TSRMLS_CC
)) {
1915 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), query_data_str
, query_data_len TSRMLS_CC
);
1916 efree(query_data_str
);
1918 zval
*data
= php_http_zsep(IS_STRING
, qdata
);
1920 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), Z_STRVAL_P(data
), Z_STRLEN_P(data
) TSRMLS_CC
);
1921 zval_ptr_dtor(&data
);
1928 PHP_METHOD(HttpRequest
, getQueryData
)
1930 if (SUCCESS
== zend_parse_parameters_none()) {
1931 RETURN_PROP(php_http_request_class_entry
, "queryData");
1936 PHP_METHOD(HttpRequest
, addQueryData
)
1940 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "a/", &qdata
)) {
1941 char *query_data_str
= NULL
;
1942 size_t query_data_len
= 0;
1943 zval
*old_qdata
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), 0 TSRMLS_CC
);
1945 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
)) {
1949 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("queryData"), query_data_str
, query_data_len TSRMLS_CC
);
1950 efree(query_data_str
);
1958 PHP_METHOD(HttpRequest
, setBody
)
1962 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|O!", &body
, php_http_message_body_class_entry
)) {
1963 if (body
&& Z_TYPE_P(body
) != IS_NULL
) {
1964 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), body TSRMLS_CC
);
1966 zend_update_property_null(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody") TSRMLS_CC
);
1973 PHP_METHOD(HttpRequest
, addBody
)
1977 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &new_body
, php_http_message_body_class_entry
)) {
1978 zval
*old_body
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), 0 TSRMLS_CC
);
1980 if (Z_TYPE_P(old_body
) == IS_OBJECT
) {
1981 php_http_message_body_object_t
*old_obj
= zend_object_store_get_object(old_body TSRMLS_CC
);
1982 php_http_message_body_object_t
*new_obj
= zend_object_store_get_object(new_body TSRMLS_CC
);
1984 php_http_message_body_to_callback(old_obj
->body
, (php_http_pass_callback_t
) php_http_message_body_append
, new_obj
->body
, 0, 0);
1986 zend_update_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestBody"), new_body TSRMLS_CC
);
1993 PHP_METHOD(HttpRequest
, getBody
)
1995 if (SUCCESS
== zend_parse_parameters_none()) {
1996 RETURN_PROP(php_http_request_class_entry
, "requestBody");
2001 PHP_METHOD(HttpRequest
, getResponseHeader
)
2004 char *header_name
= NULL
;
2007 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &header_name
, &header_len
)) {
2008 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2010 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2011 php_http_message_object_t
*msg
= zend_object_store_get_object(message TSRMLS_CC
);
2014 if ((header
= php_http_message_header(msg
->message
, header_name
, header_len
+ 1, 0))) {
2015 RETURN_ZVAL(header
, 1, 1);
2018 array_init(return_value
);
2019 zend_hash_copy(Z_ARRVAL_P(return_value
), &msg
->message
->hdrs
, (copy_ctor_func_t
) zval_add_ref
, NULL
, sizeof(zval
*));
2027 PHP_METHOD(HttpRequest
, getResponseCookies
)
2030 zval
*allowed_extras_array
= NULL
;
2032 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|la!", &flags
, &allowed_extras_array
)) {
2034 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
2035 char **allowed_extras
= NULL
;
2036 zval
**header
= NULL
, **entry
= NULL
, *message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2037 HashPosition pos
, pos1
, pos2
;
2039 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2040 php_http_message_object_t
*msg
= zend_object_store_get_object(message TSRMLS_CC
);
2042 array_init(return_value
);
2044 if (allowed_extras_array
) {
2045 allowed_extras
= ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array
)) + 1, sizeof(char *));
2046 FOREACH_VAL(pos
, allowed_extras_array
, entry
) {
2047 zval
*data
= php_http_zsep(IS_STRING
, *entry
);
2048 allowed_extras
[i
++] = estrndup(Z_STRVAL_P(data
), Z_STRLEN_P(data
));
2049 zval_ptr_dtor(&data
);
2053 FOREACH_HASH_KEYVAL(pos1
, &msg
->message
->hdrs
, key
, header
) {
2054 if (key
.type
== HASH_KEY_IS_STRING
&& !strcasecmp(key
.str
, "Set-Cookie")) {
2055 php_http_cookie_list_t
*list
;
2057 if (Z_TYPE_PP(header
) == IS_ARRAY
) {
2058 zval
**single_header
;
2060 FOREACH_VAL(pos2
, *header
, single_header
) {
2061 zval
*data
= php_http_zsep(IS_STRING
, *single_header
);
2063 if ((list
= php_http_cookie_list_parse(NULL
, Z_STRVAL_P(data
), flags
, allowed_extras TSRMLS_CC
))) {
2066 MAKE_STD_ZVAL(cookie
);
2067 ZVAL_OBJVAL(cookie
, php_http_cookie_object_new_ex(php_http_cookie_class_entry
, list
, NULL TSRMLS_CC
), 0);
2068 add_next_index_zval(return_value
, cookie
);
2070 zval_ptr_dtor(&data
);
2073 zval
*data
= php_http_zsep(IS_STRING
, *header
);
2074 if ((list
= php_http_cookie_list_parse(NULL
, Z_STRVAL_P(data
), flags
, allowed_extras TSRMLS_CC
))) {
2077 MAKE_STD_ZVAL(cookie
);
2078 ZVAL_OBJVAL(cookie
, php_http_cookie_object_new_ex(php_http_cookie_class_entry
, list
, NULL TSRMLS_CC
), 0);
2079 add_next_index_zval(return_value
, cookie
);
2081 zval_ptr_dtor(&data
);
2086 if (allowed_extras
) {
2087 for (i
= 0; allowed_extras
[i
]; ++i
) {
2088 efree(allowed_extras
[i
]);
2090 efree(allowed_extras
);
2099 PHP_METHOD(HttpRequest
, getResponseBody
)
2101 if (SUCCESS
== zend_parse_parameters_none()) {
2102 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2104 RETURN_OBJVAL(((php_http_message_object_t
*)zend_object_store_get_object(message TSRMLS_CC
))->body
, 1);
2109 PHP_METHOD(HttpRequest
, getResponseCode
)
2111 if (SUCCESS
== zend_parse_parameters_none()) {
2112 RETURN_PROP(php_http_request_class_entry
, "responseCode");
2117 PHP_METHOD(HttpRequest
, getResponseStatus
)
2119 if (SUCCESS
== zend_parse_parameters_none()) {
2120 RETURN_PROP(php_http_request_class_entry
, "responseStatus");
2125 PHP_METHOD(HttpRequest
, getResponseInfo
)
2127 char *info_name
= NULL
;
2130 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|s", &info_name
, &info_len
)) {
2131 zval
**infop
, *info
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseInfo"), 0 TSRMLS_CC
);
2133 if (Z_TYPE_P(info
) != IS_ARRAY
) {
2137 if (info_len
&& info_name
) {
2138 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(info
), php_http_pretty_key(info_name
, info_len
, 0, 0), info_len
+ 1, (void *) &infop
)) {
2139 RETURN_ZVAL(*infop
, 1, 0);
2141 php_http_error(HE_NOTICE
, PHP_HTTP_E_INVALID_PARAM
, "Could not find response info named %s", info_name
);
2145 RETURN_ZVAL(info
, 1, 0);
2151 PHP_METHOD(HttpRequest
, getResponseMessage
)
2153 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2154 if (SUCCESS
== zend_parse_parameters_none()) {
2155 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("responseMessage"), 0 TSRMLS_CC
);
2157 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2158 RETVAL_OBJECT(message
, 1);
2160 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "HttpRequest does not contain a response message");
2163 } end_error_handling();
2166 PHP_METHOD(HttpRequest
, getRequestMessage
)
2168 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2169 if (SUCCESS
== zend_parse_parameters_none()) {
2170 zval
*message
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("requestMessage"), 0 TSRMLS_CC
);
2172 if (Z_TYPE_P(message
) == IS_OBJECT
) {
2173 RETVAL_OBJECT(message
, 1);
2175 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "HttpRequest does not contain a request message");
2178 } end_error_handling();
2181 PHP_METHOD(HttpRequest
, getHistory
)
2183 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2184 if (SUCCESS
== zend_parse_parameters_none()) {
2185 zval
*hist
= zend_read_property(php_http_request_class_entry
, getThis(), ZEND_STRL("history"), 0 TSRMLS_CC
);
2187 if (Z_TYPE_P(hist
) == IS_OBJECT
) {
2188 RETVAL_OBJECT(hist
, 1);
2190 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "The history is empty");
2193 } end_error_handling();
2196 PHP_METHOD(HttpRequest
, clearHistory
)
2198 if (SUCCESS
== zend_parse_parameters_none()) {
2199 zend_update_property_null(php_http_request_class_entry
, getThis(), ZEND_STRL("history") TSRMLS_CC
);
2205 PHP_METHOD(HttpRequest
, getMessageClass
)
2207 if (SUCCESS
== zend_parse_parameters_none()) {
2208 RETURN_PROP(php_http_request_class_entry
, "messageClass");
2213 PHP_METHOD(HttpRequest
, setMessageClass
)
2218 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &cn
, &cl
)) {
2219 zend_update_property_stringl(php_http_request_class_entry
, getThis(), ZEND_STRL("messageClass"), cn
, cl TSRMLS_CC
);
2223 PHP_METHOD(HttpRequest
, send
)
2227 with_error_handling(EH_THROW
, PHP_HTTP_EX_CE(runtime
)) {
2228 if (SUCCESS
== zend_parse_parameters_none()) {
2229 php_http_request_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2232 php_http_error(HE_WARNING
, PHP_HTTP_E_RUNTIME
, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool");
2233 } else if (SUCCESS
== php_http_request_object_requesthandler(obj
, getThis() TSRMLS_CC
)) {
2234 php_http_request_exec(obj
->request
);
2235 if (SUCCESS
== php_http_request_object_responsehandler(obj
, getThis() TSRMLS_CC
)) {
2236 RETVAL_PROP(php_http_request_class_entry
, "responseMessage");
2238 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST
, "Failed to handle response");
2241 php_http_error(HE_WARNING
, PHP_HTTP_E_REQUEST
, "Failed to handle request");
2244 } end_error_handling();
2247 PHP_MINIT_FUNCTION(http_request
)
2249 #ifdef PHP_HTTP_NEED_OPENSSL_TSL
2250 /* mod_ssl, libpq or ext/curl might already have set thread lock callbacks */
2251 if (!CRYPTO_get_id_callback()) {
2252 int i
, c
= CRYPTO_num_locks();
2254 php_http_openssl_tsl
= malloc(c
* sizeof(MUTEX_T
));
2256 for (i
= 0; i
< c
; ++i
) {
2257 php_http_openssl_tsl
[i
] = tsrm_mutex_alloc();
2260 CRYPTO_set_id_callback(php_http_openssl_thread_id
);
2261 CRYPTO_set_locking_callback(php_http_openssl_thread_lock
);
2264 #ifdef PHP_HTTP_NEED_GNUTLS_TSL
2265 gcry_control(GCRYCTL_SET_THREAD_CBS
, &php_http_gnutls_tsl
);
2268 if (CURLE_OK
!= curl_global_init(CURL_GLOBAL_ALL
)) {
2272 if (SUCCESS
!= php_http_persistent_handle_provide(ZEND_STRL("http_request"), safe_curl_init
, safe_curl_dtor
, safe_curl_copy
)) {
2276 PHP_HTTP_REGISTER_CLASS(http
, Request
, http_request
, php_http_object_class_entry
, 0);
2277 php_http_request_class_entry
->create_object
= php_http_request_object_new
;
2278 memcpy(&php_http_request_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
2279 php_http_request_object_handlers
.clone_obj
= php_http_request_object_clone
;
2281 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("options"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2282 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("responseInfo"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2283 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("responseMessage"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2284 zend_declare_property_long(php_http_request_class_entry
, ZEND_STRL("responseCode"), 0, ZEND_ACC_PRIVATE TSRMLS_CC
);
2285 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("responseStatus"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2286 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("requestMessage"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2287 zend_declare_property_long(php_http_request_class_entry
, ZEND_STRL("method"), PHP_HTTP_GET
, ZEND_ACC_PRIVATE TSRMLS_CC
);
2288 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("url"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2289 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("contentType"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2290 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("requestBody"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2291 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("queryData"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2292 zend_declare_property_null(php_http_request_class_entry
, ZEND_STRL("history"), ZEND_ACC_PRIVATE TSRMLS_CC
);
2293 zend_declare_property_bool(php_http_request_class_entry
, ZEND_STRL("recordHistory"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
2294 zend_declare_property_string(php_http_request_class_entry
, ZEND_STRL("messageClass"), "", ZEND_ACC_PRIVATE TSRMLS_CC
);
2297 * HTTP Protocol Version Constants
2299 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_1_0"), CURL_HTTP_VERSION_1_0 TSRMLS_CC
);
2300 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_1_1"), CURL_HTTP_VERSION_1_1 TSRMLS_CC
);
2301 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_NONE"), CURL_HTTP_VERSION_NONE TSRMLS_CC
); /* to be removed */
2302 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("VERSION_ANY"), CURL_HTTP_VERSION_NONE TSRMLS_CC
);
2305 * SSL Version Constants
2307 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_TLSv1"), CURL_SSLVERSION_TLSv1 TSRMLS_CC
);
2308 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_SSLv2"), CURL_SSLVERSION_SSLv2 TSRMLS_CC
);
2309 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_SSLv3"), CURL_SSLVERSION_SSLv3 TSRMLS_CC
);
2310 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("SSL_VERSION_ANY"), CURL_SSLVERSION_DEFAULT TSRMLS_CC
);
2313 * DNS IPvX resolving
2315 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("IPRESOLVE_V4"), CURL_IPRESOLVE_V4 TSRMLS_CC
);
2316 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("IPRESOLVE_V6"), CURL_IPRESOLVE_V6 TSRMLS_CC
);
2317 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("IPRESOLVE_ANY"), CURL_IPRESOLVE_WHATEVER TSRMLS_CC
);
2322 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_BASIC"), CURLAUTH_BASIC TSRMLS_CC
);
2323 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_DIGEST"), CURLAUTH_DIGEST TSRMLS_CC
);
2324 #if PHP_HTTP_CURL_VERSION(7,19,3)
2325 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_DIGEST_IE"), CURLAUTH_DIGEST_IE TSRMLS_CC
);
2327 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_NTLM"), CURLAUTH_NTLM TSRMLS_CC
);
2328 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_GSSNEG"), CURLAUTH_GSSNEGOTIATE TSRMLS_CC
);
2329 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("AUTH_ANY"), CURLAUTH_ANY TSRMLS_CC
);
2332 * Proxy Type Constants
2334 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS4"), CURLPROXY_SOCKS4 TSRMLS_CC
);
2335 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS4A"), CURLPROXY_SOCKS5 TSRMLS_CC
);
2336 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS5_HOSTNAME"), CURLPROXY_SOCKS5 TSRMLS_CC
);
2337 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_SOCKS5"), CURLPROXY_SOCKS5 TSRMLS_CC
);
2338 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_HTTP"), CURLPROXY_HTTP TSRMLS_CC
);
2339 # if PHP_HTTP_CURL_VERSION(7,19,4)
2340 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("PROXY_HTTP_1_0"), CURLPROXY_HTTP_1_0 TSRMLS_CC
);
2344 * Post Redirection Constants
2346 #if PHP_HTTP_CURL_VERSION(7,19,1)
2347 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("POSTREDIR_301"), CURL_REDIR_POST_301 TSRMLS_CC
);
2348 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("POSTREDIR_302"), CURL_REDIR_POST_302 TSRMLS_CC
);
2349 zend_declare_class_constant_long(php_http_request_class_entry
, ZEND_STRL("POSTREDIR_ALL"), CURL_REDIR_POST_ALL TSRMLS_CC
);
2355 PHP_MSHUTDOWN_FUNCTION(http_request
)
2357 curl_global_cleanup();
2358 #ifdef PHP_HTTP_NEED_OPENSSL_TSL
2359 if (php_http_openssl_tsl
) {
2360 int i
, c
= CRYPTO_num_locks();
2362 CRYPTO_set_id_callback(NULL
);
2363 CRYPTO_set_locking_callback(NULL
);
2365 for (i
= 0; i
< c
; ++i
) {
2366 tsrm_mutex_free(php_http_openssl_tsl
[i
]);
2369 free(php_http_openssl_tsl
);
2370 php_http_openssl_tsl
= NULL
;
2381 * vim600: noet sw=4 ts=4 fdm=marker
2382 * vim<600: noet sw=4 ts=4