* split into more reasonable modules
[m6w6/ext-http] / http_methods.c
1 /*
2 +----------------------------------------------------------------------+
3 | PECL :: http |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.0 of the PHP license, that |
6 | is bundled with this package in the file LICENSE, and is available |
7 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
8 | If you did not receive a copy of the PHP license and are unable to |
9 | obtain it through the world-wide-web, please send a note to |
10 | license@php.net so we can mail you a copy immediately. |
11 +----------------------------------------------------------------------+
12 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
13 +----------------------------------------------------------------------+
14 */
15
16 /* $Id$ */
17
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22 #include "php.h"
23 #include "php_http.h"
24 #include "php_http_api.h"
25 #include "php_http_curl_api.h"
26 #include "ext/standard/php_smart_str.h"
27
28 #ifdef ZEND_ENGINE_2
29
30 /* {{{ HTTPi_Response */
31
32 /* {{{ proto void HTTPi_Response::__construct(bool cache, bool gzip)
33 *
34 */
35 PHP_METHOD(HTTPi_Response, __construct)
36 {
37 zend_bool do_cache = 0, do_gzip = 0;
38 getObject(httpi_response_object, obj);
39
40 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &do_cache, &do_gzip)) {
41 // throw exception
42 return;
43 }
44
45 UPD_PROP(obj, long, cache, do_cache);
46 UPD_PROP(obj, long, gzip, do_gzip);
47 }
48 /* }}} */
49
50 /* {{{ proto bool HTTPi_Response::setCache(bool cache)
51 *
52 */
53 PHP_METHOD(HTTPi_Response, setCache)
54 {
55 zend_bool do_cache = 0;
56 getObject(httpi_response_object, obj);
57
58 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
59 RETURN_FALSE;
60 }
61
62 UPD_PROP(obj, long, cache, do_cache);
63 RETURN_TRUE;
64 }
65 /* }}} */
66
67 /* {{{ proto bool HTTPi_Response::getCache()
68 *
69 */
70 PHP_METHOD(HTTPi_Response, getCache)
71 {
72 zval *do_cache = NULL;
73 getObject(httpi_response_object, obj);
74
75 NO_ARGS;
76
77 do_cache = GET_PROP(obj, cache);
78 RETURN_BOOL(Z_LVAL_P(do_cache));
79 }
80 /* }}}*/
81
82 /* {{{ proto bool HTTPi_Response::setGzip(bool gzip)
83 *
84 */
85 PHP_METHOD(HTTPi_Response, setGzip)
86 {
87 zend_bool do_gzip = 0;
88 getObject(httpi_response_object, obj);
89
90 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
91 RETURN_FALSE;
92 }
93
94 UPD_PROP(obj, long, gzip, do_gzip);
95 RETURN_TRUE;
96 }
97 /* }}} */
98
99 /* {{{ proto bool HTTPi_Response::getGzip()
100 *
101 */
102 PHP_METHOD(HTTPi_Response, getGzip)
103 {
104 zval *do_gzip = NULL;
105 getObject(httpi_response_object, obj);
106
107 NO_ARGS;
108
109 do_gzip = GET_PROP(obj, gzip);
110 RETURN_BOOL(Z_LVAL_P(do_gzip));
111 }
112 /* }}} */
113
114 /* {{{ proto bool HTTPi_Response::setCacheControl(string control[, bool raw = false])
115 *
116 */
117 PHP_METHOD(HTTPi_Response, setCacheControl)
118 {
119 char *ccontrol;
120 int cc_len;
121 zend_bool raw = 0;
122 getObject(httpi_response_object, obj);
123
124 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &ccontrol, &cc_len, &raw)) {
125 RETURN_FALSE;
126 }
127
128 if ((!raw) && (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache"))) {
129 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
130 RETURN_FALSE;
131 }
132
133 UPD_PROP(obj, long, raw_cache_header, raw);
134 UPD_PROP(obj, string, cacheControl, ccontrol);
135 RETURN_TRUE;
136 }
137 /* }}} */
138
139 /* {{{ proto string HTTPi_Response::getCacheControl()
140 *
141 */
142 PHP_METHOD(HTTPi_Response, getCacheControl)
143 {
144 zval *ccontrol;
145 getObject(httpi_response_object, obj);
146
147 NO_ARGS;
148
149 ccontrol = GET_PROP(obj, cacheControl);
150 RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
151 }
152 /* }}} */
153
154 /* {{{ proto bool HTTPi::setContentType(string content_type)
155 *
156 */
157 PHP_METHOD(HTTPi_Response, setContentType)
158 {
159 char *ctype;
160 int ctype_len;
161 getObject(httpi_response_object, obj);
162
163 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
164 RETURN_FALSE;
165 }
166
167 if (!strchr(ctype, '/')) {
168 php_error_docref(NULL TSRMLS_CC, E_WARNING,
169 "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
170 RETURN_FALSE;
171 }
172
173 UPD_PROP(obj, string, contentType, ctype);
174
175 RETURN_TRUE;
176 }
177 /* }}} */
178
179 /* {{{ proto string HTTPi_Response::getContentType()
180 *
181 */
182 PHP_METHOD(HTTPi_Response, getContentType)
183 {
184 zval *ctype;
185 getObject(httpi_response_object, obj);
186
187 NO_ARGS;
188
189 ctype = GET_PROP(obj, contentType);
190 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
191 }
192 /* }}} */
193
194 /* {{{ proto bool HTTPi_Response::setContentDisposition(string filename[, bool inline = false])
195 *
196 */
197 PHP_METHOD(HTTPi_Response, setContentDisposition)
198 {
199 char *file;
200 int file_len;
201 zend_bool is_inline = 0;
202 getObject(httpi_response_object, obj);
203
204 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &is_inline)) {
205 RETURN_FALSE;
206 }
207
208 UPD_PROP(obj, string, dispoFile, file);
209 UPD_PROP(obj, long, dispoInline, is_inline);
210 RETURN_TRUE;
211 }
212 /* }}} */
213
214 /* {{{ proto array HTTPi_Response::getContentDisposition()
215 *
216 */
217 PHP_METHOD(HTTPi_Response, getContentDisposition)
218 {
219 zval *file;
220 zval *is_inline;
221 getObject(httpi_response_object, obj);
222
223 if (ZEND_NUM_ARGS()) {
224 WRONG_PARAM_COUNT;
225 }
226
227 file = GET_PROP(obj, dispoFile);
228 is_inline = GET_PROP(obj, dispoInline);
229
230 array_init(return_value);
231 add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
232 add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
233 }
234 /* }}} */
235
236 /* {{{ proto bool HTTPi_Response::setETag(string etag)
237 *
238 */
239 PHP_METHOD(HTTPi_Response, setETag)
240 {
241 char *etag;
242 int etag_len;
243 getObject(httpi_response_object, obj);
244
245 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
246 RETURN_FALSE;
247 }
248
249 UPD_PROP(obj, string, eTag, etag);
250 RETURN_TRUE;
251 }
252 /* }}} */
253
254 /* {{{ proto string HTTPi_Response::getETag()
255 *
256 */
257 PHP_METHOD(HTTPi_Response, getETag)
258 {
259 zval *etag;
260 getObject(httpi_response_object, obj);
261
262 NO_ARGS;
263
264 etag = GET_PROP(obj, eTag);
265 RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
266 }
267 /* }}} */
268
269 /* {{{ proto bool HTTPi_Response::setData(string data)
270 *
271 */
272 PHP_METHOD(HTTPi_Response, setData)
273 {
274 zval *the_data;
275 char *etag;
276 getObject(httpi_response_object, obj);
277
278 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_data)) {
279 RETURN_FALSE;
280 }
281
282 convert_to_string_ex(&the_data);
283 SET_PROP(obj, data, the_data);
284 UPD_PROP(obj, long, lastModified, http_lmod(the_data, SEND_DATA));
285 UPD_PROP(obj, long, send_mode, SEND_DATA);
286 RETURN_TRUE;
287 }
288 /* }}} */
289
290 /* {{{ proto string HTTPi_Response::getData()
291 *
292 */
293 PHP_METHOD(HTTPi_Response, getData)
294 {
295 zval *the_data;
296 getObject(httpi_response_object, obj);
297
298 NO_ARGS;
299
300 the_data = GET_PROP(obj, data);
301 RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
302 }
303 /* }}} */
304
305 /* {{{ proto bool HTTPi_Response::setStream(resource stream)
306 *
307 */
308 PHP_METHOD(HTTPi_Response, setStream)
309 {
310 zval *the_stream;
311 php_stream *the_real_stream;
312 char *etag;
313 getObject(httpi_response_object, obj);
314
315 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
316 RETURN_FALSE;
317 }
318
319 php_stream_from_zval(the_real_stream, &the_stream);
320
321 SET_PROP(obj, stream, the_stream);
322 UPD_PROP(obj, long, lastModified, http_lmod(the_real_stream, SEND_RSRC));
323 UPD_PROP(obj, long, send_mode, SEND_RSRC);
324 RETURN_TRUE;
325 }
326 /* }}} */
327
328 /* {{{ proto resource HTTPi_Response::getStream()
329 *
330 */
331 PHP_METHOD(HTTPi_Response, getStream)
332 {
333 zval *the_stream;
334 getObject(httpi_response_object, obj);
335
336 NO_ARGS;
337
338 the_stream = GET_PROP(obj, stream);
339 RETURN_RESOURCE(Z_LVAL_P(the_stream));
340 }
341 /* }}} */
342
343 /* {{{ proto bool HTTPi_Response::setFile(string file)
344 *
345 */
346 PHP_METHOD(HTTPi_Response, setFile)
347 {
348 zval *the_file;
349 getObject(httpi_response_object, obj);
350
351 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_file)) {
352 RETURN_FALSE;
353 }
354
355 convert_to_string_ex(&the_file);
356
357 UPD_PROP(obj, string, file, Z_STRVAL_P(the_file));
358 UPD_PROP(obj, long, lastModified, http_lmod(the_file, -1));
359 UPD_PROP(obj, long, send_mode, -1);
360 RETURN_TRUE;
361 }
362 /* }}} */
363
364 /* {{{ proto string HTTPi_Response::getFile()
365 *
366 */
367 PHP_METHOD(HTTPi_Response, getFile)
368 {
369 zval *the_file;
370 getObject(httpi_response_object, obj);
371
372 NO_ARGS;
373
374 the_file = GET_PROP(obj, file);
375 RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
376 }
377 /* }}} */
378
379 PHP_METHOD(HTTPi_Response, send)
380 {
381 zval *do_cache, *do_gzip;
382 getObject(httpi_response_object, obj);
383
384 do_cache = GET_PROP(obj, cache);
385 do_gzip = GET_PROP(obj, gzip);
386
387 /* caching */
388 if (Z_LVAL_P(do_cache)) {
389 zval *cctrl, *etag, *lmod, *ccraw;
390
391 etag = GET_PROP(obj, eTag);
392 lmod = GET_PROP(obj, lastModified);
393 cctrl = GET_PROP(obj, cacheControl);
394 ccraw = GET_PROP(obj, raw_cache_header);
395
396 if (Z_LVAL_P(ccraw)) {
397 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
398 http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
399 } else {
400 char cc_header[42] = {0};
401 sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
402 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_header, strlen(cc_header));
403 http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_header, strlen(cc_header));
404 }
405 }
406
407 /* gzip */
408 if (Z_LVAL_P(do_gzip)) {
409 /* ... */
410 }
411
412 /* content type */
413 {
414 zval *ctype = GET_PROP(obj, contentType);
415 if (Z_STRLEN_P(ctype)) {
416 http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
417 } else {
418 http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
419 }
420 }
421
422 /* content disposition */
423 {
424 zval *dispo_file = GET_PROP(obj, dispoFile);
425 if (Z_STRLEN_P(dispo_file)) {
426 zval *dispo_inline = GET_PROP(obj, dispoInline);
427 http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), Z_LVAL_P(dispo_inline));
428 }
429 }
430
431 /* send */
432 {
433 zval *send_mode = GET_PROP(obj, send_mode);
434 switch (Z_LVAL_P(send_mode))
435 {
436 case SEND_DATA:
437 {
438 RETURN_SUCCESS(http_send_data(GET_PROP(obj, data)));
439 }
440
441 case SEND_RSRC:
442 {
443 php_stream *the_real_stream;
444 zval *the_stream = GET_PROP(obj, stream);
445 php_stream_from_zval(the_real_stream, &the_stream);
446 RETURN_SUCCESS(http_send_stream(the_real_stream));
447 }
448
449 default:
450 {
451 RETURN_SUCCESS(http_send_file(GET_PROP(obj, file)));
452 }
453 }
454 }
455 }
456 /* }}} */
457 /* }}} */
458
459 #ifdef HTTP_HAVE_CURL
460 /* {{{ HTTPi_Request */
461
462 /* {{{ proto void HTTPi_Request::__construct([string url[, long request_method = HTTP_GET]])
463 *
464 */
465 PHP_METHOD(HTTPi_Request, __construct)
466 {
467 char *URL = NULL;
468 int URL_len;
469 long meth = -1;
470 zval *info, *opts, *resp;
471 getObject(httpi_request_object, obj);
472
473 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
474 return;
475 }
476
477 INIT_PARR(obj, options);
478 INIT_PARR(obj, responseInfo);
479 INIT_PARR(obj, responseData);
480 INIT_PARR(obj, postData);
481 INIT_PARR(obj, postFiles);
482
483 if (URL) {
484 UPD_PROP(obj, string, url, URL);
485 }
486 if (meth > -1) {
487 UPD_PROP(obj, long, method, meth);
488 }
489 }
490 /* }}} */
491
492 /* {{{ proto void HTTPi_Request::__destruct()
493 *
494 */
495 PHP_METHOD(HTTPi_Request, __destruct)
496 {
497 getObject(httpi_request_object, obj);
498
499 NO_ARGS;
500
501 FREE_PARR(obj, options);
502 FREE_PARR(obj, responseInfo);
503 FREE_PARR(obj, responseData);
504 FREE_PARR(obj, postData);
505 FREE_PARR(obj, postFiles);
506 }
507 /* }}} */
508
509 /* {{{ proto bool HTTPi_Request::setOptions(array options)
510 *
511 */
512 PHP_METHOD(HTTPi_Request, setOptions)
513 {
514 zval *opts, *old_opts, **opt;
515 getObject(httpi_request_object, obj);
516
517 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
518 RETURN_FALSE;
519 }
520
521 old_opts = GET_PROP(obj, options);
522
523 /* headers and cookies need extra attention -- thus cannot use zend_hash_merge() or php_array_merge() directly */
524 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(opts));
525 zend_hash_get_current_data(Z_ARRVAL_P(opts), (void **) &opt) == SUCCESS;
526 zend_hash_move_forward(Z_ARRVAL_P(opts))) {
527 char *key;
528 long idx;
529 if (HASH_KEY_IS_STRING == zend_hash_get_current_key(Z_ARRVAL_P(opts), &key, &idx, 0)) {
530 if (!strcmp(key, "headers")) {
531 zval **headers;
532 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
533 array_merge(*opt, *headers);
534 continue;
535 }
536 } else if (!strcmp(key, "cookies")) {
537 zval **cookies;
538 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
539 array_merge(*opt, *cookies);
540 continue;
541 }
542 }
543 zval_add_ref(opt);
544 add_assoc_zval(old_opts, key, *opt);
545 }
546 }
547 RETURN_TRUE;
548 }
549 /* }}} */
550
551 /* {{{ proto array HTTPi_Request::getOptions()
552 *
553 */
554 PHP_METHOD(HTTPi_Request, getOptions)
555 {
556 zval *opts;
557 getObject(httpi_request_object, obj);
558
559 NO_ARGS;
560
561 opts = GET_PROP(obj, options);
562 array_init(return_value);
563 array_copy(opts, return_value);
564 }
565 /* }}} */
566
567 /* {{{ proto bool HTTPi_Request::setURL(string url)
568 *
569 */
570 PHP_METHOD(HTTPi_Request, setURL)
571 {
572 char *URL = NULL;
573 int URL_len;
574 getObject(httpi_request_object, obj);
575
576 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
577 RETURN_FALSE;
578 }
579
580 UPD_PROP(obj, string, url, URL);
581 RETURN_TRUE;
582 }
583 /* }}} */
584
585 /* {{{ proto string HTTPi_Request::getUrl()
586 *
587 */
588 PHP_METHOD(HTTPi_Request, getURL)
589 {
590 zval *URL;
591 getObject(httpi_request_object, obj);
592
593 NO_ARGS;
594
595 URL = GET_PROP(obj, url);
596 RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
597 }
598 /* }}} */
599
600 /* {{{ proto bool HTTPi_Request::setMethod(long request_method)
601 *
602 */
603 PHP_METHOD(HTTPi_Request, setMethod)
604 {
605 long meth;
606 getObject(httpi_request_object, obj);
607
608 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
609 RETURN_FALSE;
610 }
611
612 UPD_PROP(obj, long, method, meth);
613 RETURN_TRUE;
614 }
615 /* }}} */
616
617 /* {{{ proto long HTTPi_Request::getMethod()
618 *
619 */
620 PHP_METHOD(HTTPi_Request, getMethod)
621 {
622 zval *meth;
623 getObject(httpi_request_object, obj);
624
625 NO_ARGS;
626
627 meth = GET_PROP(obj, method);
628 RETURN_LONG(Z_LVAL_P(meth));
629 }
630 /* }}} */
631
632 /* {{{ proto bool HTTPi_Request::setContentType(string content_type)
633 *
634 */
635 PHP_METHOD(HTTPi_Request, setContentType)
636 {
637 char *ctype;
638 int ct_len;
639 getObject(httpi_request_object, obj);
640
641 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
642 RETURN_FALSE;
643 }
644
645 if (!strchr(ctype, '/')) {
646 php_error_docref(NULL TSRMLS_CC, E_WARNING,
647 "Content-Type '%s' doesn't seem to contain a primary and a secondary part",
648 ctype);
649 RETURN_FALSE;
650 }
651
652 UPD_PROP(obj, string, contentType, ctype);
653 RETURN_TRUE;
654 }
655 /* }}} */
656
657 /* {{{ proto string HTTPi_Request::getContentType()
658 *
659 */
660 PHP_METHOD(HTTPi_Request, getContentType)
661 {
662 zval *ctype;
663 getObject(httpi_request_object, obj);
664
665 NO_ARGS;
666
667 ctype = GET_PROP(obj, contentType);
668 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
669 }
670 /* }}} */
671
672 /* {{{ proto bool HTTPi_Request::setQueryData(mixed query_data)
673 *
674 */
675 PHP_METHOD(HTTPi_Request, setQueryData)
676 {
677 zval *qdata;
678 getObject(httpi_request_object, obj);
679
680 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &qdata)) {
681 RETURN_FALSE;
682 }
683
684 if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
685 smart_str qstr = {0};
686 HTTP_URL_ARGSEP_OVERRIDE;
687 if (SUCCESS != php_url_encode_hash_ex(HASH_OF(qdata), &qstr, NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)) {
688 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
689 if (qstr.c) {
690 efree(qstr.c);
691 }
692 HTTP_URL_ARGSEP_RESTORE;
693 RETURN_FALSE;
694 }
695 HTTP_URL_ARGSEP_RESTORE;
696 smart_str_0(&qstr);
697 UPD_PROP(obj, string, queryData, qstr.c);
698 efree(qstr.c);
699 RETURN_TRUE;
700 }
701
702 convert_to_string(qdata);
703 UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
704 RETURN_TRUE;
705 }
706 /* }}} */
707
708 /* {{{ proto string HTTPi_Request::getQueryData()
709 *
710 */
711 PHP_METHOD(HTTPi_Request, getQueryData)
712 {
713 zval *qdata;
714 getObject(httpi_request_object, obj);
715
716 NO_ARGS;
717
718 qdata = GET_PROP(obj, queryData);
719 RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
720 }
721 /* }}} */
722
723 /* {{{ proto bool HTTPi_Request::addQueryData(array query_params)
724 *
725 */
726 PHP_METHOD(HTTPi_Request, addQueryData)
727 {
728 zval *qdata, *old_qdata;
729 smart_str qstr = {0};
730 char *separator;
731 getObject(httpi_request_object, obj);
732
733 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
734 RETURN_FALSE;
735 }
736
737 old_qdata = GET_PROP(obj, queryData);
738 if (Z_STRLEN_P(old_qdata)) {
739 smart_str_appendl(&qstr, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata));
740 }
741
742 HTTP_URL_ARGSEP_OVERRIDE;
743 if (SUCCESS != php_url_encode_hash_ex(HASH_OF(qdata), &qstr, NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)) {
744 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
745 if (qstr.c) {
746 efree(qstr.c);
747 }
748 HTTP_URL_ARGSEP_RESTORE;
749 RETURN_FALSE;
750 }
751 HTTP_URL_ARGSEP_RESTORE;
752
753 smart_str_0(&qstr);
754
755 UPD_PROP(obj, string, queryData, qstr.c);
756 efree(qstr.c);
757 RETURN_TRUE;
758 }
759 /* }}} */
760
761 /* {{{ proto void HTTPi_Request::unsetQueryData()
762 *
763 */
764 PHP_METHOD(HTTPi_Request, unsetQueryData)
765 {
766 getObject(httpi_request_object, obj);
767
768 NO_ARGS;
769
770 UPD_PROP(obj, string, queryData, "");
771 }
772 /* }}} */
773
774 /* {{{ proto bool HTTPi_Request::addPostData(array post_data)
775 *
776 */
777 PHP_METHOD(HTTPi_Request, addPostData)
778 {
779 zval *post, *post_data;
780 getObject(httpi_request_object, obj);
781
782 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
783 RETURN_FALSE;
784 }
785
786 post = GET_PROP(obj, postData);
787 array_merge(post_data, post);
788
789 RETURN_TRUE;
790 }
791 /* }}} */
792
793 /* {{{ proto bool HTTPi_Request::setPostData(array post_data)
794 *
795 */
796 PHP_METHOD(HTTPi_Request, setPostData)
797 {
798 zval *post, *post_data;
799 getObject(httpi_request_object, obj);
800
801 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
802 RETURN_FALSE;
803 }
804
805 post = GET_PROP(obj, postData);
806 zend_hash_clean(Z_ARRVAL_P(post));
807 array_copy(post_data, post);
808
809 RETURN_TRUE;
810 }
811 /* }}}*/
812
813 /* {{{ proto array HTTPi_Request::getPostData()
814 *
815 */
816 PHP_METHOD(HTTPi_Request, getPostData)
817 {
818 zval *post_data;
819 getObject(httpi_request_object, obj);
820
821 NO_ARGS;
822
823 post_data = GET_PROP(obj, postData);
824 array_init(return_value);
825 array_copy(post_data, return_value);
826 }
827 /* }}} */
828
829 /* {{{ proto void HTTPi_Request::unsetPostData()
830 *
831 */
832 PHP_METHOD(HTTPi_Request, unsetPostData)
833 {
834 zval *post_data;
835 getObject(httpi_request_object, obj);
836
837 NO_ARGS;
838
839 post_data = GET_PROP(obj, postData);
840 zend_hash_clean(Z_ARRVAL_P(post_data));
841 }
842 /* }}} */
843
844 /* {{{ proto bool HTTPi_Request::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
845 *
846 */
847 PHP_METHOD(HTTPi_Request, addPostFile)
848 {
849 zval *files, *entry;
850 char *name, *file, *type = NULL;
851 int name_len, file_len, type_len = 0;
852 getObject(httpi_request_object, obj);
853
854 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
855 RETURN_FALSE;
856 }
857
858 if (type_len) {
859 if (!strchr(type, '/')) {
860 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
861 RETURN_FALSE;
862 }
863 } else {
864 type = "application/x-octetstream";
865 type_len = sizeof("application/x-octetstream") - 1;
866 }
867
868 MAKE_STD_ZVAL(entry);
869 array_init(entry);
870
871 add_assoc_stringl(entry, "name", name, name_len, 1);
872 add_assoc_stringl(entry, "type", type, type_len, 1);
873 add_assoc_stringl(entry, "file", file, file_len, 1);
874
875 files = GET_PROP(obj, postFiles);
876 add_next_index_zval(files, entry);
877
878 RETURN_TRUE;
879 }
880 /* }}} */
881
882 /* {{{ proto array HTTPi_Request::getPostFiles()
883 *
884 */
885 PHP_METHOD(HTTPi_Request, getPostFiles)
886 {
887 zval *files;
888 getObject(httpi_request_object, obj);
889
890 NO_ARGS;
891
892 files = GET_PROP(obj, postFiles);
893
894 array_init(return_value);
895 array_copy(files, return_value);
896 }
897 /* }}} */
898
899 /* {{{ proto void HTTPi_Request::unsetPostFiles()
900 *
901 */
902 PHP_METHOD(HTTPi_Request, unsetPostFiles)
903 {
904 zval *files;
905 getObject(httpi_request_object, obj);
906
907 NO_ARGS;
908
909 files = GET_PROP(obj, postFiles);
910 zend_hash_clean(Z_ARRVAL_P(files));
911 }
912 /* }}} */
913
914 /* {{{ proto array HTTPi_Request::getResponseData()
915 *
916 */
917 PHP_METHOD(HTTPi_Request, getResponseData)
918 {
919 zval *data;
920 getObject(httpi_request_object, obj);
921
922 NO_ARGS;
923
924 data = GET_PROP(obj, responseData);
925 array_init(return_value);
926 array_copy(data, return_value);
927 }
928 /* }}} */
929
930 /* {{{ proto array HTTPi_Request::getResponseHeaders()
931 *
932 */
933 PHP_METHOD(HTTPi_Request, getResponseHeaders)
934 {
935 zval *data, **headers;
936 getObject(httpi_request_object, obj);
937
938 NO_ARGS;
939
940 array_init(return_value);
941 data = GET_PROP(obj, responseData);
942 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
943 array_copy(*headers, return_value);
944 }
945 }
946 /* }}} */
947
948 /* {{{ proto string HTTPi_Request::getResponseBody()
949 *
950 */
951 PHP_METHOD(HTTPi_Request, getResponseBody)
952 {
953 zval *data, **body;
954 getObject(httpi_request_object, obj);
955
956 NO_ARGS;
957
958 data = GET_PROP(obj, responseData);
959 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
960 RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
961 } else {
962 Z_TYPE_P(return_value) = IS_NULL;
963 }
964 }
965 /* }}} */
966
967 /* {{{ proto array HTTPi_Request::getResponseInfo()
968 *
969 */
970 PHP_METHOD(HTTPi_Request, getResponseInfo)
971 {
972 zval *info;
973 getObject(httpi_request_object, obj);
974
975 NO_ARGS;
976
977 info = GET_PROP(obj, responseInfo);
978 array_init(return_value);
979 array_copy(info, return_value);
980 }
981 /* }}}*/
982
983 /* {{{ proto bool HTTPi_Request::send()
984 *
985 */
986 PHP_METHOD(HTTPi_Request, send)
987 {
988 STATUS status = FAILURE;
989 zval *meth, *URL, *qdata, *opts, *info, *resp;
990 char *response_data, *request_uri;
991 size_t response_len;
992 getObject(httpi_request_object, obj);
993
994 NO_ARGS;
995
996 if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
997 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initilaize cURL");
998 RETURN_FALSE;
999 }
1000
1001 meth = GET_PROP(obj, method);
1002 URL = GET_PROP(obj, url);
1003 qdata = GET_PROP(obj, queryData);
1004 opts = GET_PROP(obj, options);
1005 info = GET_PROP(obj, responseInfo);
1006 resp = GET_PROP(obj, responseData);
1007
1008 // HTTP_URI_MAXLEN+1 big char *
1009 request_uri = http_absolute_uri(Z_STRVAL_P(URL), NULL);
1010
1011 if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
1012 if (!strchr(request_uri, '?')) {
1013 strcat(request_uri, "?");
1014 } else {
1015 strcat(request_uri, "&");
1016 }
1017 strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
1018 }
1019
1020 switch (Z_LVAL_P(meth))
1021 {
1022 case HTTP_GET:
1023 status = http_get_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1024 break;
1025
1026 case HTTP_HEAD:
1027 status = http_head_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1028 break;
1029
1030 case HTTP_POST:
1031 {
1032 zval *post_files, *post_data, **data;
1033
1034 post_files = GET_PROP(obj, postFiles);
1035 post_data = GET_PROP(obj, postData);
1036
1037 if (!zend_hash_num_elements(Z_ARRVAL_P(post_files))) {
1038
1039 /* urlencoded post */
1040 status = http_post_array_ex(obj->ch, request_uri, Z_ARRVAL_P(post_data), Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1041
1042 } else {
1043
1044 /*
1045 * multipart post
1046 */
1047 struct curl_httppost *http_post_data[2] = {NULL, NULL};
1048
1049 /* normal data */
1050 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(post_data));
1051 zend_hash_get_current_data(Z_ARRVAL_P(post_data), (void **) &data) == SUCCESS;
1052 zend_hash_move_forward(Z_ARRVAL_P(post_data))) {
1053
1054 char *key;
1055 long idx;
1056
1057 if (HASH_KEY_IS_STRING == zend_hash_get_current_key(Z_ARRVAL_P(post_data), &key, &idx, 0)) {
1058 convert_to_string_ex(data);
1059 curl_formadd(&http_post_data[0], &http_post_data[1],
1060 CURLFORM_COPYNAME, key,
1061 CURLFORM_COPYCONTENTS, Z_STRVAL_PP(data),
1062 CURLFORM_CONTENTSLENGTH, Z_STRLEN_PP(data),
1063 CURLFORM_END
1064 );
1065 }
1066 }
1067
1068 /* file data */
1069 for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(post_files));
1070 zend_hash_get_current_data(Z_ARRVAL_P(post_files), (void **) &data) == SUCCESS;
1071 zend_hash_move_forward(Z_ARRVAL_P(post_files))) {
1072
1073 zval **file, **type, **name;
1074
1075 if (
1076 SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "name", sizeof("name"), (void **) &name) &&
1077 SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &type) &&
1078 SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "file", sizeof("file"), (void **) &file)
1079 ) {
1080
1081 curl_formadd(&http_post_data[0], &http_post_data[1],
1082 CURLFORM_COPYNAME, Z_STRVAL_PP(name),
1083 CURLFORM_FILENAME, Z_STRVAL_PP(name),
1084 CURLFORM_FILE, Z_STRVAL_PP(file),
1085 CURLFORM_CONTENTTYPE, Z_STRVAL_PP(type),
1086 CURLFORM_END
1087 );
1088 }
1089 }
1090
1091 status = http_post_curldata_ex(obj->ch, request_uri, http_post_data[0], Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1092 curl_formfree(http_post_data[0]);
1093 }
1094 }
1095 break;
1096
1097 default:
1098 break;
1099 }
1100
1101 efree(request_uri);
1102
1103 /* final data handling */
1104 if (status != SUCCESS) {
1105 RETURN_FALSE;
1106 } else {
1107 zval *zheaders, *zbody;
1108
1109 MAKE_STD_ZVAL(zbody);
1110 MAKE_STD_ZVAL(zheaders)
1111 array_init(zheaders);
1112
1113 if (SUCCESS != http_split_response_ex(response_data, response_len, zheaders, zbody)) {
1114 zval_dtor(zheaders);
1115 efree(zheaders),
1116 efree(zbody);
1117 efree(response_data);
1118 RETURN_FALSE;
1119 }
1120
1121 add_assoc_zval(resp, "headers", zheaders);
1122 add_assoc_zval(resp, "body", zbody);
1123
1124 efree(response_data);
1125
1126 RETURN_TRUE;
1127 }
1128 /* */
1129 }
1130 /* }}} */
1131 /* }}} */
1132 #endif /* HTTP_HAVE_CURL */
1133
1134 #endif /* ZEND_ENGINE_2 */
1135
1136 /*
1137 * Local variables:
1138 * tab-width: 4
1139 * c-basic-offset: 4
1140 * End:
1141 * vim600: noet sw=4 ts=4 fdm=marker
1142 * vim<600: noet sw=4 ts=4
1143 */