zend_string updates
[m6w6/ext-http] / php_http_client.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
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 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14 #include "php_http_client.h"
15
16 #include <ext/spl/spl_observer.h>
17
18 /*
19 * array of name => php_http_client_driver_t*
20 */
21 static HashTable php_http_client_drivers;
22
23 static void php_http_client_driver_hash_dtor(zval *pData)
24 {
25 pefree(Z_PTR_P(pData), 1);
26 }
27
28 ZEND_RESULT_CODE php_http_client_driver_add(php_http_client_driver_t *driver)
29 {
30 return zend_hash_add_mem(&php_http_client_drivers, driver->driver_name, (void *) driver, sizeof(php_http_client_driver_t))
31 ? SUCCESS : FAILURE;
32 }
33
34 php_http_client_driver_t *php_http_client_driver_get(zend_string *name)
35 {
36 zval *ztmp;
37 php_http_client_driver_t *tmp;
38
39 if (name && (tmp = zend_hash_find_ptr(&php_http_client_drivers, name))) {
40 return tmp;
41 }
42 if ((ztmp = zend_hash_get_current_data(&php_http_client_drivers))) {
43 return Z_PTR_P(ztmp);
44 }
45 return NULL;
46 }
47
48 static int apply_driver_list(zval *p, void *arg)
49 {
50 php_http_client_driver_t *d = Z_PTR_P(p);
51 zval zname;
52
53 ZVAL_STR(&zname, d->driver_name);
54
55 zend_hash_next_index_insert(arg, &zname);
56 return ZEND_HASH_APPLY_KEEP;
57 }
58
59 void php_http_client_driver_list(HashTable *ht)
60 {
61 zend_hash_apply_with_argument(&php_http_client_drivers, apply_driver_list, ht);
62 }
63
64 void php_http_client_options_set_subr(zval *instance, char *key, size_t len, zval *opts, int overwrite)
65 {
66 if (overwrite || (opts && zend_hash_num_elements(Z_ARRVAL_P(opts)))) {
67 zend_class_entry *this_ce = Z_OBJCE_P(instance);
68 zval old_opts_tmp, *old_opts, new_opts, *entry = NULL;
69
70 array_init(&new_opts);
71 old_opts = zend_read_property(this_ce, instance, ZEND_STRL("options"), 0, &old_opts_tmp);
72 if (Z_TYPE_P(old_opts) == IS_ARRAY) {
73 array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL(new_opts));
74 }
75
76 if (overwrite) {
77 if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
78 Z_ADDREF_P(opts);
79 zend_symtable_str_update(Z_ARRVAL(new_opts), key, len, opts);
80 } else {
81 zend_symtable_str_del(Z_ARRVAL(new_opts), key, len);
82 }
83 } else if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) {
84 if ((entry = zend_symtable_str_find(Z_ARRVAL(new_opts), key, len))) {
85 array_join(Z_ARRVAL_P(opts), Z_ARRVAL_P(entry), 0, 0);
86 } else {
87 Z_ADDREF_P(opts);
88 zend_symtable_str_update(Z_ARRVAL(new_opts), key, len, opts);
89 }
90 }
91
92 zend_update_property(this_ce, instance, ZEND_STRL("options"), &new_opts);
93 zval_ptr_dtor(&new_opts);
94 }
95 }
96
97 void php_http_client_options_set(zval *instance, zval *opts)
98 {
99 php_http_arrkey_t key;
100 zval new_opts;
101 zend_class_entry *this_ce = Z_OBJCE_P(instance);
102 zend_bool is_client = instanceof_function(this_ce, php_http_client_class_entry);
103
104 array_init(&new_opts);
105
106 if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) {
107 zend_update_property(this_ce, instance, ZEND_STRL("options"), &new_opts);
108 zval_ptr_dtor(&new_opts);
109 } else {
110 zval old_opts_tmp, *old_opts, add_opts, *opt;
111
112 array_init(&add_opts);
113 /* some options need extra attention -- thus cannot use array_merge() directly */
114 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(opts), key.h, key.key, opt)
115 {
116 if (key.key) {
117 if (Z_TYPE_P(opt) == IS_ARRAY && (zend_string_equals_literal(key.key, "ssl") || zend_string_equals_literal(key.key, "cookies"))) {
118 php_http_client_options_set_subr(instance, key.key->val, key.key->len, opt, 0);
119 } else if (is_client && (zend_string_equals_literal(key.key, "recordHistory") || zend_string_equals_literal(key.key, "responseMessageClass"))) {
120 zend_update_property(this_ce, instance, key.key->val, key.key->len, opt);
121 } else if (Z_TYPE_P(opt) == IS_NULL) {
122 old_opts = zend_read_property(this_ce, instance, ZEND_STRL("options"), 0, &old_opts_tmp);
123 if (Z_TYPE_P(old_opts) == IS_ARRAY) {
124 zend_symtable_del(Z_ARRVAL_P(old_opts), key.key);
125 }
126 } else {
127 Z_TRY_ADDREF_P(opt);
128 add_assoc_zval_ex(&add_opts, key.key->val, key.key->len, opt);
129 }
130 }
131 }
132 ZEND_HASH_FOREACH_END();
133
134 old_opts = zend_read_property(this_ce, instance, ZEND_STRL("options"), 0, &old_opts_tmp);
135 if (Z_TYPE_P(old_opts) == IS_ARRAY) {
136 array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL(new_opts));
137 }
138 array_join(Z_ARRVAL(add_opts), Z_ARRVAL(new_opts), 0, 0);
139 zend_update_property(this_ce, instance, ZEND_STRL("options"), &new_opts);
140 zval_ptr_dtor(&new_opts);
141 zval_ptr_dtor(&add_opts);
142 }
143 }
144
145 void php_http_client_options_get_subr(zval *instance, char *key, size_t len, zval *return_value)
146 {
147 zend_class_entry *this_ce = Z_OBJCE_P(instance);
148 zval *options, opts_tmp, *opts = zend_read_property(this_ce, instance, ZEND_STRL("options"), 0, &opts_tmp);
149
150 if ((Z_TYPE_P(opts) == IS_ARRAY) && (options = zend_symtable_str_find(Z_ARRVAL_P(opts), key, len))) {
151 RETVAL_ZVAL_FAST(options);
152 }
153 }
154
155 static void queue_dtor(void *enqueued)
156 {
157 php_http_client_enqueue_t *e = enqueued;
158
159 if (e->dtor) {
160 e->dtor(e);
161 }
162 }
163
164 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)
165 {
166 php_http_client_t *free_h = NULL;
167
168 if (!h) {
169 free_h = h = emalloc(sizeof(*h));
170 }
171 memset(h, 0, sizeof(*h));
172
173 h->ops = ops;
174 if (rf) {
175 h->rf = rf;
176 } else if (ops->rsrc) {
177 h->rf = php_resource_factory_init(NULL, h->ops->rsrc, h, NULL);
178 }
179 zend_llist_init(&h->requests, sizeof(php_http_client_enqueue_t), queue_dtor, 0);
180 zend_llist_init(&h->responses, sizeof(void *), NULL, 0);
181
182 if (h->ops->init) {
183 if (!(h = h->ops->init(h, init_arg))) {
184 php_error_docref(NULL, E_WARNING, "Could not initialize client");
185 PTR_FREE(free_h);
186 }
187 }
188
189 return h;
190 }
191
192 php_http_client_t *php_http_client_copy(php_http_client_t *from, php_http_client_t *to)
193 {
194 if (from->ops->copy) {
195 return from->ops->copy(from, to);
196 }
197
198 return NULL;
199 }
200
201 void php_http_client_dtor(php_http_client_t *h)
202 {
203 php_http_client_reset(h);
204
205 if (h->ops->dtor) {
206 h->ops->dtor(h);
207 }
208
209 php_resource_factory_free(&h->rf);
210 }
211
212 void php_http_client_free(php_http_client_t **h) {
213 if (*h) {
214 php_http_client_dtor(*h);
215 efree(*h);
216 *h = NULL;
217 }
218 }
219
220 ZEND_RESULT_CODE php_http_client_enqueue(php_http_client_t *h, php_http_client_enqueue_t *enqueue)
221 {
222 if (h->ops->enqueue) {
223 if (php_http_client_enqueued(h, enqueue->request, NULL)) {
224 php_error_docref(NULL, E_WARNING, "Failed to enqueue request; request already in queue");
225 return FAILURE;
226 }
227 return h->ops->enqueue(h, enqueue);
228 }
229
230 return FAILURE;
231 }
232
233 ZEND_RESULT_CODE php_http_client_dequeue(php_http_client_t *h, php_http_message_t *request)
234 {
235 if (h->ops->dequeue) {
236 php_http_client_enqueue_t *enqueue = php_http_client_enqueued(h, request, NULL);
237
238 if (!enqueue) {
239 php_error_docref(NULL, E_WARNING, "Failed to dequeue request; request not in queue");
240 return FAILURE;
241 }
242 return h->ops->dequeue(h, enqueue);
243 }
244 return FAILURE;
245 }
246
247 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)
248 {
249 zend_llist_element *el = NULL;
250
251 if (compare_func) {
252 for (el = h->requests.head; el; el = el->next) {
253 if (compare_func((php_http_client_enqueue_t *) el->data, compare_arg)) {
254 break;
255 }
256 }
257 } else {
258 for (el = h->requests.head; el; el = el->next) {
259 if (((php_http_client_enqueue_t *) el->data)->request == compare_arg) {
260 break;
261 }
262 }
263 }
264 return el ? (php_http_client_enqueue_t *) el->data : NULL;
265 }
266
267 ZEND_RESULT_CODE php_http_client_wait(php_http_client_t *h, struct timeval *custom_timeout)
268 {
269 if (h->ops->wait) {
270 return h->ops->wait(h, custom_timeout);
271 }
272
273 return FAILURE;
274 }
275
276 int php_http_client_once(php_http_client_t *h)
277 {
278 if (h->ops->once) {
279 return h->ops->once(h);
280 }
281
282 return FAILURE;
283 }
284
285 ZEND_RESULT_CODE php_http_client_exec(php_http_client_t *h)
286 {
287 if (h->ops->exec) {
288 return h->ops->exec(h);
289 }
290
291 return FAILURE;
292 }
293
294 void php_http_client_reset(php_http_client_t *h)
295 {
296 if (h->ops->reset) {
297 h->ops->reset(h);
298 }
299
300 zend_llist_clean(&h->requests);
301 zend_llist_clean(&h->responses);
302 }
303
304 ZEND_RESULT_CODE php_http_client_setopt(php_http_client_t *h, php_http_client_setopt_opt_t opt, void *arg)
305 {
306 if (h->ops->setopt) {
307 return h->ops->setopt(h, opt, arg);
308 }
309
310 return FAILURE;
311 }
312
313 ZEND_RESULT_CODE php_http_client_getopt(php_http_client_t *h, php_http_client_getopt_opt_t opt, void *arg, void *res_ptr)
314 {
315 if (h->ops->getopt) {
316 return h->ops->getopt(h, opt, arg, res_ptr);
317 }
318 return FAILURE;
319 }
320
321 zend_class_entry *php_http_client_class_entry;
322 static zend_object_handlers php_http_client_object_handlers;
323
324 void php_http_client_object_free(zend_object *object)
325 {
326 php_http_client_object_t *o = PHP_HTTP_OBJ(object, NULL);
327
328 php_http_client_free(&o->client);
329 zend_object_std_dtor(object);
330 }
331
332 php_http_client_object_t *php_http_client_object_new_ex(zend_class_entry *ce, php_http_client_t *client)
333 {
334 php_http_client_object_t *o;
335
336 o = ecalloc(1, sizeof(php_http_client_object_t) + (ce->default_properties_count - 1) * sizeof(zval));
337 zend_object_std_init(&o->zo, ce);
338 object_properties_init(&o->zo, ce);
339
340 o->client = client;
341
342 o->zo.handlers = &php_http_client_object_handlers;
343
344 return o;
345 }
346
347 zend_object *php_http_client_object_new(zend_class_entry *ce)
348 {
349 return &php_http_client_object_new_ex(ce, NULL)->zo;
350 }
351
352 static void handle_history(zval *zclient, php_http_message_t *request, php_http_message_t *response)
353 {
354 zval new_hist, old_hist_tmp, *old_hist = zend_read_property(php_http_client_class_entry, zclient, ZEND_STRL("history"), 0, &old_hist_tmp);
355 php_http_message_t *req_copy = php_http_message_copy(request, NULL);
356 php_http_message_t *res_copy = php_http_message_copy(response, NULL);
357 php_http_message_t *zipped = php_http_message_zip(res_copy, req_copy);
358 php_http_message_object_t *obj = php_http_message_object_new_ex(php_http_message_class_entry, zipped);
359
360 ZVAL_OBJ(&new_hist, &obj->zo);
361
362 if (Z_TYPE_P(old_hist) == IS_OBJECT) {
363 php_http_message_object_prepend(&new_hist, old_hist, 1);
364 }
365
366 zend_update_property(php_http_client_class_entry, zclient, ZEND_STRL("history"), &new_hist);
367 zval_ptr_dtor(&new_hist);
368 }
369
370 static ZEND_RESULT_CODE handle_response(void *arg, php_http_client_t *client, php_http_client_enqueue_t *e, php_http_message_t **request, php_http_message_t **response)
371 {
372 zend_bool dequeue = 0;
373 zval zclient;
374 php_http_message_t *msg;
375 php_http_client_progress_state_t *progress;
376
377 ZVAL_OBJ(&zclient, &((php_http_client_object_t*) arg)->zo);
378
379 if ((msg = *response)) {
380 php_http_message_object_t *msg_obj;
381 zval info, zresponse, zrequest, rec_hist_tmp;
382 HashTable *info_ht;
383
384 /* ensure the message is of type response (could be uninitialized in case of early error, like DNS) */
385 php_http_message_set_type(msg, PHP_HTTP_RESPONSE);
386
387 if (zend_is_true(zend_read_property(php_http_client_class_entry, &zclient, ZEND_STRL("recordHistory"), 0, &rec_hist_tmp))) {
388 handle_history(&zclient, *request, *response);
389 }
390
391 /* hard detach, redirects etc. are in the history */
392 php_http_message_free(&msg->parent);
393 *response = NULL;
394
395 msg_obj = php_http_message_object_new_ex(php_http_client_response_class_entry, msg);
396 ZVAL_OBJ(&zresponse, &msg_obj->zo);
397 ZVAL_OBJECT(&zrequest, &((php_http_message_object_t *) e->opaque)->zo, 1);
398
399 php_http_message_object_prepend(&zresponse, &zrequest, 1);
400
401 object_init(&info);
402 info_ht = HASH_OF(&info);
403 php_http_client_getopt(client, PHP_HTTP_CLIENT_OPT_TRANSFER_INFO, e->request, &info_ht);
404 zend_update_property(php_http_client_response_class_entry, &zresponse, ZEND_STRL("transferInfo"), &info);
405 zval_ptr_dtor(&info);
406
407 Z_ADDREF(zresponse);
408 zend_llist_add_element(&client->responses, &msg_obj);
409
410 if (e->closure.fci.size) {
411 zval retval;
412 zend_error_handling zeh;
413
414 ZVAL_UNDEF(&retval);
415 zend_fcall_info_argn(&e->closure.fci, 1, &zresponse);
416 zend_replace_error_handling(EH_NORMAL, NULL, &zeh);
417 zend_fcall_info_call(&e->closure.fci, &e->closure.fcc, &retval, NULL);
418 zend_restore_error_handling(&zeh);
419 zend_fcall_info_argn(&e->closure.fci, 0);
420
421 if (Z_TYPE(retval) == IS_TRUE) {
422 dequeue = 1;
423 }
424 zval_ptr_dtor(&retval);
425 }
426
427 zval_ptr_dtor(&zresponse);
428 zval_ptr_dtor(&zrequest);
429 }
430
431 if (SUCCESS == php_http_client_getopt(client, PHP_HTTP_CLIENT_OPT_PROGRESS_INFO, e->request, &progress)) {
432 progress->info = "finished";
433 progress->finished = 1;
434 client->callback.progress.func(client->callback.progress.arg, client, e, progress);
435 }
436
437 if (dequeue) {
438 php_http_client_dequeue(client, e->request);
439 }
440
441 return SUCCESS;
442 }
443
444 static void handle_progress(void *arg, php_http_client_t *client, php_http_client_enqueue_t *e, php_http_client_progress_state_t *progress)
445 {
446 zval zrequest, zprogress, retval, zclient;
447 zend_error_handling zeh;
448
449 ZVAL_UNDEF(&retval);
450 ZVAL_OBJECT(&zclient, &((php_http_client_object_t *) arg)->zo, 1);
451 ZVAL_OBJECT(&zrequest, &((php_http_message_object_t *) e->opaque)->zo, 1);
452 object_init(&zprogress);
453 add_property_bool(&zprogress, "started", progress->started);
454 add_property_bool(&zprogress, "finished", progress->finished);
455 add_property_string(&zprogress, "info", STR_PTR(progress->info));
456 add_property_double(&zprogress, "dltotal", progress->dl.total);
457 add_property_double(&zprogress, "dlnow", progress->dl.now);
458 add_property_double(&zprogress, "ultotal", progress->ul.total);
459 add_property_double(&zprogress, "ulnow", progress->ul.now);
460 zend_replace_error_handling(EH_NORMAL, NULL, &zeh);
461 zend_call_method_with_2_params(&zclient, NULL, NULL, "notify", &retval, &zrequest, &zprogress);
462 zend_restore_error_handling(&zeh);
463 zval_ptr_dtor(&zclient);
464 zval_ptr_dtor(&zrequest);
465 zval_ptr_dtor(&zprogress);
466 zval_ptr_dtor(&retval);
467 }
468
469 static void response_dtor(void *data)
470 {
471 php_http_message_object_t *msg_obj = *(php_http_message_object_t **) data;
472
473 zend_objects_store_del(&msg_obj->zo);
474 }
475
476 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_construct, 0, 0, 0)
477 ZEND_ARG_INFO(0, driver)
478 ZEND_ARG_INFO(0, persistent_handle_id)
479 ZEND_END_ARG_INFO();
480 static PHP_METHOD(HttpClient, __construct)
481 {
482 zend_string *driver_name = NULL, *persistent_handle_name = NULL;
483 php_http_client_driver_t *driver;
484 php_resource_factory_t *rf = NULL;
485 php_http_client_object_t *obj;
486 zval os;
487
488 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|S!S!", &driver_name, &persistent_handle_name), invalid_arg, return);
489
490 if (!zend_hash_num_elements(&php_http_client_drivers)) {
491 php_http_throw(unexpected_val, "No http\\Client drivers available", NULL);
492 return;
493 }
494 if (!(driver = php_http_client_driver_get(driver_name))) {
495 php_http_throw(unexpected_val, "Failed to locate \"%s\" client request handler", driver_name ? driver_name->val : "default");
496 return;
497 }
498
499 object_init_ex(&os, spl_ce_SplObjectStorage);
500 zend_update_property(php_http_client_class_entry, getThis(), ZEND_STRL("observers"), &os);
501 zval_ptr_dtor(&os);
502
503 if (persistent_handle_name) {
504 php_persistent_handle_factory_t *pf;
505
506 if ((pf = php_persistent_handle_concede(NULL, driver->client_name, persistent_handle_name, NULL, NULL))) {
507 rf = php_resource_factory_init(NULL, php_persistent_handle_get_resource_factory_ops(), pf, (void (*)(void *)) php_persistent_handle_abandon);
508 }
509 }
510
511 obj = PHP_HTTP_OBJ(NULL, getThis());
512
513 php_http_expect(obj->client = php_http_client_init(NULL, driver->client_ops, rf, NULL), runtime, return);
514
515 obj->client->callback.response.func = handle_response;
516 obj->client->callback.response.arg = obj;
517 obj->client->callback.progress.func = handle_progress;
518 obj->client->callback.progress.arg = obj;
519
520 obj->client->responses.dtor = response_dtor;
521 }
522
523 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_reset, 0, 0, 0)
524 ZEND_END_ARG_INFO();
525 static PHP_METHOD(HttpClient, reset)
526 {
527 php_http_client_object_t *obj;
528 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
529
530 obj = PHP_HTTP_OBJ(NULL, getThis());
531
532 obj->iterator = 0;
533 php_http_client_reset(obj->client);
534
535 RETVAL_ZVAL_FAST(getThis());
536 }
537
538 static HashTable *combined_options(zval *client, zval *request)
539 {
540 HashTable *options;
541 unsigned num_options = 0;
542 zval z_roptions, z_options_tmp, *z_coptions = zend_read_property(php_http_client_class_entry, client, ZEND_STRL("options"), 0, &z_options_tmp);
543
544 if (Z_TYPE_P(z_coptions) == IS_ARRAY) {
545 num_options = zend_hash_num_elements(Z_ARRVAL_P(z_coptions));
546 }
547 ZVAL_UNDEF(&z_roptions);
548 zend_call_method_with_0_params(request, NULL, NULL, "getOptions", &z_roptions);
549 if (Z_TYPE(z_roptions) == IS_ARRAY) {
550 unsigned num = zend_hash_num_elements(Z_ARRVAL(z_roptions));
551 if (num > num_options) {
552 num_options = num;
553 }
554 }
555 ALLOC_HASHTABLE(options);
556 ZEND_INIT_SYMTABLE_EX(options, num_options, 0);
557 if (Z_TYPE_P(z_coptions) == IS_ARRAY) {
558 array_copy(Z_ARRVAL_P(z_coptions), options);
559 }
560 if (Z_TYPE(z_roptions) == IS_ARRAY) {
561 array_join(Z_ARRVAL(z_roptions), options, 0, 0);
562 }
563 zval_ptr_dtor(&z_roptions);
564
565 return options;
566 }
567
568 static void msg_queue_dtor(php_http_client_enqueue_t *e)
569 {
570 php_http_message_object_t *msg_obj = e->opaque;
571
572 zend_objects_store_del(&msg_obj->zo);
573 zend_hash_destroy(e->options);
574 FREE_HASHTABLE(e->options);
575
576 if (e->closure.fci.size) {
577 zval_ptr_dtor(&e->closure.fci.function_name);
578 if (e->closure.fci.object) {
579 zend_objects_store_del(e->closure.fci.object);
580 }
581 }
582 }
583
584 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enqueue, 0, 0, 1)
585 ZEND_ARG_OBJ_INFO(0, request, http\\Client\\Request, 0)
586 ZEND_ARG_INFO(0, callable)
587 ZEND_END_ARG_INFO();
588 static PHP_METHOD(HttpClient, enqueue)
589 {
590 zval *request;
591 zend_fcall_info fci = empty_fcall_info;
592 zend_fcall_info_cache fcc = empty_fcall_info_cache;
593 php_http_client_object_t *obj;
594 php_http_message_object_t *msg_obj;
595 php_http_client_enqueue_t q;
596
597 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O|f", &request, php_http_client_request_class_entry, &fci, &fcc), invalid_arg, return);
598
599 obj = PHP_HTTP_OBJ(NULL, getThis());
600 msg_obj = PHP_HTTP_OBJ(NULL, request);
601
602 if (php_http_client_enqueued(obj->client, msg_obj->message, NULL)) {
603 php_http_throw(bad_method_call, "Failed to enqueue request; request already in queue", NULL);
604 return;
605 }
606
607 q.request = msg_obj->message;
608 q.options = combined_options(getThis(), request);
609 q.dtor = msg_queue_dtor;
610 q.opaque = msg_obj;
611 q.closure.fci = fci;
612 q.closure.fcc = fcc;
613
614 if (fci.size) {
615 Z_TRY_ADDREF(fci.function_name);
616 if (fci.object) {
617 ++GC_REFCOUNT(fci.object);
618 }
619 }
620
621 Z_ADDREF_P(request);
622
623 php_http_expect(SUCCESS == php_http_client_enqueue(obj->client, &q), runtime,
624 msg_queue_dtor(&q);
625 return;
626 );
627
628 RETVAL_ZVAL_FAST(getThis());
629 }
630
631 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_dequeue, 0, 0, 1)
632 ZEND_ARG_OBJ_INFO(0, request, http\\Client\\Request, 0)
633 ZEND_END_ARG_INFO();
634 static PHP_METHOD(HttpClient, dequeue)
635 {
636 zval *request;
637 php_http_client_object_t *obj;
638 php_http_message_object_t *msg_obj;
639
640 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O", &request, php_http_client_request_class_entry), invalid_arg, return);
641
642 obj = PHP_HTTP_OBJ(NULL, getThis());
643 msg_obj = PHP_HTTP_OBJ(NULL, request);
644
645 if (!php_http_client_enqueued(obj->client, msg_obj->message, NULL)) {
646 php_http_throw(bad_method_call, "Failed to dequeue request; request not in queue", NULL);
647 return;
648 }
649
650 php_http_expect(SUCCESS == php_http_client_dequeue(obj->client, msg_obj->message), runtime, return);
651
652 RETVAL_ZVAL_FAST(getThis());
653 }
654
655 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_requeue, 0, 0, 1)
656 ZEND_ARG_OBJ_INFO(0, request, http\\Client\\Request, 0)
657 ZEND_ARG_INFO(0, callable)
658 ZEND_END_ARG_INFO();
659 static PHP_METHOD(HttpClient, requeue)
660 {
661 zval *request;
662 zend_fcall_info fci = empty_fcall_info;
663 zend_fcall_info_cache fcc = empty_fcall_info_cache;
664 php_http_client_object_t *obj;
665 php_http_message_object_t *msg_obj;
666 php_http_client_enqueue_t q;
667
668 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O|f", &request, php_http_client_request_class_entry, &fci, &fcc), invalid_arg, return);
669
670 obj = PHP_HTTP_OBJ(NULL, getThis());
671 msg_obj = PHP_HTTP_OBJ(NULL, request);
672
673 if (php_http_client_enqueued(obj->client, msg_obj->message, NULL)) {
674 php_http_expect(SUCCESS == php_http_client_dequeue(obj->client, msg_obj->message), runtime, return);
675 }
676
677 q.request = msg_obj->message;
678 q.options = combined_options(getThis(), request);
679 q.dtor = msg_queue_dtor;
680 q.opaque = msg_obj;
681 q.closure.fci = fci;
682 q.closure.fcc = fcc;
683
684 if (fci.size) {
685 Z_TRY_ADDREF(fci.function_name);
686 if (fci.object) {
687 ++GC_REFCOUNT(fci.object);
688 }
689 }
690
691 Z_ADDREF_P(request);
692
693 php_http_expect(SUCCESS == php_http_client_enqueue(obj->client, &q), runtime,
694 msg_queue_dtor(&q);
695 return;
696 );
697
698 RETVAL_ZVAL_FAST(getThis());
699 }
700
701 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_count, 0, 0, 0)
702 ZEND_END_ARG_INFO();
703 static PHP_METHOD(HttpClient, count)
704 {
705 zend_long count_mode = -1;
706
707 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &count_mode)) {
708 php_http_client_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
709
710 RETVAL_LONG(zend_llist_count(&obj->client->requests));
711 }
712 }
713
714 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getResponse, 0, 0, 0)
715 ZEND_ARG_OBJ_INFO(0, request, http\\Client\\Request, 1)
716 ZEND_END_ARG_INFO();
717 static PHP_METHOD(HttpClient, getResponse)
718 {
719 zval *zrequest = NULL;
720 php_http_client_object_t *obj;
721
722 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|O", &zrequest, php_http_client_request_class_entry), invalid_arg, return);
723
724 obj = PHP_HTTP_OBJ(NULL, getThis());
725
726 if (zrequest) {
727 /* lookup the response with the request */
728 zend_llist_element *el = NULL;
729 php_http_message_object_t *req_obj = PHP_HTTP_OBJ(NULL, zrequest);
730
731 for (el = obj->client->responses.head; el; el = el->next) {
732 php_http_message_object_t *response_obj = *(php_http_message_object_t **) el->data;
733
734 if (response_obj->message->parent == req_obj->message) {
735 RETURN_OBJECT(&response_obj->zo, 1);
736 }
737 }
738
739 /* not found for the request! */
740 php_http_throw(unexpected_val, "Could not find response for the request", NULL);
741 return;
742 }
743
744 /* pop off the last response */
745 if (obj->client->responses.tail) {
746 php_http_message_object_t *response_obj = *(php_http_message_object_t **) obj->client->responses.tail->data;
747
748 /* pop off and go */
749 if (response_obj) {
750 RETVAL_OBJECT(&response_obj->zo, 1);
751 zend_llist_remove_tail(&obj->client->responses);
752 }
753 }
754 }
755
756 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getHistory, 0, 0, 0)
757 ZEND_END_ARG_INFO();
758 static PHP_METHOD(HttpClient, getHistory)
759 {
760 zval zhistory_tmp, *zhistory;
761
762 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
763
764 zhistory = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("history"), 0, &zhistory_tmp);
765 RETVAL_ZVAL_FAST(zhistory);
766 }
767
768 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_send, 0, 0, 0)
769 ZEND_END_ARG_INFO();
770 static PHP_METHOD(HttpClient, send)
771 {
772 php_http_client_object_t *obj;
773
774 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
775
776 obj = PHP_HTTP_OBJ(NULL, getThis());
777
778 php_http_expect(SUCCESS == php_http_client_exec(obj->client), runtime, return);
779
780 RETVAL_ZVAL_FAST(getThis());
781 }
782
783 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_once, 0, 0, 0)
784 ZEND_END_ARG_INFO();
785 static PHP_METHOD(HttpClient, once)
786 {
787 if (SUCCESS == zend_parse_parameters_none()) {
788 php_http_client_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
789
790 RETURN_BOOL(0 < php_http_client_once(obj->client));
791 }
792 }
793
794 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_wait, 0, 0, 0)
795 ZEND_ARG_INFO(0, timeout)
796 ZEND_END_ARG_INFO();
797 static PHP_METHOD(HttpClient, wait)
798 {
799 double timeout = 0;
800
801 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|d", &timeout)) {
802 struct timeval timeout_val;
803 php_http_client_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
804
805 timeout_val.tv_sec = (time_t) timeout;
806 timeout_val.tv_usec = PHP_HTTP_USEC(timeout) % PHP_HTTP_MCROSEC;
807
808 RETURN_BOOL(SUCCESS == php_http_client_wait(obj->client, timeout > 0 ? &timeout_val : NULL));
809 }
810 }
811
812 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enablePipelining, 0, 0, 0)
813 ZEND_ARG_INFO(0, enable)
814 ZEND_END_ARG_INFO();
815 static PHP_METHOD(HttpClient, enablePipelining)
816 {
817 zend_bool enable = 1;
818 php_http_client_object_t *obj;
819
820 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &enable), invalid_arg, return);
821
822 obj = PHP_HTTP_OBJ(NULL, getThis());
823
824 php_http_expect(SUCCESS == php_http_client_setopt(obj->client, PHP_HTTP_CLIENT_OPT_ENABLE_PIPELINING, &enable), unexpected_val, return);
825
826 RETVAL_ZVAL_FAST(getThis());
827 }
828
829 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_enableEvents, 0, 0, 0)
830 ZEND_ARG_INFO(0, enable)
831 ZEND_END_ARG_INFO();
832 static PHP_METHOD(HttpClient, enableEvents)
833 {
834 zend_bool enable = 1;
835 php_http_client_object_t *obj;
836
837 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &enable), invalid_arg, return);
838
839 obj = PHP_HTTP_OBJ(NULL, getThis());
840
841 php_http_expect(SUCCESS == php_http_client_setopt(obj->client, PHP_HTTP_CLIENT_OPT_USE_EVENTS, &enable), unexpected_val, return);
842
843 RETVAL_ZVAL_FAST(getThis());
844 }
845
846 static int notify(zend_object_iterator *iter, void *puser)
847 {
848 zval *observer, *args = puser;
849
850 if ((observer = iter->funcs->get_current_data(iter))) {
851 int num_args = !Z_ISUNDEF(args[0]) + !Z_ISUNDEF(args[1]) + !Z_ISUNDEF(args[2]);
852 return php_http_method_call(observer, ZEND_STRL("update"), num_args, args, NULL);
853 }
854 return FAILURE;
855 }
856
857 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_notify, 0, 0, 0)
858 ZEND_ARG_OBJ_INFO(0, request, http\\Client\\Request, 1)
859 ZEND_END_ARG_INFO();
860 static PHP_METHOD(HttpClient, notify)
861 {
862 zval *request = NULL, *zprogress = NULL, observers_tmp, *observers, args[3];
863
864 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|O!o!", &request, php_http_client_request_class_entry, &zprogress), invalid_arg, return);
865
866 observers = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("observers"), 0, &observers_tmp);
867
868 if (Z_TYPE_P(observers) != IS_OBJECT) {
869 php_http_throw(unexpected_val, "Observer storage is corrupted", NULL);
870 return;
871 }
872
873 ZVAL_COPY(&args[0], getThis());
874 if (request) {
875 ZVAL_COPY(&args[1], request);
876 } else {
877 ZVAL_UNDEF(&args[1]);
878 }
879 if (zprogress) {
880 ZVAL_COPY(&args[2], zprogress);
881 } else {
882 ZVAL_UNDEF(&args[2]);
883 }
884
885 spl_iterator_apply(observers, notify, args);
886
887 zval_ptr_dtor(getThis());
888 if (request) {
889 zval_ptr_dtor(request);
890 }
891 if (zprogress) {
892 zval_ptr_dtor(zprogress);
893 }
894
895 RETVAL_ZVAL_FAST(getThis());
896 }
897
898 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_attach, 0, 0, 1)
899 ZEND_ARG_OBJ_INFO(0, observer, SplObserver, 0)
900 ZEND_END_ARG_INFO();
901 static PHP_METHOD(HttpClient, attach)
902 {
903 zval observers_tmp, *observers, *observer, retval;
904
905 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O", &observer, spl_ce_SplObserver), invalid_arg, return);
906
907 observers = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("observers"), 0, &observers_tmp);
908
909 if (Z_TYPE_P(observers) != IS_OBJECT) {
910 php_http_throw(unexpected_val, "Observer storage is corrupted", NULL);
911 return;
912 }
913
914 ZVAL_UNDEF(&retval);
915 zend_call_method_with_1_params(observers, NULL, NULL, "attach", &retval, observer);
916 zval_ptr_dtor(&retval);
917
918 RETVAL_ZVAL_FAST(getThis());
919 }
920
921 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_detach, 0, 0, 1)
922 ZEND_ARG_OBJ_INFO(0, observer, SplObserver, 0)
923 ZEND_END_ARG_INFO();
924 static PHP_METHOD(HttpClient, detach)
925 {
926 zval observers_tmp, *observers, *observer, retval;
927
928 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O", &observer, spl_ce_SplObserver), invalid_arg, return);
929
930 observers = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("observers"), 0, &observers_tmp);
931
932 if (Z_TYPE_P(observers) != IS_OBJECT) {
933 php_http_throw(unexpected_val, "Observer storage is corrupted", NULL);
934 return;
935 }
936
937 ZVAL_UNDEF(&retval);
938 zend_call_method_with_1_params(observers, NULL, NULL, "detach", &retval, observer);
939 zval_ptr_dtor(&retval);
940
941 RETVAL_ZVAL_FAST(getThis());
942 }
943
944 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getObservers, 0, 0, 0)
945 ZEND_END_ARG_INFO();
946 static PHP_METHOD(HttpClient, getObservers)
947 {
948 zval observers_tmp, *observers;
949
950 php_http_expect(SUCCESS == zend_parse_parameters_none(), invalid_arg, return);
951
952 observers = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("observers"), 0, &observers_tmp);
953
954 if (Z_TYPE_P(observers) != IS_OBJECT) {
955 php_http_throw(unexpected_val, "Observer storage is corrupted", NULL);
956 return;
957 }
958
959 RETVAL_ZVAL_FAST(observers);
960 }
961
962 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getProgressInfo, 0, 0, 1)
963 ZEND_ARG_OBJ_INFO(0, request, http\\Client\\Request, 0)
964 ZEND_END_ARG_INFO();
965 static PHP_METHOD(HttpClient, getProgressInfo)
966 {
967 zval *request;
968 php_http_client_object_t *obj;
969 php_http_message_object_t *req_obj;
970 php_http_client_progress_state_t *progress;
971
972 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O", &request, php_http_client_request_class_entry), invalid_arg, return);
973
974 obj = PHP_HTTP_OBJ(NULL, getThis());
975 req_obj = PHP_HTTP_OBJ(NULL, request);
976
977 php_http_expect(SUCCESS == php_http_client_getopt(obj->client, PHP_HTTP_CLIENT_OPT_PROGRESS_INFO, req_obj->message, &progress), unexpected_val, return);
978
979 object_init(return_value);
980 add_property_bool(return_value, "started", progress->started);
981 add_property_bool(return_value, "finished", progress->finished);
982 add_property_string(return_value, "info", STR_PTR(progress->info));
983 add_property_double(return_value, "dltotal", progress->dl.total);
984 add_property_double(return_value, "dlnow", progress->dl.now);
985 add_property_double(return_value, "ultotal", progress->ul.total);
986 add_property_double(return_value, "ulnow", progress->ul.now);
987 }
988
989 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getTransferInfo, 0, 0, 1)
990 ZEND_ARG_OBJ_INFO(0, request, http\\Client\\Request, 0)
991 ZEND_END_ARG_INFO();
992 static PHP_METHOD(HttpClient, getTransferInfo)
993 {
994 zval *request;
995 HashTable *info;
996 php_http_client_object_t *obj;
997 php_http_message_object_t *req_obj;
998
999 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "O", &request, php_http_client_request_class_entry), invalid_arg, return);
1000
1001 obj = PHP_HTTP_OBJ(NULL, getThis());
1002 req_obj = PHP_HTTP_OBJ(NULL, request);
1003
1004 object_init(return_value);
1005 info = HASH_OF(return_value);
1006 php_http_expect(SUCCESS == php_http_client_getopt(obj->client, PHP_HTTP_CLIENT_OPT_TRANSFER_INFO, req_obj->message, &info), unexpected_val, return);
1007 }
1008
1009 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_setOptions, 0, 0, 0)
1010 ZEND_ARG_ARRAY_INFO(0, options, 1)
1011 ZEND_END_ARG_INFO();
1012 static PHP_METHOD(HttpClient, setOptions)
1013 {
1014 zval *opts = NULL;
1015
1016 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
1017
1018 php_http_client_options_set(getThis(), opts);
1019
1020 RETVAL_ZVAL_FAST(getThis());
1021 }
1022
1023 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getOptions, 0, 0, 0)
1024 ZEND_END_ARG_INFO();
1025 static PHP_METHOD(HttpClient, getOptions)
1026 {
1027 if (SUCCESS == zend_parse_parameters_none()) {
1028 zval options_tmp, *options = zend_read_property(php_http_client_class_entry, getThis(), ZEND_STRL("options"), 0, &options_tmp);
1029 RETVAL_ZVAL_FAST(options);
1030 }
1031 }
1032
1033 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_setSslOptions, 0, 0, 0)
1034 ZEND_ARG_ARRAY_INFO(0, ssl_option, 1)
1035 ZEND_END_ARG_INFO();
1036 static PHP_METHOD(HttpClient, setSslOptions)
1037 {
1038 zval *opts = NULL;
1039
1040 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
1041
1042 php_http_client_options_set_subr(getThis(), ZEND_STRL("ssl"), opts, 1);
1043
1044 RETVAL_ZVAL_FAST(getThis());
1045 }
1046
1047 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_addSslOptions, 0, 0, 0)
1048 ZEND_ARG_ARRAY_INFO(0, ssl_options, 1)
1049 ZEND_END_ARG_INFO();
1050 static PHP_METHOD(HttpClient, addSslOptions)
1051 {
1052 zval *opts = NULL;
1053
1054 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
1055
1056 php_http_client_options_set_subr(getThis(), ZEND_STRL("ssl"), opts, 0);
1057
1058 RETVAL_ZVAL_FAST(getThis());
1059 }
1060
1061 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getSslOptions, 0, 0, 0)
1062 ZEND_END_ARG_INFO();
1063 static PHP_METHOD(HttpClient, getSslOptions)
1064 {
1065 if (SUCCESS == zend_parse_parameters_none()) {
1066 php_http_client_options_get_subr(getThis(), ZEND_STRL("ssl"), return_value);
1067 }
1068 }
1069
1070 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_setCookies, 0, 0, 0)
1071 ZEND_ARG_ARRAY_INFO(0, cookies, 1)
1072 ZEND_END_ARG_INFO();
1073 static PHP_METHOD(HttpClient, setCookies)
1074 {
1075 zval *opts = NULL;
1076
1077 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
1078
1079 php_http_client_options_set_subr(getThis(), ZEND_STRL("cookies"), opts, 1);
1080
1081 RETVAL_ZVAL_FAST(getThis());
1082 }
1083
1084 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_addCookies, 0, 0, 0)
1085 ZEND_ARG_ARRAY_INFO(0, cookies, 1)
1086 ZEND_END_ARG_INFO();
1087 static PHP_METHOD(HttpClient, addCookies)
1088 {
1089 zval *opts = NULL;
1090
1091 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
1092
1093 php_http_client_options_set_subr(getThis(), ZEND_STRL("cookies"), opts, 0);
1094
1095 RETVAL_ZVAL_FAST(getThis());
1096 }
1097
1098 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getCookies, 0, 0, 0)
1099 ZEND_END_ARG_INFO();
1100 static PHP_METHOD(HttpClient, getCookies)
1101 {
1102 if (SUCCESS == zend_parse_parameters_none()) {
1103 php_http_client_options_get_subr(getThis(), ZEND_STRL("cookies"), return_value);
1104 }
1105 }
1106
1107 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClient_getAvailableDrivers, 0, 0, 0)
1108 ZEND_END_ARG_INFO();
1109 static PHP_METHOD(HttpClient, getAvailableDrivers)
1110 {
1111 if (SUCCESS == zend_parse_parameters_none()) {
1112 array_init(return_value);
1113 php_http_client_driver_list(Z_ARRVAL_P(return_value));
1114 }
1115 }
1116
1117 static zend_function_entry php_http_client_methods[] = {
1118 PHP_ME(HttpClient, __construct, ai_HttpClient_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
1119 PHP_ME(HttpClient, reset, ai_HttpClient_reset, ZEND_ACC_PUBLIC)
1120 PHP_ME(HttpClient, enqueue, ai_HttpClient_enqueue, ZEND_ACC_PUBLIC)
1121 PHP_ME(HttpClient, dequeue, ai_HttpClient_dequeue, ZEND_ACC_PUBLIC)
1122 PHP_ME(HttpClient, requeue, ai_HttpClient_requeue, ZEND_ACC_PUBLIC)
1123 PHP_ME(HttpClient, count, ai_HttpClient_count, ZEND_ACC_PUBLIC)
1124 PHP_ME(HttpClient, send, ai_HttpClient_send, ZEND_ACC_PUBLIC)
1125 PHP_ME(HttpClient, once, ai_HttpClient_once, ZEND_ACC_PUBLIC)
1126 PHP_ME(HttpClient, wait, ai_HttpClient_wait, ZEND_ACC_PUBLIC)
1127 PHP_ME(HttpClient, getResponse, ai_HttpClient_getResponse, ZEND_ACC_PUBLIC)
1128 PHP_ME(HttpClient, getHistory, ai_HttpClient_getHistory, ZEND_ACC_PUBLIC)
1129 PHP_ME(HttpClient, enablePipelining, ai_HttpClient_enablePipelining, ZEND_ACC_PUBLIC)
1130 PHP_ME(HttpClient, enableEvents, ai_HttpClient_enableEvents, ZEND_ACC_PUBLIC)
1131 PHP_ME(HttpClient, notify, ai_HttpClient_notify, ZEND_ACC_PUBLIC)
1132 PHP_ME(HttpClient, attach, ai_HttpClient_attach, ZEND_ACC_PUBLIC)
1133 PHP_ME(HttpClient, detach, ai_HttpClient_detach, ZEND_ACC_PUBLIC)
1134 PHP_ME(HttpClient, getObservers, ai_HttpClient_getObservers, ZEND_ACC_PUBLIC)
1135 PHP_ME(HttpClient, getProgressInfo, ai_HttpClient_getProgressInfo, ZEND_ACC_PUBLIC)
1136 PHP_ME(HttpClient, getTransferInfo, ai_HttpClient_getTransferInfo, ZEND_ACC_PUBLIC)
1137 PHP_ME(HttpClient, setOptions, ai_HttpClient_setOptions, ZEND_ACC_PUBLIC)
1138 PHP_ME(HttpClient, getOptions, ai_HttpClient_getOptions, ZEND_ACC_PUBLIC)
1139 PHP_ME(HttpClient, setSslOptions, ai_HttpClient_setSslOptions, ZEND_ACC_PUBLIC)
1140 PHP_ME(HttpClient, addSslOptions, ai_HttpClient_addSslOptions, ZEND_ACC_PUBLIC)
1141 PHP_ME(HttpClient, getSslOptions, ai_HttpClient_getSslOptions, ZEND_ACC_PUBLIC)
1142 PHP_ME(HttpClient, setCookies, ai_HttpClient_setCookies, ZEND_ACC_PUBLIC)
1143 PHP_ME(HttpClient, addCookies, ai_HttpClient_addCookies, ZEND_ACC_PUBLIC)
1144 PHP_ME(HttpClient, getCookies, ai_HttpClient_getCookies, ZEND_ACC_PUBLIC)
1145 PHP_ME(HttpClient, getAvailableDrivers, ai_HttpClient_getAvailableDrivers, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
1146 EMPTY_FUNCTION_ENTRY
1147 };
1148
1149 PHP_MINIT_FUNCTION(http_client)
1150 {
1151 zend_class_entry ce = {0};
1152
1153 INIT_NS_CLASS_ENTRY(ce, "http", "Client", php_http_client_methods);
1154 php_http_client_class_entry = zend_register_internal_class_ex(&ce, NULL);
1155 php_http_client_class_entry->create_object = php_http_client_object_new;
1156 zend_class_implements(php_http_client_class_entry, 2, spl_ce_SplSubject, spl_ce_Countable);
1157 memcpy(&php_http_client_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1158 php_http_client_object_handlers.offset = XtOffsetOf(php_http_client_object_t, zo);
1159 php_http_client_object_handlers.free_obj = php_http_client_object_free;
1160 php_http_client_object_handlers.clone_obj = NULL;
1161 zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("observers"), ZEND_ACC_PRIVATE);
1162 zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("options"), ZEND_ACC_PROTECTED);
1163 zend_declare_property_null(php_http_client_class_entry, ZEND_STRL("history"), ZEND_ACC_PROTECTED);
1164 zend_declare_property_bool(php_http_client_class_entry, ZEND_STRL("recordHistory"), 0, ZEND_ACC_PUBLIC);
1165
1166 zend_hash_init(&php_http_client_drivers, 2, NULL, php_http_client_driver_hash_dtor, 1);
1167
1168 return SUCCESS;
1169 }
1170
1171 PHP_MSHUTDOWN_FUNCTION(http_client)
1172 {
1173 zend_hash_destroy(&php_http_client_drivers);
1174 return SUCCESS;
1175 }
1176
1177 /*
1178 * Local variables:
1179 * tab-width: 4
1180 * c-basic-offset: 4
1181 * End:
1182 * vim600: noet sw=4 ts=4 fdm=marker
1183 * vim<600: noet sw=4 ts=4
1184 */