* add std defs header
[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 char *etag;
281 getObject(httpi_response_object, obj);
282
283 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_data)) {
284 RETURN_FALSE;
285 }
286
287 convert_to_string_ex(&the_data);
288 SET_PROP(obj, data, the_data);
289 UPD_PROP(obj, long, lastModified, http_lmod(the_data, SEND_DATA));
290 UPD_PROP(obj, long, send_mode, SEND_DATA);
291 RETURN_TRUE;
292 }
293 /* }}} */
294
295 /* {{{ proto string HTTPi_Response::getData()
296 *
297 */
298 PHP_METHOD(HTTPi_Response, getData)
299 {
300 zval *the_data;
301 getObject(httpi_response_object, obj);
302
303 NO_ARGS;
304
305 the_data = GET_PROP(obj, data);
306 RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
307 }
308 /* }}} */
309
310 /* {{{ proto bool HTTPi_Response::setStream(resource stream)
311 *
312 */
313 PHP_METHOD(HTTPi_Response, setStream)
314 {
315 zval *the_stream;
316 php_stream *the_real_stream;
317 char *etag;
318 getObject(httpi_response_object, obj);
319
320 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
321 RETURN_FALSE;
322 }
323
324 php_stream_from_zval(the_real_stream, &the_stream);
325
326 SET_PROP(obj, stream, the_stream);
327 UPD_PROP(obj, long, lastModified, http_lmod(the_real_stream, SEND_RSRC));
328 UPD_PROP(obj, long, send_mode, SEND_RSRC);
329 RETURN_TRUE;
330 }
331 /* }}} */
332
333 /* {{{ proto resource HTTPi_Response::getStream()
334 *
335 */
336 PHP_METHOD(HTTPi_Response, getStream)
337 {
338 zval *the_stream;
339 getObject(httpi_response_object, obj);
340
341 NO_ARGS;
342
343 the_stream = GET_PROP(obj, stream);
344 RETURN_RESOURCE(Z_LVAL_P(the_stream));
345 }
346 /* }}} */
347
348 /* {{{ proto bool HTTPi_Response::setFile(string file)
349 *
350 */
351 PHP_METHOD(HTTPi_Response, setFile)
352 {
353 zval *the_file;
354 getObject(httpi_response_object, obj);
355
356 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_file)) {
357 RETURN_FALSE;
358 }
359
360 convert_to_string_ex(&the_file);
361
362 UPD_PROP(obj, string, file, Z_STRVAL_P(the_file));
363 UPD_PROP(obj, long, lastModified, http_lmod(the_file, -1));
364 UPD_PROP(obj, long, send_mode, -1);
365 RETURN_TRUE;
366 }
367 /* }}} */
368
369 /* {{{ proto string HTTPi_Response::getFile()
370 *
371 */
372 PHP_METHOD(HTTPi_Response, getFile)
373 {
374 zval *the_file;
375 getObject(httpi_response_object, obj);
376
377 NO_ARGS;
378
379 the_file = GET_PROP(obj, file);
380 RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
381 }
382 /* }}} */
383
384 PHP_METHOD(HTTPi_Response, send)
385 {
386 zval *do_cache, *do_gzip;
387 getObject(httpi_response_object, obj);
388
389 do_cache = GET_PROP(obj, cache);
390 do_gzip = GET_PROP(obj, gzip);
391
392 /* caching */
393 if (Z_LVAL_P(do_cache)) {
394 zval *cctrl, *etag, *lmod, *ccraw;
395
396 etag = GET_PROP(obj, eTag);
397 lmod = GET_PROP(obj, lastModified);
398 cctrl = GET_PROP(obj, cacheControl);
399 ccraw = GET_PROP(obj, raw_cache_header);
400
401 if (Z_LVAL_P(ccraw)) {
402 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
403 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));
404 } else {
405 char cc_header[42] = {0};
406 sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
407 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_header, strlen(cc_header));
408 http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_header, strlen(cc_header));
409 }
410 }
411
412 /* gzip */
413 if (Z_LVAL_P(do_gzip)) {
414 /* ... */
415 }
416
417 /* content type */
418 {
419 zval *ctype = GET_PROP(obj, contentType);
420 if (Z_STRLEN_P(ctype)) {
421 http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
422 } else {
423 http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
424 }
425 }
426
427 /* content disposition */
428 {
429 zval *dispo_file = GET_PROP(obj, dispoFile);
430 if (Z_STRLEN_P(dispo_file)) {
431 zval *dispo_inline = GET_PROP(obj, dispoInline);
432 http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), Z_LVAL_P(dispo_inline));
433 }
434 }
435
436 /* send */
437 {
438 zval *send_mode = GET_PROP(obj, send_mode);
439 switch (Z_LVAL_P(send_mode))
440 {
441 case SEND_DATA:
442 {
443 RETURN_SUCCESS(http_send_data(GET_PROP(obj, data)));
444 }
445
446 case SEND_RSRC:
447 {
448 php_stream *the_real_stream;
449 zval *the_stream = GET_PROP(obj, stream);
450 php_stream_from_zval(the_real_stream, &the_stream);
451 RETURN_SUCCESS(http_send_stream(the_real_stream));
452 }
453
454 default:
455 {
456 RETURN_SUCCESS(http_send_file(GET_PROP(obj, file)));
457 }
458 }
459 }
460 }
461 /* }}} */
462 /* }}} */
463
464 #ifdef HTTP_HAVE_CURL
465 /* {{{ HTTPi_Request */
466
467 /* {{{ proto void HTTPi_Request::__construct([string url[, long request_method = HTTP_GET]])
468 *
469 */
470 PHP_METHOD(HTTPi_Request, __construct)
471 {
472 char *URL = NULL;
473 int URL_len;
474 long meth = -1;
475 zval *info, *opts, *resp;
476 getObject(httpi_request_object, obj);
477
478 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
479 return;
480 }
481
482 INIT_PARR(obj, options);
483 INIT_PARR(obj, responseInfo);
484 INIT_PARR(obj, responseData);
485 INIT_PARR(obj, postData);
486 INIT_PARR(obj, postFiles);
487
488 if (URL) {
489 UPD_PROP(obj, string, url, URL);
490 }
491 if (meth > -1) {
492 UPD_PROP(obj, long, method, meth);
493 }
494 }
495 /* }}} */
496
497 /* {{{ proto void HTTPi_Request::__destruct()
498 *
499 */
500 PHP_METHOD(HTTPi_Request, __destruct)
501 {
502 getObject(httpi_request_object, obj);
503
504 NO_ARGS;
505
506 FREE_PARR(obj, options);
507 FREE_PARR(obj, responseInfo);
508 FREE_PARR(obj, responseData);
509 FREE_PARR(obj, postData);
510 FREE_PARR(obj, postFiles);
511 }
512 /* }}} */
513
514 /* {{{ proto bool HTTPi_Request::setOptions(array options)
515 *
516 */
517 PHP_METHOD(HTTPi_Request, setOptions)
518 {
519 char *key = NULL;
520 long idx = 0;
521 zval *opts, *old_opts, **opt;
522 getObject(httpi_request_object, obj);
523
524 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
525 RETURN_FALSE;
526 }
527
528 old_opts = GET_PROP(obj, options);
529
530 /* headers and cookies need extra attention -- thus cannot use array_merge() directly */
531 FOREACH_KEYVAL(opts, key, idx, opt) {
532 if (key) {
533 if (!strcmp(key, "headers")) {
534 zval **headers;
535 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
536 array_merge(*opt, *headers);
537 continue;
538 }
539 } else if (!strcmp(key, "cookies")) {
540 zval **cookies;
541 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
542 array_merge(*opt, *cookies);
543 continue;
544 }
545 }
546 zval_add_ref(opt);
547 add_assoc_zval(old_opts, key, *opt);
548
549 /* reset */
550 key = NULL;
551 }
552 }
553
554 RETURN_TRUE;
555 }
556 /* }}} */
557
558 /* {{{ proto array HTTPi_Request::getOptions()
559 *
560 */
561 PHP_METHOD(HTTPi_Request, getOptions)
562 {
563 zval *opts;
564 getObject(httpi_request_object, obj);
565
566 NO_ARGS;
567
568 opts = GET_PROP(obj, options);
569 array_init(return_value);
570 array_copy(opts, return_value);
571 }
572 /* }}} */
573
574 /* {{{ proto bool HTTPi_Request::setURL(string url)
575 *
576 */
577 PHP_METHOD(HTTPi_Request, setURL)
578 {
579 char *URL = NULL;
580 int URL_len;
581 getObject(httpi_request_object, obj);
582
583 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
584 RETURN_FALSE;
585 }
586
587 UPD_PROP(obj, string, url, URL);
588 RETURN_TRUE;
589 }
590 /* }}} */
591
592 /* {{{ proto string HTTPi_Request::getUrl()
593 *
594 */
595 PHP_METHOD(HTTPi_Request, getURL)
596 {
597 zval *URL;
598 getObject(httpi_request_object, obj);
599
600 NO_ARGS;
601
602 URL = GET_PROP(obj, url);
603 RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
604 }
605 /* }}} */
606
607 /* {{{ proto bool HTTPi_Request::setMethod(long request_method)
608 *
609 */
610 PHP_METHOD(HTTPi_Request, setMethod)
611 {
612 long meth;
613 getObject(httpi_request_object, obj);
614
615 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
616 RETURN_FALSE;
617 }
618
619 UPD_PROP(obj, long, method, meth);
620 RETURN_TRUE;
621 }
622 /* }}} */
623
624 /* {{{ proto long HTTPi_Request::getMethod()
625 *
626 */
627 PHP_METHOD(HTTPi_Request, getMethod)
628 {
629 zval *meth;
630 getObject(httpi_request_object, obj);
631
632 NO_ARGS;
633
634 meth = GET_PROP(obj, method);
635 RETURN_LONG(Z_LVAL_P(meth));
636 }
637 /* }}} */
638
639 /* {{{ proto bool HTTPi_Request::setContentType(string content_type)
640 *
641 */
642 PHP_METHOD(HTTPi_Request, setContentType)
643 {
644 char *ctype;
645 int ct_len;
646 getObject(httpi_request_object, obj);
647
648 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
649 RETURN_FALSE;
650 }
651
652 if (!strchr(ctype, '/')) {
653 php_error_docref(NULL TSRMLS_CC, E_WARNING,
654 "Content-Type '%s' doesn't seem to contain a primary and a secondary part",
655 ctype);
656 RETURN_FALSE;
657 }
658
659 UPD_PROP(obj, string, contentType, ctype);
660 RETURN_TRUE;
661 }
662 /* }}} */
663
664 /* {{{ proto string HTTPi_Request::getContentType()
665 *
666 */
667 PHP_METHOD(HTTPi_Request, getContentType)
668 {
669 zval *ctype;
670 getObject(httpi_request_object, obj);
671
672 NO_ARGS;
673
674 ctype = GET_PROP(obj, contentType);
675 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
676 }
677 /* }}} */
678
679 /* {{{ proto bool HTTPi_Request::setQueryData(mixed query_data)
680 *
681 */
682 PHP_METHOD(HTTPi_Request, setQueryData)
683 {
684 zval *qdata;
685 char *query_data = NULL;
686 getObject(httpi_request_object, obj);
687
688 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &qdata)) {
689 RETURN_FALSE;
690 }
691
692 if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
693 if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) {
694 RETURN_FALSE;
695 }
696 UPD_PROP(obj, string, queryData, query_data);
697 efree(query_data);
698 RETURN_TRUE;
699 }
700
701 convert_to_string(qdata);
702 UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
703 RETURN_TRUE;
704 }
705 /* }}} */
706
707 /* {{{ proto string HTTPi_Request::getQueryData()
708 *
709 */
710 PHP_METHOD(HTTPi_Request, getQueryData)
711 {
712 zval *qdata;
713 getObject(httpi_request_object, obj);
714
715 NO_ARGS;
716
717 qdata = GET_PROP(obj, queryData);
718 RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
719 }
720 /* }}} */
721
722 /* {{{ proto bool HTTPi_Request::addQueryData(array query_params)
723 *
724 */
725 PHP_METHOD(HTTPi_Request, addQueryData)
726 {
727 zval *qdata, *old_qdata;
728 char *query_data = NULL;
729 getObject(httpi_request_object, obj);
730
731 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
732 RETURN_FALSE;
733 }
734
735 old_qdata = GET_PROP(obj, queryData);
736
737 if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, NULL)) {
738 RETURN_FALSE;
739 }
740
741 UPD_PROP(obj, string, queryData, query_data);
742 efree(query_data);
743
744 RETURN_TRUE;
745 }
746 /* }}} */
747
748 /* {{{ proto void HTTPi_Request::unsetQueryData()
749 *
750 */
751 PHP_METHOD(HTTPi_Request, unsetQueryData)
752 {
753 getObject(httpi_request_object, obj);
754
755 NO_ARGS;
756
757 UPD_PROP(obj, string, queryData, "");
758 }
759 /* }}} */
760
761 /* {{{ proto bool HTTPi_Request::addPostData(array post_data)
762 *
763 */
764 PHP_METHOD(HTTPi_Request, addPostData)
765 {
766 zval *post, *post_data;
767 getObject(httpi_request_object, obj);
768
769 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
770 RETURN_FALSE;
771 }
772
773 post = GET_PROP(obj, postData);
774 array_merge(post_data, post);
775
776 RETURN_TRUE;
777 }
778 /* }}} */
779
780 /* {{{ proto bool HTTPi_Request::setPostData(array post_data)
781 *
782 */
783 PHP_METHOD(HTTPi_Request, setPostData)
784 {
785 zval *post, *post_data;
786 getObject(httpi_request_object, obj);
787
788 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
789 RETURN_FALSE;
790 }
791
792 post = GET_PROP(obj, postData);
793 zend_hash_clean(Z_ARRVAL_P(post));
794 array_copy(post_data, post);
795
796 RETURN_TRUE;
797 }
798 /* }}}*/
799
800 /* {{{ proto array HTTPi_Request::getPostData()
801 *
802 */
803 PHP_METHOD(HTTPi_Request, getPostData)
804 {
805 zval *post_data;
806 getObject(httpi_request_object, obj);
807
808 NO_ARGS;
809
810 post_data = GET_PROP(obj, postData);
811 array_init(return_value);
812 array_copy(post_data, return_value);
813 }
814 /* }}} */
815
816 /* {{{ proto void HTTPi_Request::unsetPostData()
817 *
818 */
819 PHP_METHOD(HTTPi_Request, unsetPostData)
820 {
821 zval *post_data;
822 getObject(httpi_request_object, obj);
823
824 NO_ARGS;
825
826 post_data = GET_PROP(obj, postData);
827 zend_hash_clean(Z_ARRVAL_P(post_data));
828 }
829 /* }}} */
830
831 /* {{{ proto bool HTTPi_Request::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
832 *
833 */
834 PHP_METHOD(HTTPi_Request, addPostFile)
835 {
836 zval *files, *entry;
837 char *name, *file, *type = NULL;
838 int name_len, file_len, type_len = 0;
839 getObject(httpi_request_object, obj);
840
841 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
842 RETURN_FALSE;
843 }
844
845 if (type_len) {
846 if (!strchr(type, '/')) {
847 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
848 RETURN_FALSE;
849 }
850 } else {
851 type = "application/x-octetstream";
852 type_len = sizeof("application/x-octetstream") - 1;
853 }
854
855 MAKE_STD_ZVAL(entry);
856 array_init(entry);
857
858 add_assoc_stringl(entry, "name", name, name_len, 1);
859 add_assoc_stringl(entry, "type", type, type_len, 1);
860 add_assoc_stringl(entry, "file", file, file_len, 1);
861
862 files = GET_PROP(obj, postFiles);
863 add_next_index_zval(files, entry);
864
865 RETURN_TRUE;
866 }
867 /* }}} */
868
869 /* {{{ proto array HTTPi_Request::getPostFiles()
870 *
871 */
872 PHP_METHOD(HTTPi_Request, getPostFiles)
873 {
874 zval *files;
875 getObject(httpi_request_object, obj);
876
877 NO_ARGS;
878
879 files = GET_PROP(obj, postFiles);
880
881 array_init(return_value);
882 array_copy(files, return_value);
883 }
884 /* }}} */
885
886 /* {{{ proto void HTTPi_Request::unsetPostFiles()
887 *
888 */
889 PHP_METHOD(HTTPi_Request, unsetPostFiles)
890 {
891 zval *files;
892 getObject(httpi_request_object, obj);
893
894 NO_ARGS;
895
896 files = GET_PROP(obj, postFiles);
897 zend_hash_clean(Z_ARRVAL_P(files));
898 }
899 /* }}} */
900
901 /* {{{ proto array HTTPi_Request::getResponseData()
902 *
903 */
904 PHP_METHOD(HTTPi_Request, getResponseData)
905 {
906 zval *data;
907 getObject(httpi_request_object, obj);
908
909 NO_ARGS;
910
911 data = GET_PROP(obj, responseData);
912 array_init(return_value);
913 array_copy(data, return_value);
914 }
915 /* }}} */
916
917 /* {{{ proto array HTTPi_Request::getResponseHeaders()
918 *
919 */
920 PHP_METHOD(HTTPi_Request, getResponseHeaders)
921 {
922 zval *data, **headers;
923 getObject(httpi_request_object, obj);
924
925 NO_ARGS;
926
927 array_init(return_value);
928 data = GET_PROP(obj, responseData);
929 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
930 array_copy(*headers, return_value);
931 }
932 }
933 /* }}} */
934
935 /* {{{ proto string HTTPi_Request::getResponseBody()
936 *
937 */
938 PHP_METHOD(HTTPi_Request, getResponseBody)
939 {
940 zval *data, **body;
941 getObject(httpi_request_object, obj);
942
943 NO_ARGS;
944
945 data = GET_PROP(obj, responseData);
946 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
947 RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
948 } else {
949 Z_TYPE_P(return_value) = IS_NULL;
950 }
951 }
952 /* }}} */
953
954 /* {{{ proto array HTTPi_Request::getResponseInfo()
955 *
956 */
957 PHP_METHOD(HTTPi_Request, getResponseInfo)
958 {
959 zval *info;
960 getObject(httpi_request_object, obj);
961
962 NO_ARGS;
963
964 info = GET_PROP(obj, responseInfo);
965 array_init(return_value);
966 array_copy(info, return_value);
967 }
968 /* }}}*/
969
970 /* {{{ proto bool HTTPi_Request::send()
971 *
972 */
973 PHP_METHOD(HTTPi_Request, send)
974 {
975 STATUS status = FAILURE;
976 zval *meth, *URL, *qdata, *opts, *info, *resp;
977 char *response_data, *request_uri;
978 size_t response_len;
979 getObject(httpi_request_object, obj);
980
981 NO_ARGS;
982
983 if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
984 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initilaize cURL");
985 RETURN_FALSE;
986 }
987
988 meth = GET_PROP(obj, method);
989 URL = GET_PROP(obj, url);
990 qdata = GET_PROP(obj, queryData);
991 opts = GET_PROP(obj, options);
992 info = GET_PROP(obj, responseInfo);
993 resp = GET_PROP(obj, responseData);
994
995 // HTTP_URI_MAXLEN+1 big char *
996 request_uri = http_absolute_uri(Z_STRVAL_P(URL), NULL);
997
998 if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
999 if (!strchr(request_uri, '?')) {
1000 strcat(request_uri, "?");
1001 } else {
1002 strcat(request_uri, "&");
1003 }
1004 strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
1005 }
1006
1007 switch (Z_LVAL_P(meth))
1008 {
1009 case HTTP_GET:
1010 status = http_get_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1011 break;
1012
1013 case HTTP_HEAD:
1014 status = http_head_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1015 break;
1016
1017 case HTTP_POST:
1018 {
1019 zval *post_files, *post_data;
1020
1021 post_files = GET_PROP(obj, postFiles);
1022 post_data = GET_PROP(obj, postData);
1023
1024 if (!zend_hash_num_elements(Z_ARRVAL_P(post_files))) {
1025
1026 /* urlencoded post */
1027 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);
1028
1029 } else {
1030
1031 /*
1032 * multipart post
1033 */
1034 char *key = NULL;
1035 long idx;
1036 zval **data;
1037 struct curl_httppost *http_post_data[2] = {NULL, NULL};
1038
1039 /* normal data */
1040 FOREACH_KEYVAL(post_data, key, idx, data) {
1041 if (key) {
1042 convert_to_string_ex(data);
1043 curl_formadd(&http_post_data[0], &http_post_data[1],
1044 CURLFORM_COPYNAME, key,
1045 CURLFORM_COPYCONTENTS, Z_STRVAL_PP(data),
1046 CURLFORM_CONTENTSLENGTH, Z_STRLEN_PP(data),
1047 CURLFORM_END
1048 );
1049
1050 /* reset */
1051 key = NULL;
1052 }
1053 }
1054
1055 /* file data */
1056 FOREACH_VAL(post_files, data) {
1057 zval **file, **type, **name;
1058
1059 if ( SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "name", sizeof("name"), (void **) &name) &&
1060 SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &type) &&
1061 SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "file", sizeof("file"), (void **) &file)) {
1062
1063 curl_formadd(&http_post_data[0], &http_post_data[1],
1064 CURLFORM_COPYNAME, Z_STRVAL_PP(name),
1065 CURLFORM_FILE, Z_STRVAL_PP(file),
1066 CURLFORM_CONTENTTYPE, Z_STRVAL_PP(type),
1067 CURLFORM_END
1068 );
1069 }
1070 }
1071
1072 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);
1073 curl_formfree(http_post_data[0]);
1074 }
1075 }
1076 break;
1077
1078 default:
1079 break;
1080 }
1081
1082 efree(request_uri);
1083
1084 /* final data handling */
1085 if (status != SUCCESS) {
1086 RETURN_FALSE;
1087 } else {
1088 zval *zheaders, *zbody;
1089
1090 MAKE_STD_ZVAL(zbody);
1091 MAKE_STD_ZVAL(zheaders)
1092 array_init(zheaders);
1093
1094 if (SUCCESS != http_split_response_ex(response_data, response_len, zheaders, zbody)) {
1095 zval_dtor(zheaders);
1096 efree(zheaders),
1097 efree(zbody);
1098 efree(response_data);
1099 RETURN_FALSE;
1100 }
1101
1102 add_assoc_zval(resp, "headers", zheaders);
1103 add_assoc_zval(resp, "body", zbody);
1104
1105 efree(response_data);
1106
1107 RETURN_TRUE;
1108 }
1109 /* */
1110 }
1111 /* }}} */
1112 /* }}} */
1113 #endif /* HTTP_HAVE_CURL */
1114
1115 #endif /* ZEND_ENGINE_2 */
1116
1117 /*
1118 * Local variables:
1119 * tab-width: 4
1120 * c-basic-offset: 4
1121 * End:
1122 * vim600: noet sw=4 ts=4 fdm=marker
1123 * vim<600: noet sw=4 ts=4
1124 */