1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Sterling Hughes <sterling@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "php.h"
28
29 #if HAVE_CURL
30
31 #include "php_curl.h"
32
33 #include <curl/curl.h>
34 #include <curl/multi.h>
35
36 #ifdef HAVE_SYS_SELECT_H
37 #include <sys/select.h>
38 #endif
39
40 #ifdef HAVE_SYS_TIME_H
41 #include <sys/time.h>
42 #endif
43
44 #ifdef HAVE_SYS_TYPES_H
45 #include <sys/types.h>
46 #endif
47
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #define SAVE_CURLM_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
53
54 /* {{{ proto resource curl_multi_init(void)
55 Returns a new cURL multi handle */
PHP_FUNCTION(curl_multi_init)56 PHP_FUNCTION(curl_multi_init)
57 {
58 php_curlm *mh;
59
60 if (zend_parse_parameters_none() == FAILURE) {
61 return;
62 }
63
64 mh = ecalloc(1, sizeof(php_curlm));
65 mh->multi = curl_multi_init();
66 mh->handlers = ecalloc(1, sizeof(php_curlm_handlers));
67
68 zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0);
69
70 RETURN_RES(zend_register_resource(mh, le_curl_multi_handle));
71 }
72 /* }}} */
73
74 /* {{{ proto int curl_multi_add_handle(resource mh, resource ch)
75 Add a normal cURL handle to a cURL multi handle */
PHP_FUNCTION(curl_multi_add_handle)76 PHP_FUNCTION(curl_multi_add_handle)
77 {
78 zval *z_mh;
79 zval *z_ch;
80 php_curlm *mh;
81 php_curl *ch;
82 zval tmp_val;
83 CURLMcode error = CURLM_OK;
84
85 ZEND_PARSE_PARAMETERS_START(2,2)
86 Z_PARAM_RESOURCE(z_mh)
87 Z_PARAM_RESOURCE(z_ch)
88 ZEND_PARSE_PARAMETERS_END();
89
90 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
91 RETURN_FALSE;
92 }
93
94 if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) {
95 RETURN_FALSE;
96 }
97
98 _php_curl_cleanup_handle(ch);
99
100 /* we want to create a copy of this zval that we store in the multihandle structure element "easyh" */
101 ZVAL_DUP(&tmp_val, z_ch);
102
103 zend_llist_add_element(&mh->easyh, &tmp_val);
104
105 error = curl_multi_add_handle(mh->multi, ch->cp);
106 SAVE_CURLM_ERROR(mh, error);
107
108 RETURN_LONG((zend_long) error);
109 }
110 /* }}} */
111
_php_curl_multi_cleanup_list(void * data)112 void _php_curl_multi_cleanup_list(void *data) /* {{{ */
113 {
114 zval *z_ch = (zval *)data;
115 php_curl *ch;
116
117 if (!z_ch) {
118 return;
119 }
120 if (!Z_RES_P(z_ch)->ptr) {
121 return;
122 }
123 if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) {
124 return;
125 }
126
127 zend_list_delete(Z_RES_P(z_ch));
128 }
129 /* }}} */
130
131 /* Used internally as comparison routine passed to zend_list_del_element */
curl_compare_resources(zval * z1,zval * z2)132 static int curl_compare_resources( zval *z1, zval *z2 ) /* {{{ */
133 {
134 return (Z_TYPE_P(z1) == Z_TYPE_P(z2) &&
135 Z_TYPE_P(z1) == IS_RESOURCE &&
136 Z_RES_P(z1) == Z_RES_P(z2));
137 }
138 /* }}} */
139
140 /* Used to find the php_curl resource for a given curl easy handle */
_php_curl_multi_find_easy_handle(php_curlm * mh,CURL * easy)141 static zval *_php_curl_multi_find_easy_handle(php_curlm *mh, CURL *easy) /* {{{ */
142 {
143 php_curl *tmp_ch;
144 zend_llist_position pos;
145 zval *pz_ch_temp;
146
147 for(pz_ch_temp = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch_temp;
148 pz_ch_temp = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
149
150 if ((tmp_ch = (php_curl *)zend_fetch_resource(Z_RES_P(pz_ch_temp), le_curl_name, le_curl)) == NULL) {
151 return NULL;
152 }
153
154 if (tmp_ch->cp == easy) {
155 return pz_ch_temp;
156 }
157 }
158
159 return NULL;
160 }
161 /* }}} */
162
163 /* {{{ proto int curl_multi_remove_handle(resource mh, resource ch)
164 Remove a multi handle from a set of cURL handles */
PHP_FUNCTION(curl_multi_remove_handle)165 PHP_FUNCTION(curl_multi_remove_handle)
166 {
167 zval *z_mh;
168 zval *z_ch;
169 php_curlm *mh;
170 php_curl *ch;
171 CURLMcode error = CURLM_OK;
172
173 ZEND_PARSE_PARAMETERS_START(2,2)
174 Z_PARAM_RESOURCE(z_mh)
175 Z_PARAM_RESOURCE(z_ch)
176 ZEND_PARSE_PARAMETERS_END();
177
178 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
179 RETURN_FALSE;
180 }
181
182 if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) {
183 RETURN_FALSE;
184 }
185
186 error = curl_multi_remove_handle(mh->multi, ch->cp);
187 SAVE_CURLM_ERROR(mh, error);
188
189 RETVAL_LONG((zend_long) error);
190 zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_resources);
191
192 }
193 /* }}} */
194
195 #if LIBCURL_VERSION_NUM < 0x071c00
_make_timeval_struct(struct timeval * to,double timeout)196 static void _make_timeval_struct(struct timeval *to, double timeout) /* {{{ */
197 {
198 unsigned long conv;
199
200 conv = (unsigned long) (timeout * 1000000.0);
201 to->tv_sec = conv / 1000000;
202 to->tv_usec = conv % 1000000;
203 }
204 /* }}} */
205 #endif
206
207 /* {{{ proto int curl_multi_select(resource mh[, double timeout])
208 Get all the sockets associated with the cURL extension, which can then be "selected" */
PHP_FUNCTION(curl_multi_select)209 PHP_FUNCTION(curl_multi_select)
210 {
211 zval *z_mh;
212 php_curlm *mh;
213 double timeout = 1.0;
214 #if LIBCURL_VERSION_NUM >= 0x071c00 /* Available since 7.28.0 */
215 int numfds = 0;
216 #else
217 fd_set readfds;
218 fd_set writefds;
219 fd_set exceptfds;
220 int maxfd;
221 struct timeval to;
222 #endif
223 CURLMcode error = CURLM_OK;
224
225 ZEND_PARSE_PARAMETERS_START(1,2)
226 Z_PARAM_RESOURCE(z_mh)
227 Z_PARAM_OPTIONAL
228 Z_PARAM_DOUBLE(timeout)
229 ZEND_PARSE_PARAMETERS_END();
230
231 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
232 RETURN_FALSE;
233 }
234
235 #if LIBCURL_VERSION_NUM >= 0x071c00 /* Available since 7.28.0 */
236 error = curl_multi_wait(mh->multi, NULL, 0, (unsigned long) (timeout * 1000.0), &numfds);
237 if (CURLM_OK != error) {
238 SAVE_CURLM_ERROR(mh, error);
239 RETURN_LONG(-1);
240 }
241
242 RETURN_LONG(numfds);
243 #else
244 _make_timeval_struct(&to, timeout);
245
246 FD_ZERO(&readfds);
247 FD_ZERO(&writefds);
248 FD_ZERO(&exceptfds);
249
250 error = curl_multi_fdset(mh->multi, &readfds, &writefds, &exceptfds, &maxfd);
251 SAVE_CURLM_ERROR(mh, error);
252
253 if (maxfd == -1) {
254 RETURN_LONG(-1);
255 }
256 RETURN_LONG(select(maxfd + 1, &readfds, &writefds, &exceptfds, &to));
257 #endif
258 }
259 /* }}} */
260
261 /* {{{ proto int curl_multi_exec(resource mh, int &still_running)
262 Run the sub-connections of the current cURL handle */
PHP_FUNCTION(curl_multi_exec)263 PHP_FUNCTION(curl_multi_exec)
264 {
265 zval *z_mh;
266 zval *z_still_running;
267 php_curlm *mh;
268 int still_running;
269 CURLMcode error = CURLM_OK;
270
271 ZEND_PARSE_PARAMETERS_START(2, 2)
272 Z_PARAM_RESOURCE(z_mh)
273 Z_PARAM_ZVAL_DEREF(z_still_running)
274 ZEND_PARSE_PARAMETERS_END();
275
276 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
277 RETURN_FALSE;
278 }
279
280 {
281 zend_llist_position pos;
282 php_curl *ch;
283 zval *pz_ch;
284
285 for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
286 pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
287
288 if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(pz_ch), le_curl_name, le_curl)) == NULL) {
289 RETURN_FALSE;
290 }
291
292 _php_curl_verify_handlers(ch, 1);
293 }
294 }
295
296 still_running = zval_get_long(z_still_running);
297 error = curl_multi_perform(mh->multi, &still_running);
298 zval_ptr_dtor(z_still_running);
299 ZVAL_LONG(z_still_running, still_running);
300
301 SAVE_CURLM_ERROR(mh, error);
302 RETURN_LONG((zend_long) error);
303 }
304 /* }}} */
305
306 /* {{{ proto string curl_multi_getcontent(resource ch)
307 Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set */
PHP_FUNCTION(curl_multi_getcontent)308 PHP_FUNCTION(curl_multi_getcontent)
309 {
310 zval *z_ch;
311 php_curl *ch;
312
313 ZEND_PARSE_PARAMETERS_START(1,1)
314 Z_PARAM_RESOURCE(z_ch)
315 ZEND_PARSE_PARAMETERS_END();
316
317 if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) {
318 RETURN_FALSE;
319 }
320
321 if (ch->handlers->write->method == PHP_CURL_RETURN) {
322 if (!ch->handlers->write->buf.s) {
323 RETURN_EMPTY_STRING();
324 }
325 smart_str_0(&ch->handlers->write->buf);
326 RETURN_STR_COPY(ch->handlers->write->buf.s);
327 }
328
329 RETURN_NULL();
330 }
331 /* }}} */
332
333 /* {{{ proto array curl_multi_info_read(resource mh [, long &msgs_in_queue])
334 Get information about the current transfers */
PHP_FUNCTION(curl_multi_info_read)335 PHP_FUNCTION(curl_multi_info_read)
336 {
337 zval *z_mh;
338 php_curlm *mh;
339 CURLMsg *tmp_msg;
340 int queued_msgs;
341 zval *zmsgs_in_queue = NULL;
342 php_curl *ch;
343
344 ZEND_PARSE_PARAMETERS_START(1, 2)
345 Z_PARAM_RESOURCE(z_mh)
346 Z_PARAM_OPTIONAL
347 Z_PARAM_ZVAL_DEREF(zmsgs_in_queue)
348 ZEND_PARSE_PARAMETERS_END();
349
350 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
351 RETURN_FALSE;
352 }
353
354 tmp_msg = curl_multi_info_read(mh->multi, &queued_msgs);
355 if (tmp_msg == NULL) {
356 RETURN_FALSE;
357 }
358 if (zmsgs_in_queue) {
359 zval_ptr_dtor(zmsgs_in_queue);
360 ZVAL_LONG(zmsgs_in_queue, queued_msgs);
361 }
362
363 array_init(return_value);
364 add_assoc_long(return_value, "msg", tmp_msg->msg);
365 add_assoc_long(return_value, "result", tmp_msg->data.result);
366
367 /* find the original easy curl handle */
368 {
369 zval *pz_ch = _php_curl_multi_find_easy_handle(mh, tmp_msg->easy_handle);
370 if (pz_ch != NULL) {
371 /* we are adding a reference to the underlying php_curl
372 resource, so we need to add one to the resource's refcount
373 in order to ensure it doesn't get destroyed when the
374 underlying curl easy handle goes out of scope.
375 Normally you would call zval_copy_ctor( pz_ch ), or
376 SEPARATE_ZVAL, but those create new zvals, which is already
377 being done in add_assoc_resource */
378 Z_ADDREF_P(pz_ch);
379
380 /* we must save result to be able to read error message */
381 ch = (php_curl*)zend_fetch_resource(Z_RES_P(pz_ch), le_curl_name, le_curl);
382 SAVE_CURL_ERROR(ch, tmp_msg->data.result);
383
384 /* add_assoc_resource automatically creates a new zval to
385 wrap the "resource" represented by the current pz_ch */
386
387 add_assoc_zval(return_value, "handle", pz_ch);
388 }
389 }
390 }
391 /* }}} */
392
393 /* {{{ proto void curl_multi_close(resource mh)
394 Close a set of cURL handles */
PHP_FUNCTION(curl_multi_close)395 PHP_FUNCTION(curl_multi_close)
396 {
397 zval *z_mh;
398 php_curlm *mh;
399
400 ZEND_PARSE_PARAMETERS_START(1,1)
401 Z_PARAM_RESOURCE(z_mh)
402 ZEND_PARSE_PARAMETERS_END();
403
404 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
405 RETURN_FALSE;
406 }
407
408 zend_list_close(Z_RES_P(z_mh));
409 }
410 /* }}} */
411
_php_curl_multi_close(zend_resource * rsrc)412 void _php_curl_multi_close(zend_resource *rsrc) /* {{{ */
413 {
414 php_curlm *mh = (php_curlm *)rsrc->ptr;
415 if (mh) {
416 zend_llist_position pos;
417 php_curl *ch;
418 zval *pz_ch;
419
420 for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
421 pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
422 /* ptr is NULL means it already be freed */
423 if (Z_RES_P(pz_ch)->ptr) {
424 if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(pz_ch), le_curl_name, le_curl))) {
425 _php_curl_verify_handlers(ch, 0);
426 }
427 }
428 }
429
430 curl_multi_cleanup(mh->multi);
431 zend_llist_clean(&mh->easyh);
432 if (mh->handlers->server_push) {
433 zval_ptr_dtor(&mh->handlers->server_push->func_name);
434 efree(mh->handlers->server_push);
435 }
436 if (mh->handlers) {
437 efree(mh->handlers);
438 }
439 efree(mh);
440 rsrc->ptr = NULL;
441 }
442 }
443 /* }}} */
444
445 /* {{{ proto int curl_multi_errno(resource mh)
446 Return an integer containing the last multi curl error number */
PHP_FUNCTION(curl_multi_errno)447 PHP_FUNCTION(curl_multi_errno)
448 {
449 zval *z_mh;
450 php_curlm *mh;
451
452 ZEND_PARSE_PARAMETERS_START(1,1)
453 Z_PARAM_RESOURCE(z_mh)
454 ZEND_PARSE_PARAMETERS_END();
455
456 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
457 RETURN_FALSE;
458 }
459
460 RETURN_LONG(mh->err.no);
461 }
462 /* }}} */
463
464 #if LIBCURL_VERSION_NUM >= 0x070c00 /* Available since 7.12.0 */
465 /* {{{ proto bool curl_multi_strerror(int code)
466 return string describing error code */
PHP_FUNCTION(curl_multi_strerror)467 PHP_FUNCTION(curl_multi_strerror)
468 {
469 zend_long code;
470 const char *str;
471
472 ZEND_PARSE_PARAMETERS_START(1,1)
473 Z_PARAM_LONG(code)
474 ZEND_PARSE_PARAMETERS_END();
475
476 str = curl_multi_strerror(code);
477 if (str) {
478 RETURN_STRING(str);
479 } else {
480 RETURN_NULL();
481 }
482 }
483 /* }}} */
484 #endif
485
486 #if LIBCURL_VERSION_NUM >= 0x072C00 /* Available since 7.44.0 */
487
_php_server_push_callback(CURL * parent_ch,CURL * easy,size_t num_headers,struct curl_pushheaders * push_headers,void * userp)488 static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_headers, struct curl_pushheaders *push_headers, void *userp) /* {{{ */
489 {
490 php_curl *ch;
491 php_curl *parent;
492 php_curlm *mh = (php_curlm *)userp;
493 size_t rval = CURL_PUSH_DENY;
494 php_curlm_server_push *t = mh->handlers->server_push;
495 zval *pz_parent_ch = NULL;
496 zval pz_ch;
497 zval headers;
498 zval retval;
499 zend_resource *res;
500 char *header;
501 int error;
502 zend_fcall_info fci = empty_fcall_info;
503
504 pz_parent_ch = _php_curl_multi_find_easy_handle(mh, parent_ch);
505 if (pz_parent_ch == NULL) {
506 return rval;
507 }
508
509 parent = (php_curl*)zend_fetch_resource(Z_RES_P(pz_parent_ch), le_curl_name, le_curl);
510
511 ch = alloc_curl_handle();
512 ch->cp = easy;
513 _php_setup_easy_copy_handlers(ch, parent);
514
515 Z_ADDREF_P(pz_parent_ch);
516
517 res = zend_register_resource(ch, le_curl);
518 ch->res = res;
519 ZVAL_RES(&pz_ch, res);
520
521 size_t i;
522 array_init(&headers);
523 for(i=0; i<num_headers; i++) {
524 header = curl_pushheader_bynum(push_headers, i);
525 add_next_index_string(&headers, header);
526 }
527
528 zend_fcall_info_init(&t->func_name, 0, &fci, &t->fci_cache, NULL, NULL);
529
530 zend_fcall_info_argn(
531 &fci, 3,
532 pz_parent_ch,
533 &pz_ch,
534 &headers
535 );
536
537 fci.retval = &retval;
538
539 error = zend_call_function(&fci, &t->fci_cache);
540 zend_fcall_info_args_clear(&fci, 1);
541 zval_dtor(&headers);
542
543 if (error == FAILURE) {
544 php_error_docref(NULL, E_WARNING, "Cannot call the CURLMOPT_PUSHFUNCTION");
545 } else if (!Z_ISUNDEF(retval)) {
546 if (CURL_PUSH_DENY != zval_get_long(&retval)) {
547 rval = CURL_PUSH_OK;
548
549 /* we want to create a copy of this zval that we store in the multihandle structure element "easyh" */
550 zval tmp_val;
551 ZVAL_DUP(&tmp_val, &pz_ch);
552 zend_llist_add_element(&mh->easyh, &tmp_val);
553 } else {
554 /* libcurl will free this easy handle, avoid double free */
555 ch->cp = NULL;
556 }
557 }
558
559 return rval;
560 }
561
562 #endif
563
564 #if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */
_php_curl_multi_setopt(php_curlm * mh,zend_long option,zval * zvalue,zval * return_value)565 static int _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue, zval *return_value) /* {{{ */
566 {
567 CURLMcode error = CURLM_OK;
568
569 switch (option) {
570 #if LIBCURL_VERSION_NUM >= 0x071000 /* 7.16.0 */
571 case CURLMOPT_PIPELINING:
572 #endif
573 #if LIBCURL_VERSION_NUM >= 0x071003 /* 7.16.3 */
574 case CURLMOPT_MAXCONNECTS:
575 #endif
576 #if LIBCURL_VERSION_NUM >= 0x071e00 /* 7.30.0 */
577 case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE:
578 case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE:
579 case CURLMOPT_MAX_HOST_CONNECTIONS:
580 case CURLMOPT_MAX_PIPELINE_LENGTH:
581 case CURLMOPT_MAX_TOTAL_CONNECTIONS:
582 #endif
583 error = curl_multi_setopt(mh->multi, option, zval_get_long(zvalue));
584 break;
585 #if LIBCURL_VERSION_NUM > 0x072D00 /* Available since 7.46.0 */
586 case CURLMOPT_PUSHFUNCTION:
587 if (mh->handlers->server_push == NULL) {
588 mh->handlers->server_push = ecalloc(1, sizeof(php_curlm_server_push));
589 } else if (!Z_ISUNDEF(mh->handlers->server_push->func_name)) {
590 zval_ptr_dtor(&mh->handlers->server_push->func_name);
591 mh->handlers->server_push->fci_cache = empty_fcall_info_cache;
592 }
593
594 ZVAL_COPY(&mh->handlers->server_push->func_name, zvalue);
595 mh->handlers->server_push->method = PHP_CURL_USER;
596 error = curl_multi_setopt(mh->multi, option, _php_server_push_callback);
597 if (error != CURLM_OK) {
598 return 0;
599 }
600 error = curl_multi_setopt(mh->multi, CURLMOPT_PUSHDATA, mh);
601 break;
602 #endif
603 default:
604 php_error_docref(NULL, E_WARNING, "Invalid curl multi configuration option");
605 error = CURLM_UNKNOWN_OPTION;
606 break;
607 }
608
609 SAVE_CURLM_ERROR(mh, error);
610 if (error != CURLM_OK) {
611 return 1;
612 } else {
613 return 0;
614 }
615 }
616 /* }}} */
617
618 /* {{{ proto int curl_multi_setopt(resource mh, int option, mixed value)
619 Set an option for the curl multi handle */
PHP_FUNCTION(curl_multi_setopt)620 PHP_FUNCTION(curl_multi_setopt)
621 {
622 zval *z_mh, *zvalue;
623 zend_long options;
624 php_curlm *mh;
625
626 ZEND_PARSE_PARAMETERS_START(3,3)
627 Z_PARAM_RESOURCE(z_mh)
628 Z_PARAM_LONG(options)
629 Z_PARAM_ZVAL(zvalue)
630 ZEND_PARSE_PARAMETERS_END();
631
632 if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
633 RETURN_FALSE;
634 }
635
636 if (!_php_curl_multi_setopt(mh, options, zvalue, return_value)) {
637 RETURN_TRUE;
638 } else {
639 RETURN_FALSE;
640 }
641 }
642 /* }}} */
643 #endif
644
645 #endif
646
647 /*
648 * Local variables:
649 * tab-width: 4
650 * c-basic-offset: 4
651 * End:
652 * vim600: noet sw=4 ts=4 fdm=marker
653 * vim<600: noet sw=4 ts=4
654 */
655