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-2014, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
13 #include "php_http_api.h"
14 #include "php_http_client.h"
16 #include "ext/spl/spl_observer.h"
19 * array of name => php_http_client_driver_t*
21 static HashTable php_http_client_drivers
;
23 ZEND_RESULT_CODE
php_http_client_driver_add(php_http_client_driver_t
*driver
)
25 return zend_hash_add(&php_http_client_drivers
, driver
->name_str
, driver
->name_len
+ 1, (void *) driver
, sizeof(php_http_client_driver_t
), NULL
);
28 ZEND_RESULT_CODE
php_http_client_driver_get(const char *name_str
, size_t name_len
, php_http_client_driver_t
*driver
)
30 php_http_client_driver_t
*tmp
;
32 if ((name_str
&& SUCCESS
== zend_hash_find(&php_http_client_drivers
, name_str
, name_len
+ 1, (void *) &tmp
))
33 || (SUCCESS
== zend_hash_get_current_data(&php_http_client_drivers
, (void *) &tmp
))) {
40 static int apply_driver_list(void *p
, void *arg TSRMLS_DC
)
42 php_http_client_driver_t
*d
= p
;
46 ZVAL_STRINGL(zname
, d
->name_str
, d
->name_len
, 1);
48 zend_hash_next_index_insert(arg
, &zname
, sizeof(zval
*), NULL
);
49 return ZEND_HASH_APPLY_KEEP
;
52 void php_http_client_driver_list(HashTable
*ht TSRMLS_DC
)
54 zend_hash_apply_with_argument(&php_http_client_drivers
, apply_driver_list
, ht TSRMLS_CC
);
57 void php_http_client_options_set_subr(zval
*this_ptr
, char *key
, size_t len
, zval
*opts
, int overwrite TSRMLS_DC
)
59 if (overwrite
|| (opts
&& zend_hash_num_elements(Z_ARRVAL_P(opts
)))) {
60 zend_class_entry
*this_ce
= Z_OBJCE_P(getThis());
61 zval
*old_opts
, *new_opts
, **entry
= NULL
;
63 MAKE_STD_ZVAL(new_opts
);
65 old_opts
= zend_read_property(this_ce
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
66 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
67 array_copy(Z_ARRVAL_P(old_opts
), Z_ARRVAL_P(new_opts
));
71 if (opts
&& zend_hash_num_elements(Z_ARRVAL_P(opts
))) {
73 zend_symtable_update(Z_ARRVAL_P(new_opts
), key
, len
, (void *) &opts
, sizeof(zval
*), NULL
);
75 zend_symtable_del(Z_ARRVAL_P(new_opts
), key
, len
);
77 } else if (opts
&& zend_hash_num_elements(Z_ARRVAL_P(opts
))) {
78 if (SUCCESS
== zend_symtable_find(Z_ARRVAL_P(new_opts
), key
, len
, (void *) &entry
)) {
79 array_join(Z_ARRVAL_P(opts
), Z_ARRVAL_PP(entry
), 0, 0);
82 zend_symtable_update(Z_ARRVAL_P(new_opts
), key
, len
, (void *) &opts
, sizeof(zval
*), NULL
);
86 zend_update_property(this_ce
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
87 zval_ptr_dtor(&new_opts
);
91 void php_http_client_options_set(zval
*this_ptr
, zval
*opts TSRMLS_DC
)
93 php_http_array_hashkey_t key
= php_http_array_hashkey_init(0);
96 zend_class_entry
*this_ce
= Z_OBJCE_P(getThis());
97 zend_bool is_client
= instanceof_function(this_ce
, php_http_client_class_entry TSRMLS_CC
);
99 MAKE_STD_ZVAL(new_opts
);
100 array_init(new_opts
);
102 if (!opts
|| !zend_hash_num_elements(Z_ARRVAL_P(opts
))) {
103 zend_update_property(this_ce
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
104 zval_ptr_dtor(&new_opts
);
106 zval
*old_opts
, *add_opts
, **opt
;
108 MAKE_STD_ZVAL(add_opts
);
109 array_init(add_opts
);
110 /* some options need extra attention -- thus cannot use array_merge() directly */
111 FOREACH_KEYVAL(pos
, opts
, key
, opt
) {
112 if (key
.type
== HASH_KEY_IS_STRING
) {
113 #define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s))
114 if (Z_TYPE_PP(opt
) == IS_ARRAY
&& (KEYMATCH(key
, "ssl") || KEYMATCH(key
, "cookies"))) {
115 php_http_client_options_set_subr(getThis(), key
.str
, key
.len
, *opt
, 0 TSRMLS_CC
);
116 } else if (is_client
&& (KEYMATCH(key
, "recordHistory") || KEYMATCH(key
, "responseMessageClass"))) {
117 zend_update_property(this_ce
, getThis(), key
.str
, key
.len
-1, *opt TSRMLS_CC
);
118 } else if (Z_TYPE_PP(opt
) == IS_NULL
) {
119 old_opts
= zend_read_property(this_ce
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
120 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
121 zend_symtable_del(Z_ARRVAL_P(old_opts
), key
.str
, key
.len
);
125 add_assoc_zval_ex(add_opts
, key
.str
, key
.len
, *opt
);
130 old_opts
= zend_read_property(this_ce
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
131 if (Z_TYPE_P(old_opts
) == IS_ARRAY
) {
132 array_copy(Z_ARRVAL_P(old_opts
), Z_ARRVAL_P(new_opts
));
134 array_join(Z_ARRVAL_P(add_opts
), Z_ARRVAL_P(new_opts
), 0, 0);
135 zend_update_property(this_ce
, getThis(), ZEND_STRL("options"), new_opts TSRMLS_CC
);
136 zval_ptr_dtor(&new_opts
);
137 zval_ptr_dtor(&add_opts
);
141 void php_http_client_options_get_subr(zval
*this_ptr
, char *key
, size_t len
, zval
*return_value TSRMLS_DC
)
143 zend_class_entry
*this_ce
= Z_OBJCE_P(getThis());
144 zval
**options
, *opts
= zend_read_property(this_ce
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
146 if ((Z_TYPE_P(opts
) == IS_ARRAY
) && (SUCCESS
== zend_symtable_find(Z_ARRVAL_P(opts
), key
, len
, (void *) &options
))) {
147 RETVAL_ZVAL(*options
, 1, 0);
151 static void queue_dtor(void *enqueued
)
153 php_http_client_enqueue_t
*e
= enqueued
;
160 php_http_client_t
*php_http_client_init(php_http_client_t
*h
, php_http_client_ops_t
*ops
, php_resource_factory_t
*rf
, void *init_arg TSRMLS_DC
)
162 php_http_client_t
*free_h
= NULL
;
165 free_h
= h
= emalloc(sizeof(*h
));
167 memset(h
, 0, sizeof(*h
));
172 } else if (ops
->rsrc
) {
173 h
->rf
= php_resource_factory_init(NULL
, h
->ops
->rsrc
, h
, NULL
);
175 zend_llist_init(&h
->requests
, sizeof(php_http_client_enqueue_t
), queue_dtor
, 0);
176 zend_llist_init(&h
->responses
, sizeof(void *), NULL
, 0);
177 TSRMLS_SET_CTX(h
->ts
);
180 if (!(h
= h
->ops
->init(h
, init_arg
))) {
181 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not initialize client");
191 php_http_client_t
*php_http_client_copy(php_http_client_t
*from
, php_http_client_t
*to
)
193 if (from
->ops
->copy
) {
194 return from
->ops
->copy(from
, to
);
200 void php_http_client_dtor(php_http_client_t
*h
)
202 php_http_client_reset(h
);
207 h
->callback
.debug
.func
= NULL
;
208 h
->callback
.debug
.arg
= NULL
;
210 php_resource_factory_free(&h
->rf
);
213 void php_http_client_free(php_http_client_t
**h
) {
215 php_http_client_dtor(*h
);
221 ZEND_RESULT_CODE
php_http_client_enqueue(php_http_client_t
*h
, php_http_client_enqueue_t
*enqueue
)
223 TSRMLS_FETCH_FROM_CTX(h
->ts
);
225 if (h
->ops
->enqueue
) {
226 if (php_http_client_enqueued(h
, enqueue
->request
, NULL
)) {
227 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to enqueue request; request already in queue");
230 return h
->ops
->enqueue(h
, enqueue
);
236 ZEND_RESULT_CODE
php_http_client_dequeue(php_http_client_t
*h
, php_http_message_t
*request
)
238 TSRMLS_FETCH_FROM_CTX(h
->ts
);
240 if (h
->ops
->dequeue
) {
241 php_http_client_enqueue_t
*enqueue
= php_http_client_enqueued(h
, request
, NULL
);
244 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to dequeue request; request not in queue");
247 return h
->ops
->dequeue(h
, enqueue
);
252 php_http_client_enqueue_t
*php_http_client_enqueued(php_http_client_t
*h
, void *compare_arg
, php_http_client_enqueue_cmp_func_t compare_func
)
254 zend_llist_element
*el
= NULL
;
257 for (el
= h
->requests
.head
; el
; el
= el
->next
) {
258 if (compare_func((php_http_client_enqueue_t
*) el
->data
, compare_arg
)) {
263 for (el
= h
->requests
.head
; el
; el
= el
->next
) {
264 if (((php_http_client_enqueue_t
*) el
->data
)->request
== compare_arg
) {
269 return el
? (php_http_client_enqueue_t
*) el
->data
: NULL
;
272 ZEND_RESULT_CODE
php_http_client_wait(php_http_client_t
*h
, struct timeval
*custom_timeout
)
275 return h
->ops
->wait(h
, custom_timeout
);
281 int php_http_client_once(php_http_client_t
*h
)
284 return h
->ops
->once(h
);
290 ZEND_RESULT_CODE
php_http_client_exec(php_http_client_t
*h
)
293 return h
->ops
->exec(h
);
299 void php_http_client_reset(php_http_client_t
*h
)
305 zend_llist_clean(&h
->requests
);
306 zend_llist_clean(&h
->responses
);
309 ZEND_RESULT_CODE
php_http_client_setopt(php_http_client_t
*h
, php_http_client_setopt_opt_t opt
, void *arg
)
311 if (h
->ops
->setopt
) {
312 return h
->ops
->setopt(h
, opt
, arg
);
318 ZEND_RESULT_CODE
php_http_client_getopt(php_http_client_t
*h
, php_http_client_getopt_opt_t opt
, void *arg
, void *res_ptr
)
320 if (h
->ops
->getopt
) {
321 return h
->ops
->getopt(h
, opt
, arg
, res_ptr
);
326 zend_class_entry
*php_http_client_class_entry
;
327 static zend_object_handlers php_http_client_object_handlers
;
329 void php_http_client_object_free(void *object TSRMLS_DC
)
331 php_http_client_object_t
*o
= (php_http_client_object_t
*) object
;
333 php_http_client_free(&o
->client
);
334 if (o
->debug
.fci
.size
> 0) {
335 zend_fcall_info_args_clear(&o
->debug
.fci
, 1);
336 zval_ptr_dtor(&o
->debug
.fci
.function_name
);
337 o
->debug
.fci
.size
= 0;
339 php_http_object_method_dtor(&o
->notify
);
340 php_http_object_method_free(&o
->update
);
341 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
345 zend_object_value
php_http_client_object_new_ex(zend_class_entry
*ce
, php_http_client_t
*client
, php_http_client_object_t
**ptr TSRMLS_DC
)
347 php_http_client_object_t
*o
;
349 o
= ecalloc(1, sizeof(php_http_client_object_t
));
350 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
351 object_properties_init((zend_object
*) o
, ce
);
359 o
->zv
.handle
= zend_objects_store_put(o
, NULL
, php_http_client_object_free
, NULL TSRMLS_CC
);
360 o
->zv
.handlers
= &php_http_client_object_handlers
;
365 zend_object_value
php_http_client_object_new(zend_class_entry
*ce TSRMLS_DC
)
367 return php_http_client_object_new_ex(ce
, NULL
, NULL TSRMLS_CC
);
370 static void handle_history(zval
*zclient
, php_http_message_t
*request
, php_http_message_t
*response TSRMLS_DC
)
372 zval
*new_hist
, *old_hist
= zend_read_property(php_http_client_class_entry
, zclient
, ZEND_STRL("history"), 0 TSRMLS_CC
);
373 php_http_message_t
*zipped
= php_http_message_zip(response
, request
);
374 zend_object_value ov
= php_http_message_object_new_ex(php_http_message_class_entry
, zipped
, NULL TSRMLS_CC
);
376 MAKE_STD_ZVAL(new_hist
);
377 ZVAL_OBJVAL(new_hist
, ov
, 0);
379 if (Z_TYPE_P(old_hist
) == IS_OBJECT
) {
380 php_http_message_object_prepend(new_hist
, old_hist
, 1 TSRMLS_CC
);
383 zend_update_property(php_http_client_class_entry
, zclient
, ZEND_STRL("history"), new_hist TSRMLS_CC
);
384 zval_ptr_dtor(&new_hist
);
387 static ZEND_RESULT_CODE
handle_response(void *arg
, php_http_client_t
*client
, php_http_client_enqueue_t
*e
, php_http_message_t
**response
)
389 zend_bool dequeue
= 0;
391 php_http_message_t
*msg
;
392 php_http_client_progress_state_t
*progress
;
393 TSRMLS_FETCH_FROM_CTX(client
->ts
);
395 INIT_PZVAL(&zclient
);
396 ZVAL_OBJVAL(&zclient
, ((php_http_client_object_t
*) arg
)->zv
, 0);
398 if ((msg
= *response
)) {
399 php_http_message_object_t
*msg_obj
;
400 zval
*info
, *zresponse
, *zrequest
;
403 /* ensure the message is of type response (could be uninitialized in case of early error, like DNS) */
404 php_http_message_set_type(msg
, PHP_HTTP_RESPONSE
);
406 if (z_is_true(zend_read_property(php_http_client_class_entry
, &zclient
, ZEND_STRL("recordHistory"), 0 TSRMLS_CC
))) {
407 handle_history(&zclient
, e
->request
, *response TSRMLS_CC
);
410 /* hard detach, redirects etc. are in the history */
411 php_http_message_free(&msg
->parent
);
414 MAKE_STD_ZVAL(zresponse
);
415 ZVAL_OBJVAL(zresponse
, php_http_message_object_new_ex(php_http_client_response_class_entry
, msg
, &msg_obj TSRMLS_CC
), 0);
417 MAKE_STD_ZVAL(zrequest
);
418 ZVAL_OBJVAL(zrequest
, ((php_http_message_object_t
*) e
->opaque
)->zv
, 1);
420 php_http_message_object_prepend(zresponse
, zrequest
, 1 TSRMLS_CC
);
424 info_ht
= HASH_OF(info
);
425 php_http_client_getopt(client
, PHP_HTTP_CLIENT_OPT_TRANSFER_INFO
, e
->request
, &info_ht
);
426 zend_update_property(php_http_client_response_class_entry
, zresponse
, ZEND_STRL("transferInfo"), info TSRMLS_CC
);
427 zval_ptr_dtor(&info
);
429 zend_objects_store_add_ref_by_handle(msg_obj
->zv
.handle TSRMLS_CC
);
430 zend_llist_add_element(&client
->responses
, &msg_obj
);
432 if (e
->closure
.fci
.size
) {
434 zend_error_handling zeh
;
436 zend_fcall_info_argn(&e
->closure
.fci TSRMLS_CC
, 1, &zresponse
);
437 zend_replace_error_handling(EH_NORMAL
, NULL
, &zeh TSRMLS_CC
);
438 ++client
->callback
.depth
;
439 zend_fcall_info_call(&e
->closure
.fci
, &e
->closure
.fcc
, &retval
, NULL TSRMLS_CC
);
440 --client
->callback
.depth
;
441 zend_restore_error_handling(&zeh TSRMLS_CC
);
442 zend_fcall_info_argn(&e
->closure
.fci TSRMLS_CC
, 0);
445 if (Z_TYPE_P(retval
) == IS_BOOL
) {
446 dequeue
= Z_BVAL_P(retval
);
448 zval_ptr_dtor(&retval
);
452 zval_ptr_dtor(&zresponse
);
453 zval_ptr_dtor(&zrequest
);
456 if (SUCCESS
== php_http_client_getopt(client
, PHP_HTTP_CLIENT_OPT_PROGRESS_INFO
, e
->request
, &progress
)) {
457 progress
->info
= "finished";
458 progress
->finished
= 1;
459 client
->callback
.progress
.func(client
->callback
.progress
.arg
, client
, e
, progress
);
463 php_http_client_dequeue(client
, e
->request
);
469 static void handle_progress(void *arg
, php_http_client_t
*client
, php_http_client_enqueue_t
*e
, php_http_client_progress_state_t
*progress
)
471 zval
*zrequest
, *zprogress
, *zclient
, **args
[2];
472 php_http_client_object_t
*client_obj
= arg
;
473 zend_error_handling zeh
;
474 TSRMLS_FETCH_FROM_CTX(client
->ts
);
476 MAKE_STD_ZVAL(zclient
);
477 ZVAL_OBJVAL(zclient
, client_obj
->zv
, 1);
479 MAKE_STD_ZVAL(zrequest
);
480 ZVAL_OBJVAL(zrequest
, ((php_http_message_object_t
*) e
->opaque
)->zv
, 1);
483 MAKE_STD_ZVAL(zprogress
);
484 object_init(zprogress
);
485 add_property_bool(zprogress
, "started", progress
->started
);
486 add_property_bool(zprogress
, "finished", progress
->finished
);
487 add_property_string(zprogress
, "info", STR_PTR(progress
->info
), 1);
488 add_property_double(zprogress
, "dltotal", progress
->dl
.total
);
489 add_property_double(zprogress
, "dlnow", progress
->dl
.now
);
490 add_property_double(zprogress
, "ultotal", progress
->ul
.total
);
491 add_property_double(zprogress
, "ulnow", progress
->ul
.now
);
492 args
[1] = &zprogress
;
494 zend_replace_error_handling(EH_NORMAL
, NULL
, &zeh TSRMLS_CC
);
495 ++client
->callback
.depth
;
496 php_http_object_method_call(&client_obj
->notify
, zclient
, NULL
, 2, args TSRMLS_CC
);
497 --client
->callback
.depth
;
498 zend_restore_error_handling(&zeh TSRMLS_CC
);
500 zval_ptr_dtor(&zclient
);
501 zval_ptr_dtor(&zrequest
);
502 zval_ptr_dtor(&zprogress
);
505 static void handle_debug(void *arg
, php_http_client_t
*client
, php_http_client_enqueue_t
*e
, unsigned type
, const char *data
, size_t size
)
507 zval
*ztype
, *zdata
, *zreq
, *zclient
;
508 php_http_client_object_t
*client_obj
= arg
;
509 zend_error_handling zeh
;
510 TSRMLS_FETCH_FROM_CTX(client
->ts
);
512 MAKE_STD_ZVAL(zclient
);
513 ZVAL_OBJVAL(zclient
, client_obj
->zv
, 1);
515 ZVAL_OBJVAL(zreq
, ((php_http_message_object_t
*) e
->opaque
)->zv
, 1);
516 MAKE_STD_ZVAL(ztype
);
517 ZVAL_LONG(ztype
, type
);
518 MAKE_STD_ZVAL(zdata
);
519 ZVAL_STRINGL(zdata
, data
, size
, 1);
521 zend_replace_error_handling(EH_NORMAL
, NULL
, &zeh TSRMLS_CC
);
522 if (SUCCESS
== zend_fcall_info_argn(&client_obj
->debug
.fci TSRMLS_CC
, 4, &zclient
, &zreq
, &ztype
, &zdata
)) {
523 ++client_obj
->client
->callback
.depth
;
524 zend_fcall_info_call(&client_obj
->debug
.fci
, &client_obj
->debug
.fcc
, NULL
, NULL TSRMLS_CC
);
525 --client_obj
->client
->callback
.depth
;
526 zend_fcall_info_args_clear(&client_obj
->debug
.fci
, 0);
528 zend_restore_error_handling(&zeh TSRMLS_CC
);
530 zval_ptr_dtor(&zclient
);
531 zval_ptr_dtor(&zreq
);
532 zval_ptr_dtor(&ztype
);
533 zval_ptr_dtor(&zdata
);
536 static void response_dtor(void *data
)
538 php_http_message_object_t
*msg_obj
= *(php_http_message_object_t
**) data
;
539 TSRMLS_FETCH_FROM_CTX(msg_obj
->message
->ts
);
541 zend_objects_store_del_ref_by_handle_ex(msg_obj
->zv
.handle
, msg_obj
->zv
.handlers TSRMLS_CC
);
544 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_construct
, 0, 0, 0)
545 ZEND_ARG_INFO(0, driver
)
546 ZEND_ARG_INFO(0, persistent_handle_id
)
548 static PHP_METHOD(HttpClient
, __construct
)
550 char *driver_str
= NULL
, *persistent_handle_str
= NULL
;
551 int driver_len
= 0, persistent_handle_len
= 0;
552 php_http_client_driver_t driver
;
553 php_resource_factory_t
*rf
= NULL
;
554 php_http_client_object_t
*obj
;
557 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|ss", &driver_str
, &driver_len
, &persistent_handle_str
, &persistent_handle_len
), invalid_arg
, return);
559 if (SUCCESS
!= php_http_client_driver_get(driver_str
, driver_len
, &driver
)) {
560 php_http_throw(unexpected_val
, "Failed to locate \"%s\" client request handler", driver_str
);
565 object_init_ex(os
, spl_ce_SplObjectStorage
);
566 zend_update_property(php_http_client_class_entry
, getThis(), ZEND_STRL("observers"), os TSRMLS_CC
);
569 if (persistent_handle_len
) {
572 php_persistent_handle_factory_t
*pf
;
574 name_len
= spprintf(&name_str
, 0, "http\\Client\\%s", driver
.name_str
);
575 php_http_pretty_key(name_str
+ sizeof("http\\Client"), driver
.name_len
, 1, 1);
577 if ((pf
= php_persistent_handle_concede(NULL
, name_str
, name_len
, persistent_handle_str
, persistent_handle_len
, NULL
, NULL TSRMLS_CC
))) {
578 rf
= php_persistent_handle_resource_factory_init(NULL
, pf
);
584 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
586 php_http_expect(obj
->client
= php_http_client_init(NULL
, driver
.client_ops
, rf
, NULL TSRMLS_CC
), runtime
, return);
588 php_http_object_method_init(&obj
->notify
, getThis(), ZEND_STRL("notify") TSRMLS_CC
);
590 obj
->client
->callback
.response
.func
= handle_response
;
591 obj
->client
->callback
.response
.arg
= obj
;
592 obj
->client
->callback
.progress
.func
= handle_progress
;
593 obj
->client
->callback
.progress
.arg
= obj
;
595 obj
->client
->responses
.dtor
= response_dtor
;
598 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_reset
, 0, 0, 0)
600 static PHP_METHOD(HttpClient
, reset
)
602 php_http_client_object_t
*obj
;
603 php_http_expect(SUCCESS
== zend_parse_parameters_none(), invalid_arg
, return);
605 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
608 php_http_client_reset(obj
->client
);
610 RETVAL_ZVAL(getThis(), 1, 0);
613 static HashTable
*combined_options(zval
*client
, zval
*request TSRMLS_DC
)
617 zval
*z_roptions
= NULL
, *z_coptions
= zend_read_property(php_http_client_class_entry
, client
, ZEND_STRL("options"), 0 TSRMLS_CC
);
619 if (Z_TYPE_P(z_coptions
) == IS_ARRAY
) {
620 num_options
= zend_hash_num_elements(Z_ARRVAL_P(z_coptions
));
622 zend_call_method_with_0_params(&request
, NULL
, NULL
, "getOptions", &z_roptions
);
623 if (z_roptions
&& Z_TYPE_P(z_roptions
) == IS_ARRAY
) {
624 int num
= zend_hash_num_elements(Z_ARRVAL_P(z_roptions
));
625 if (num
> num_options
) {
629 ALLOC_HASHTABLE(options
);
630 ZEND_INIT_SYMTABLE_EX(options
, num_options
, 0);
631 if (Z_TYPE_P(z_coptions
) == IS_ARRAY
) {
632 array_copy(Z_ARRVAL_P(z_coptions
), options
);
635 if (Z_TYPE_P(z_roptions
) == IS_ARRAY
) {
636 array_join(Z_ARRVAL_P(z_roptions
), options
, 0, 0);
638 zval_ptr_dtor(&z_roptions
);
643 static void msg_queue_dtor(php_http_client_enqueue_t
*e
)
645 php_http_message_object_t
*msg_obj
= e
->opaque
;
646 TSRMLS_FETCH_FROM_CTX(msg_obj
->message
->ts
);
648 zend_objects_store_del_ref_by_handle_ex(msg_obj
->zv
.handle
, msg_obj
->zv
.handlers TSRMLS_CC
);
649 zend_hash_destroy(e
->options
);
650 FREE_HASHTABLE(e
->options
);
652 if (e
->closure
.fci
.size
) {
653 zval_ptr_dtor(&e
->closure
.fci
.function_name
);
654 if (e
->closure
.fci
.object_ptr
) {
655 zval_ptr_dtor(&e
->closure
.fci
.object_ptr
);
660 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enqueue
, 0, 0, 1)
661 ZEND_ARG_OBJ_INFO(0, request
, http
\\Client
\\Request
, 0)
662 ZEND_ARG_INFO(0, callable
)
664 static PHP_METHOD(HttpClient
, enqueue
)
667 zend_fcall_info fci
= empty_fcall_info
;
668 zend_fcall_info_cache fcc
= empty_fcall_info_cache
;
669 php_http_client_object_t
*obj
;
670 php_http_message_object_t
*msg_obj
;
671 php_http_client_enqueue_t q
;
673 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O|f", &request
, php_http_client_request_class_entry
, &fci
, &fcc
), invalid_arg
, return);
675 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
676 msg_obj
= zend_object_store_get_object(request TSRMLS_CC
);
678 if (php_http_client_enqueued(obj
->client
, msg_obj
->message
, NULL
)) {
679 php_http_throw(bad_method_call
, "Failed to enqueue request; request already in queue", NULL
);
683 q
.request
= msg_obj
->message
;
684 q
.options
= combined_options(getThis(), request TSRMLS_CC
);
685 q
.dtor
= msg_queue_dtor
;
691 Z_ADDREF_P(fci
.function_name
);
692 if (fci
.object_ptr
) {
693 Z_ADDREF_P(fci
.object_ptr
);
697 zend_objects_store_add_ref_by_handle(msg_obj
->zv
.handle TSRMLS_CC
);
699 php_http_expect(SUCCESS
== php_http_client_enqueue(obj
->client
, &q
), runtime
,
704 RETVAL_ZVAL(getThis(), 1, 0);
707 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_dequeue
, 0, 0, 1)
708 ZEND_ARG_OBJ_INFO(0, request
, http
\\Client
\\Request
, 0)
710 static PHP_METHOD(HttpClient
, dequeue
)
713 php_http_client_object_t
*obj
;
714 php_http_message_object_t
*msg_obj
;
716 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &request
, php_http_client_request_class_entry
), invalid_arg
, return);
718 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
719 msg_obj
= zend_object_store_get_object(request TSRMLS_CC
);
721 if (!php_http_client_enqueued(obj
->client
, msg_obj
->message
, NULL
)) {
722 php_http_throw(bad_method_call
, "Failed to dequeue request; request not in queue", NULL
);
726 php_http_expect(SUCCESS
== php_http_client_dequeue(obj
->client
, msg_obj
->message
), runtime
, return);
728 RETVAL_ZVAL(getThis(), 1, 0);
731 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_requeue
, 0, 0, 1)
732 ZEND_ARG_OBJ_INFO(0, request
, http
\\Client
\\Request
, 0)
733 ZEND_ARG_INFO(0, callable
)
735 static PHP_METHOD(HttpClient
, requeue
)
738 zend_fcall_info fci
= empty_fcall_info
;
739 zend_fcall_info_cache fcc
= empty_fcall_info_cache
;
740 php_http_client_object_t
*obj
;
741 php_http_message_object_t
*msg_obj
;
742 php_http_client_enqueue_t q
;
744 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O|f", &request
, php_http_client_request_class_entry
, &fci
, &fcc
), invalid_arg
, return);
746 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
747 msg_obj
= zend_object_store_get_object(request TSRMLS_CC
);
749 if (php_http_client_enqueued(obj
->client
, msg_obj
->message
, NULL
)) {
750 php_http_expect(SUCCESS
== php_http_client_dequeue(obj
->client
, msg_obj
->message
), runtime
, return);
753 q
.request
= msg_obj
->message
;
754 q
.options
= combined_options(getThis(), request TSRMLS_CC
);
755 q
.dtor
= msg_queue_dtor
;
761 Z_ADDREF_P(fci
.function_name
);
762 if (fci
.object_ptr
) {
763 Z_ADDREF_P(fci
.object_ptr
);
767 zend_objects_store_add_ref_by_handle(msg_obj
->zv
.handle TSRMLS_CC
);
769 php_http_expect(SUCCESS
== php_http_client_enqueue(obj
->client
, &q
), runtime
,
774 RETVAL_ZVAL(getThis(), 1, 0);
777 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_count
, 0, 0, 0)
779 static PHP_METHOD(HttpClient
, count
)
781 long count_mode
= -1;
783 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &count_mode
)) {
784 php_http_client_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
786 RETVAL_LONG(zend_llist_count(&obj
->client
->requests
));
790 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getResponse
, 0, 0, 0)
791 ZEND_ARG_OBJ_INFO(0, request
, http
\\Client
\\Request
, 1)
793 static PHP_METHOD(HttpClient
, getResponse
)
795 zval
*zrequest
= NULL
;
796 php_http_client_object_t
*obj
;
798 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|O", &zrequest
, php_http_client_request_class_entry
), invalid_arg
, return);
800 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
803 /* lookup the response with the request */
804 zend_llist_element
*el
= NULL
;
805 php_http_message_object_t
*req_obj
= zend_object_store_get_object(zrequest TSRMLS_CC
);
807 for (el
= obj
->client
->responses
.head
; el
; el
= el
->next
) {
808 php_http_message_object_t
*response_obj
= *(php_http_message_object_t
**) el
->data
;
810 if (response_obj
->message
->parent
== req_obj
->message
) {
811 RETURN_OBJVAL(response_obj
->zv
, 1);
815 /* not found for the request! */
816 php_http_throw(unexpected_val
, "Could not find response for the request", NULL
);
820 /* pop off the last response */
821 if (obj
->client
->responses
.tail
) {
822 php_http_message_object_t
*response_obj
= *(php_http_message_object_t
**) obj
->client
->responses
.tail
->data
;
826 RETVAL_OBJVAL(response_obj
->zv
, 1);
827 zend_llist_remove_tail(&obj
->client
->responses
);
832 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getHistory
, 0, 0, 0)
834 static PHP_METHOD(HttpClient
, getHistory
)
838 php_http_expect(SUCCESS
== zend_parse_parameters_none(), invalid_arg
, return);
840 zhistory
= zend_read_property(php_http_client_class_entry
, getThis(), ZEND_STRL("history"), 0 TSRMLS_CC
);
841 RETVAL_ZVAL(zhistory
, 1, 0);
844 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_send
, 0, 0, 0)
846 static PHP_METHOD(HttpClient
, send
)
848 php_http_client_object_t
*obj
;
850 php_http_expect(SUCCESS
== zend_parse_parameters_none(), invalid_arg
, return);
852 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
854 php_http_expect(SUCCESS
== php_http_client_exec(obj
->client
), runtime
, return);
856 RETVAL_ZVAL(getThis(), 1, 0);
859 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_once
, 0, 0, 0)
861 static PHP_METHOD(HttpClient
, once
)
863 if (SUCCESS
== zend_parse_parameters_none()) {
864 php_http_client_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
866 RETURN_BOOL(0 < php_http_client_once(obj
->client
));
870 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_wait
, 0, 0, 0)
871 ZEND_ARG_INFO(0, timeout
)
873 static PHP_METHOD(HttpClient
, wait
)
877 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|d", &timeout
)) {
878 struct timeval timeout_val
;
879 php_http_client_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
881 timeout_val
.tv_sec
= (time_t) timeout
;
882 timeout_val
.tv_usec
= PHP_HTTP_USEC(timeout
) % PHP_HTTP_MCROSEC
;
884 RETURN_BOOL(SUCCESS
== php_http_client_wait(obj
->client
, timeout
> 0 ? &timeout_val
: NULL
));
888 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_configure
, 0, 0, 1)
889 ZEND_ARG_ARRAY_INFO(0, settings
, 1)
891 static PHP_METHOD(HttpClient
, configure
)
893 HashTable
*settings
= NULL
;
894 php_http_client_object_t
*obj
;
896 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|H!", &settings
), invalid_arg
, return);
897 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
899 php_http_expect(SUCCESS
== php_http_client_setopt(obj
->client
, PHP_HTTP_CLIENT_OPT_CONFIGURATION
, settings
), unexpected_val
, return);
901 RETVAL_ZVAL(getThis(), 1, 0);
904 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enablePipelining
, 0, 0, 0)
905 ZEND_ARG_INFO(0, enable
)
907 static PHP_METHOD(HttpClient
, enablePipelining
)
909 zend_bool enable
= 1;
910 php_http_client_object_t
*obj
;
912 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|b", &enable
), invalid_arg
, return);
914 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
916 php_http_expect(SUCCESS
== php_http_client_setopt(obj
->client
, PHP_HTTP_CLIENT_OPT_ENABLE_PIPELINING
, &enable
), unexpected_val
, return);
918 RETVAL_ZVAL(getThis(), 1, 0);
921 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enableEvents
, 0, 0, 0)
922 ZEND_ARG_INFO(0, enable
)
924 static PHP_METHOD(HttpClient
, enableEvents
)
926 zend_bool enable
= 1;
927 php_http_client_object_t
*obj
;
929 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|b", &enable
), invalid_arg
, return);
931 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
933 php_http_expect(SUCCESS
== php_http_client_setopt(obj
->client
, PHP_HTTP_CLIENT_OPT_USE_EVENTS
, &enable
), unexpected_val
, return);
935 RETVAL_ZVAL(getThis(), 1, 0);
939 php_http_object_method_t
*cb
;
944 static int notify(zend_object_iterator
*iter
, void *puser TSRMLS_DC
)
946 zval
**observer
= NULL
;
947 struct notify_arg
*arg
= puser
;
949 iter
->funcs
->get_current_data(iter
, &observer TSRMLS_CC
);
951 return php_http_object_method_call(arg
->cb
, *observer
, NULL
, arg
->argc
, arg
->args TSRMLS_CC
);
956 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_notify
, 0, 0, 0)
957 ZEND_ARG_OBJ_INFO(0, request
, http
\\Client
\\Request
, 1)
959 static PHP_METHOD(HttpClient
, notify
)
961 zval
*request
= NULL
, *zprogress
= NULL
, *observers
;
962 php_http_client_object_t
*client_obj
;
963 struct notify_arg arg
= {NULL
};
965 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|O!o!", &request
, php_http_client_request_class_entry
, &zprogress
), invalid_arg
, return);
967 client_obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
968 observers
= zend_read_property(php_http_client_class_entry
, getThis(), ZEND_STRL("observers"), 0 TSRMLS_CC
);
970 if (Z_TYPE_P(observers
) != IS_OBJECT
) {
971 php_http_throw(unexpected_val
, "Observer storage is corrupted", NULL
);
975 if (client_obj
->update
) {
976 arg
.cb
= client_obj
->update
;
978 Z_ADDREF_P(getThis());
979 arg
.args
[0] = &getThis();
984 arg
.args
[1] = &request
;
989 Z_ADDREF_P(zprogress
);
990 arg
.args
[2] = &zprogress
;
994 spl_iterator_apply(observers
, notify
, &arg TSRMLS_CC
);
996 zval_ptr_dtor(&getThis());
998 zval_ptr_dtor(&request
);
1001 zval_ptr_dtor(&zprogress
);
1005 RETVAL_ZVAL(getThis(), 1, 0);
1008 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_attach
, 0, 0, 1)
1009 ZEND_ARG_OBJ_INFO(0, observer
, SplObserver
, 0)
1010 ZEND_END_ARG_INFO();
1011 static PHP_METHOD(HttpClient
, attach
)
1013 zval
*observers
, *observer
, *retval
= NULL
;
1014 php_http_client_object_t
*client_obj
;
1016 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &observer
, spl_ce_SplObserver
), invalid_arg
, return);
1018 client_obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1019 observers
= zend_read_property(php_http_client_class_entry
, getThis(), ZEND_STRL("observers"), 0 TSRMLS_CC
);
1021 if (Z_TYPE_P(observers
) != IS_OBJECT
) {
1022 php_http_throw(unexpected_val
, "Observer storage is corrupted", NULL
);
1026 if (!client_obj
->update
) {
1027 client_obj
->update
= php_http_object_method_init(NULL
, observer
, ZEND_STRL("update") TSRMLS_CC
);
1030 zend_call_method_with_1_params(&observers
, NULL
, NULL
, "attach", &retval
, observer
);
1032 zval_ptr_dtor(&retval
);
1035 RETVAL_ZVAL(getThis(), 1, 0);
1038 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_detach
, 0, 0, 1)
1039 ZEND_ARG_OBJ_INFO(0, observer
, SplObserver
, 0)
1040 ZEND_END_ARG_INFO();
1041 static PHP_METHOD(HttpClient
, detach
)
1043 zval
*observers
, *observer
, *retval
= NULL
;
1045 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &observer
, spl_ce_SplObserver
), invalid_arg
, return);
1047 observers
= zend_read_property(php_http_client_class_entry
, getThis(), ZEND_STRL("observers"), 0 TSRMLS_CC
);
1049 if (Z_TYPE_P(observers
) != IS_OBJECT
) {
1050 php_http_throw(unexpected_val
, "Observer storage is corrupted", NULL
);
1054 zend_call_method_with_1_params(&observers
, NULL
, NULL
, "detach", &retval
, observer
);
1056 zval_ptr_dtor(&retval
);
1059 RETVAL_ZVAL(getThis(), 1, 0);
1062 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getObservers
, 0, 0, 0)
1063 ZEND_END_ARG_INFO();
1064 static PHP_METHOD(HttpClient
, getObservers
)
1068 php_http_expect(SUCCESS
== zend_parse_parameters_none(), invalid_arg
, return);
1070 observers
= zend_read_property(php_http_client_class_entry
, getThis(), ZEND_STRL("observers"), 0 TSRMLS_CC
);
1072 if (Z_TYPE_P(observers
) != IS_OBJECT
) {
1073 php_http_throw(unexpected_val
, "Observer storage is corrupted", NULL
);
1077 RETVAL_ZVAL(observers
, 1, 0);
1080 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getProgressInfo
, 0, 0, 1)
1081 ZEND_ARG_OBJ_INFO(0, request
, http
\\Client
\\Request
, 0)
1082 ZEND_END_ARG_INFO();
1083 static PHP_METHOD(HttpClient
, getProgressInfo
)
1086 php_http_client_object_t
*obj
;
1087 php_http_message_object_t
*req_obj
;
1088 php_http_client_progress_state_t
*progress
;
1090 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &request
, php_http_client_request_class_entry
), invalid_arg
, return);
1092 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1093 req_obj
= zend_object_store_get_object(request TSRMLS_CC
);
1095 php_http_expect(SUCCESS
== php_http_client_getopt(obj
->client
, PHP_HTTP_CLIENT_OPT_PROGRESS_INFO
, req_obj
->message
, &progress
), unexpected_val
, return);
1097 object_init(return_value
);
1098 add_property_bool(return_value
, "started", progress
->started
);
1099 add_property_bool(return_value
, "finished", progress
->finished
);
1100 add_property_string(return_value
, "info", STR_PTR(progress
->info
), 1);
1101 add_property_double(return_value
, "dltotal", progress
->dl
.total
);
1102 add_property_double(return_value
, "dlnow", progress
->dl
.now
);
1103 add_property_double(return_value
, "ultotal", progress
->ul
.total
);
1104 add_property_double(return_value
, "ulnow", progress
->ul
.now
);
1107 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getTransferInfo
, 0, 0, 1)
1108 ZEND_ARG_OBJ_INFO(0, request
, http
\\Client
\\Request
, 0)
1109 ZEND_END_ARG_INFO();
1110 static PHP_METHOD(HttpClient
, getTransferInfo
)
1114 php_http_client_object_t
*obj
;
1115 php_http_message_object_t
*req_obj
;
1117 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &request
, php_http_client_request_class_entry
), invalid_arg
, return);
1119 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1120 req_obj
= zend_object_store_get_object(request TSRMLS_CC
);
1122 object_init(return_value
);
1123 info
= HASH_OF(return_value
);
1124 php_http_expect(SUCCESS
== php_http_client_getopt(obj
->client
, PHP_HTTP_CLIENT_OPT_TRANSFER_INFO
, req_obj
->message
, &info
), unexpected_val
, return);
1127 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_setOptions
, 0, 0, 0)
1128 ZEND_ARG_ARRAY_INFO(0, options
, 1)
1129 ZEND_END_ARG_INFO();
1130 static PHP_METHOD(HttpClient
, setOptions
)
1134 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a!/", &opts
), invalid_arg
, return);
1136 php_http_client_options_set(getThis(), opts TSRMLS_CC
);
1138 RETVAL_ZVAL(getThis(), 1, 0);
1141 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getOptions
, 0, 0, 0)
1142 ZEND_END_ARG_INFO();
1143 static PHP_METHOD(HttpClient
, getOptions
)
1145 if (SUCCESS
== zend_parse_parameters_none()) {
1146 zval
*options
= zend_read_property(php_http_client_class_entry
, getThis(), ZEND_STRL("options"), 0 TSRMLS_CC
);
1147 RETVAL_ZVAL(options
, 1, 0);
1151 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_setSslOptions
, 0, 0, 0)
1152 ZEND_ARG_ARRAY_INFO(0, ssl_option
, 1)
1153 ZEND_END_ARG_INFO();
1154 static PHP_METHOD(HttpClient
, setSslOptions
)
1158 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a!/", &opts
), invalid_arg
, return);
1160 php_http_client_options_set_subr(getThis(), ZEND_STRS("ssl"), opts
, 1 TSRMLS_CC
);
1162 RETVAL_ZVAL(getThis(), 1, 0);
1165 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_addSslOptions
, 0, 0, 0)
1166 ZEND_ARG_ARRAY_INFO(0, ssl_options
, 1)
1167 ZEND_END_ARG_INFO();
1168 static PHP_METHOD(HttpClient
, addSslOptions
)
1172 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a!/", &opts
), invalid_arg
, return);
1174 php_http_client_options_set_subr(getThis(), ZEND_STRS("ssl"), opts
, 0 TSRMLS_CC
);
1176 RETVAL_ZVAL(getThis(), 1, 0);
1179 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getSslOptions
, 0, 0, 0)
1180 ZEND_END_ARG_INFO();
1181 static PHP_METHOD(HttpClient
, getSslOptions
)
1183 if (SUCCESS
== zend_parse_parameters_none()) {
1184 php_http_client_options_get_subr(getThis(), ZEND_STRS("ssl"), return_value TSRMLS_CC
);
1188 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_setCookies
, 0, 0, 0)
1189 ZEND_ARG_ARRAY_INFO(0, cookies
, 1)
1190 ZEND_END_ARG_INFO();
1191 static PHP_METHOD(HttpClient
, setCookies
)
1195 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a!/", &opts
), invalid_arg
, return);
1197 php_http_client_options_set_subr(getThis(), ZEND_STRS("cookies"), opts
, 1 TSRMLS_CC
);
1199 RETVAL_ZVAL(getThis(), 1, 0);
1202 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_addCookies
, 0, 0, 0)
1203 ZEND_ARG_ARRAY_INFO(0, cookies
, 1)
1204 ZEND_END_ARG_INFO();
1205 static PHP_METHOD(HttpClient
, addCookies
)
1209 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a!/", &opts
), invalid_arg
, return);
1211 php_http_client_options_set_subr(getThis(), ZEND_STRS("cookies"), opts
, 0 TSRMLS_CC
);
1213 RETVAL_ZVAL(getThis(), 1, 0);
1216 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getCookies
, 0, 0, 0)
1217 ZEND_END_ARG_INFO();
1218 static PHP_METHOD(HttpClient
, getCookies
)
1220 if (SUCCESS
== zend_parse_parameters_none()) {
1221 php_http_client_options_get_subr(getThis(), ZEND_STRS("cookies"), return_value TSRMLS_CC
);
1225 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getAvailableDrivers
, 0, 0, 0)
1226 ZEND_END_ARG_INFO();
1227 static PHP_METHOD(HttpClient
, getAvailableDrivers
) {
1228 if (SUCCESS
== zend_parse_parameters_none()) {
1229 array_init(return_value
);
1230 php_http_client_driver_list(Z_ARRVAL_P(return_value
) TSRMLS_CC
);
1234 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getAvailableOptions
, 0, 0, 0)
1235 ZEND_END_ARG_INFO();
1236 static PHP_METHOD(HttpClient
, getAvailableOptions
)
1238 if (SUCCESS
== zend_parse_parameters_none()) {
1239 php_http_client_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1241 array_init(return_value
);
1242 php_http_client_getopt(obj
->client
, PHP_HTTP_CLIENT_OPT_AVAILABLE_OPTIONS
, NULL
, &Z_ARRVAL_P(return_value
));
1246 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getAvailableConfiguration
, 0, 0, 0)
1247 ZEND_END_ARG_INFO();
1248 static PHP_METHOD(HttpClient
, getAvailableConfiguration
)
1250 if (SUCCESS
== zend_parse_parameters_none()) {
1251 php_http_client_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1253 array_init(return_value
);
1254 php_http_client_getopt(obj
->client
, PHP_HTTP_CLIENT_OPT_AVAILABLE_CONFIGURATION
, NULL
, &Z_ARRVAL_P(return_value
));
1258 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_setDebug
, 0, 0, 1)
1259 /* using IS_CALLABLE type hint would create a forwards compatibility break */
1260 ZEND_ARG_INFO(0, callback
)
1261 ZEND_END_ARG_INFO();
1262 static PHP_METHOD(HttpClient
, setDebug
)
1264 zend_fcall_info fci
;
1265 zend_fcall_info_cache fcc
;
1266 php_http_client_object_t
*client_obj
;
1269 php_http_expect(SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|f", &fci
, &fcc
), invalid_arg
, return);
1271 client_obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1273 if (client_obj
->debug
.fci
.size
> 0) {
1274 zval_ptr_dtor(&client_obj
->debug
.fci
.function_name
);
1275 client_obj
->debug
.fci
.size
= 0;
1278 memcpy(&client_obj
->debug
.fci
, &fci
, sizeof(fci
));
1279 memcpy(&client_obj
->debug
.fcc
, &fcc
, sizeof(fcc
));
1280 Z_ADDREF_P(fci
.function_name
);
1281 client_obj
->client
->callback
.debug
.func
= handle_debug
;
1282 client_obj
->client
->callback
.debug
.arg
= client_obj
;
1284 client_obj
->client
->callback
.debug
.func
= NULL
;
1285 client_obj
->client
->callback
.debug
.arg
= NULL
;
1288 RETVAL_ZVAL(getThis(), 1, 0);
1291 static zend_function_entry php_http_client_methods
[] = {
1292 PHP_ME(HttpClient
, __construct
, ai_HttpClient_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
1293 PHP_ME(HttpClient
, reset
, ai_HttpClient_reset
, ZEND_ACC_PUBLIC
)
1294 PHP_ME(HttpClient
, enqueue
, ai_HttpClient_enqueue
, ZEND_ACC_PUBLIC
)
1295 PHP_ME(HttpClient
, dequeue
, ai_HttpClient_dequeue
, ZEND_ACC_PUBLIC
)
1296 PHP_ME(HttpClient
, requeue
, ai_HttpClient_requeue
, ZEND_ACC_PUBLIC
)
1297 PHP_ME(HttpClient
, count
, ai_HttpClient_count
, ZEND_ACC_PUBLIC
)
1298 PHP_ME(HttpClient
, send
, ai_HttpClient_send
, ZEND_ACC_PUBLIC
)
1299 PHP_ME(HttpClient
, once
, ai_HttpClient_once
, ZEND_ACC_PUBLIC
)
1300 PHP_ME(HttpClient
, wait
, ai_HttpClient_wait
, ZEND_ACC_PUBLIC
)
1301 PHP_ME(HttpClient
, getResponse
, ai_HttpClient_getResponse
, ZEND_ACC_PUBLIC
)
1302 PHP_ME(HttpClient
, getHistory
, ai_HttpClient_getHistory
, ZEND_ACC_PUBLIC
)
1303 PHP_ME(HttpClient
, configure
, ai_HttpClient_configure
, ZEND_ACC_PUBLIC
)
1304 PHP_ME(HttpClient
, enablePipelining
, ai_HttpClient_enablePipelining
, ZEND_ACC_PUBLIC
|ZEND_ACC_DEPRECATED
)
1305 PHP_ME(HttpClient
, enableEvents
, ai_HttpClient_enableEvents
, ZEND_ACC_PUBLIC
|ZEND_ACC_DEPRECATED
)
1306 PHP_ME(HttpClient
, notify
, ai_HttpClient_notify
, ZEND_ACC_PUBLIC
)
1307 PHP_ME(HttpClient
, attach
, ai_HttpClient_attach
, ZEND_ACC_PUBLIC
)
1308 PHP_ME(HttpClient
, detach
, ai_HttpClient_detach
, ZEND_ACC_PUBLIC
)
1309 PHP_ME(HttpClient
, getObservers
, ai_HttpClient_getObservers
, ZEND_ACC_PUBLIC
)
1310 PHP_ME(HttpClient
, getProgressInfo
, ai_HttpClient_getProgressInfo
, ZEND_ACC_PUBLIC
)
1311 PHP_ME(HttpClient
, getTransferInfo
, ai_HttpClient_getTransferInfo
, ZEND_ACC_PUBLIC
)
1312 PHP_ME(HttpClient
, setOptions
, ai_HttpClient_setOptions
, ZEND_ACC_PUBLIC
)
1313 PHP_ME(HttpClient
, getOptions
, ai_HttpClient_getOptions
, ZEND_ACC_PUBLIC
)
1314 PHP_ME(HttpClient
, setSslOptions
, ai_HttpClient_setSslOptions
, ZEND_ACC_PUBLIC
)
1315 PHP_ME(HttpClient
, addSslOptions
, ai_HttpClient_addSslOptions
, ZEND_ACC_PUBLIC
)
1316 PHP_ME(HttpClient
, getSslOptions
, ai_HttpClient_getSslOptions
, ZEND_ACC_PUBLIC
)
1317 PHP_ME(HttpClient
, setCookies
, ai_HttpClient_setCookies
, ZEND_ACC_PUBLIC
)
1318 PHP_ME(HttpClient
, addCookies
, ai_HttpClient_addCookies
, ZEND_ACC_PUBLIC
)
1319 PHP_ME(HttpClient
, getCookies
, ai_HttpClient_getCookies
, ZEND_ACC_PUBLIC
)
1320 PHP_ME(HttpClient
, getAvailableDrivers
, ai_HttpClient_getAvailableDrivers
, ZEND_ACC_PUBLIC
|ZEND_ACC_STATIC
)
1321 PHP_ME(HttpClient
, getAvailableOptions
, ai_HttpClient_getAvailableOptions
, ZEND_ACC_PUBLIC
)
1322 PHP_ME(HttpClient
, getAvailableConfiguration
, ai_HttpClient_getAvailableConfiguration
, ZEND_ACC_PUBLIC
)
1323 PHP_ME(HttpClient
, setDebug
, ai_HttpClient_setDebug
, ZEND_ACC_PUBLIC
)
1324 EMPTY_FUNCTION_ENTRY
1327 PHP_MINIT_FUNCTION(http_client
)
1329 zend_class_entry ce
= {0};
1331 INIT_NS_CLASS_ENTRY(ce
, "http", "Client", php_http_client_methods
);
1332 php_http_client_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
1333 php_http_client_class_entry
->create_object
= php_http_client_object_new
;
1334 zend_class_implements(php_http_client_class_entry TSRMLS_CC
, 2, spl_ce_SplSubject
, spl_ce_Countable
);
1335 memcpy(&php_http_client_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
1336 php_http_client_object_handlers
.clone_obj
= NULL
;
1337 zend_declare_property_null(php_http_client_class_entry
, ZEND_STRL("observers"), ZEND_ACC_PRIVATE TSRMLS_CC
);
1338 zend_declare_property_null(php_http_client_class_entry
, ZEND_STRL("options"), ZEND_ACC_PROTECTED TSRMLS_CC
);
1339 zend_declare_property_null(php_http_client_class_entry
, ZEND_STRL("history"), ZEND_ACC_PROTECTED TSRMLS_CC
);
1340 zend_declare_property_bool(php_http_client_class_entry
, ZEND_STRL("recordHistory"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
1342 zend_declare_class_constant_long(php_http_client_class_entry
, ZEND_STRL("DEBUG_INFO"), PHP_HTTP_CLIENT_DEBUG_INFO TSRMLS_CC
);
1343 zend_declare_class_constant_long(php_http_client_class_entry
, ZEND_STRL("DEBUG_IN"), PHP_HTTP_CLIENT_DEBUG_IN TSRMLS_CC
);
1344 zend_declare_class_constant_long(php_http_client_class_entry
, ZEND_STRL("DEBUG_OUT"), PHP_HTTP_CLIENT_DEBUG_OUT TSRMLS_CC
);
1345 zend_declare_class_constant_long(php_http_client_class_entry
, ZEND_STRL("DEBUG_HEADER"), PHP_HTTP_CLIENT_DEBUG_HEADER TSRMLS_CC
);
1346 zend_declare_class_constant_long(php_http_client_class_entry
, ZEND_STRL("DEBUG_BODY"), PHP_HTTP_CLIENT_DEBUG_BODY TSRMLS_CC
);
1347 zend_declare_class_constant_long(php_http_client_class_entry
, ZEND_STRL("DEBUG_SSL"), PHP_HTTP_CLIENT_DEBUG_SSL TSRMLS_CC
);
1349 zend_hash_init(&php_http_client_drivers
, 2, NULL
, NULL
, 1);
1354 PHP_MSHUTDOWN_FUNCTION(http_client
)
1356 zend_hash_destroy(&php_http_client_drivers
);
1365 * vim600: noet sw=4 ts=4 fdm=marker
1366 * vim<600: noet sw=4 ts=4