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