* ditch some inline functions and replace them with a macro
[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 zval *zdata = GET_PROP(obj, data);
442 RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
443 }
444
445 case SEND_RSRC:
446 {
447 php_stream *the_real_stream;
448 zval *the_stream = GET_PROP(obj, stream);
449 php_stream_from_zval(the_real_stream, &the_stream);
450 RETURN_SUCCESS(http_send_stream(the_real_stream));
451 }
452
453 default:
454 {
455 zval *zfile = GET_PROP(obj, file);
456 RETURN_SUCCESS(http_send_file(Z_STRVAL_P(zfile)));
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 getObject(httpi_request_object, obj);
476
477 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
478 return;
479 }
480
481 INIT_PARR(obj, options);
482 INIT_PARR(obj, responseInfo);
483 INIT_PARR(obj, responseData);
484 INIT_PARR(obj, postData);
485 INIT_PARR(obj, postFiles);
486
487 if (URL) {
488 UPD_PROP(obj, string, url, URL);
489 }
490 if (meth > -1) {
491 UPD_PROP(obj, long, method, meth);
492 }
493 }
494 /* }}} */
495
496 /* {{{ proto void HTTPi_Request::__destruct()
497 *
498 */
499 PHP_METHOD(HTTPi_Request, __destruct)
500 {
501 getObject(httpi_request_object, obj);
502
503 NO_ARGS;
504
505 FREE_PARR(obj, options);
506 FREE_PARR(obj, responseInfo);
507 FREE_PARR(obj, responseData);
508 FREE_PARR(obj, postData);
509 FREE_PARR(obj, postFiles);
510 }
511 /* }}} */
512
513 /* {{{ proto bool HTTPi_Request::setOptions(array options)
514 *
515 */
516 PHP_METHOD(HTTPi_Request, setOptions)
517 {
518 char *key = NULL;
519 long idx = 0;
520 zval *opts, *old_opts, **opt;
521 getObject(httpi_request_object, obj);
522
523 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
524 RETURN_FALSE;
525 }
526
527 old_opts = GET_PROP(obj, options);
528
529 /* headers and cookies need extra attention -- thus cannot use array_merge() directly */
530 FOREACH_KEYVAL(opts, key, idx, opt) {
531 if (key) {
532 if (!strcmp(key, "headers")) {
533 zval **headers;
534 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
535 array_merge(*opt, *headers);
536 continue;
537 }
538 } else if (!strcmp(key, "cookies")) {
539 zval **cookies;
540 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
541 array_merge(*opt, *cookies);
542 continue;
543 }
544 }
545 zval_add_ref(opt);
546 add_assoc_zval(old_opts, key, *opt);
547
548 /* reset */
549 key = NULL;
550 }
551 }
552
553 RETURN_TRUE;
554 }
555 /* }}} */
556
557 /* {{{ proto array HTTPi_Request::getOptions()
558 *
559 */
560 PHP_METHOD(HTTPi_Request, getOptions)
561 {
562 zval *opts;
563 getObject(httpi_request_object, obj);
564
565 NO_ARGS;
566
567 opts = GET_PROP(obj, options);
568 array_init(return_value);
569 array_copy(opts, return_value);
570 }
571 /* }}} */
572
573 /* {{{ proto bool HTTPi_Request::setURL(string url)
574 *
575 */
576 PHP_METHOD(HTTPi_Request, setURL)
577 {
578 char *URL = NULL;
579 int URL_len;
580 getObject(httpi_request_object, obj);
581
582 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
583 RETURN_FALSE;
584 }
585
586 UPD_PROP(obj, string, url, URL);
587 RETURN_TRUE;
588 }
589 /* }}} */
590
591 /* {{{ proto string HTTPi_Request::getUrl()
592 *
593 */
594 PHP_METHOD(HTTPi_Request, getURL)
595 {
596 zval *URL;
597 getObject(httpi_request_object, obj);
598
599 NO_ARGS;
600
601 URL = GET_PROP(obj, url);
602 RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
603 }
604 /* }}} */
605
606 /* {{{ proto bool HTTPi_Request::setMethod(long request_method)
607 *
608 */
609 PHP_METHOD(HTTPi_Request, setMethod)
610 {
611 long meth;
612 getObject(httpi_request_object, obj);
613
614 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
615 RETURN_FALSE;
616 }
617
618 UPD_PROP(obj, long, method, meth);
619 RETURN_TRUE;
620 }
621 /* }}} */
622
623 /* {{{ proto long HTTPi_Request::getMethod()
624 *
625 */
626 PHP_METHOD(HTTPi_Request, getMethod)
627 {
628 zval *meth;
629 getObject(httpi_request_object, obj);
630
631 NO_ARGS;
632
633 meth = GET_PROP(obj, method);
634 RETURN_LONG(Z_LVAL_P(meth));
635 }
636 /* }}} */
637
638 /* {{{ proto bool HTTPi_Request::setContentType(string content_type)
639 *
640 */
641 PHP_METHOD(HTTPi_Request, setContentType)
642 {
643 char *ctype;
644 int ct_len;
645 getObject(httpi_request_object, obj);
646
647 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
648 RETURN_FALSE;
649 }
650
651 if (!strchr(ctype, '/')) {
652 php_error_docref(NULL TSRMLS_CC, E_WARNING,
653 "Content-Type '%s' doesn't seem to contain a primary and a secondary part",
654 ctype);
655 RETURN_FALSE;
656 }
657
658 UPD_PROP(obj, string, contentType, ctype);
659 RETURN_TRUE;
660 }
661 /* }}} */
662
663 /* {{{ proto string HTTPi_Request::getContentType()
664 *
665 */
666 PHP_METHOD(HTTPi_Request, getContentType)
667 {
668 zval *ctype;
669 getObject(httpi_request_object, obj);
670
671 NO_ARGS;
672
673 ctype = GET_PROP(obj, contentType);
674 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
675 }
676 /* }}} */
677
678 /* {{{ proto bool HTTPi_Request::setQueryData(mixed query_data)
679 *
680 */
681 PHP_METHOD(HTTPi_Request, setQueryData)
682 {
683 zval *qdata;
684 char *query_data = NULL;
685 getObject(httpi_request_object, obj);
686
687 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &qdata)) {
688 RETURN_FALSE;
689 }
690
691 if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
692 if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) {
693 RETURN_FALSE;
694 }
695 UPD_PROP(obj, string, queryData, query_data);
696 efree(query_data);
697 RETURN_TRUE;
698 }
699
700 convert_to_string(qdata);
701 UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
702 RETURN_TRUE;
703 }
704 /* }}} */
705
706 /* {{{ proto string HTTPi_Request::getQueryData()
707 *
708 */
709 PHP_METHOD(HTTPi_Request, getQueryData)
710 {
711 zval *qdata;
712 getObject(httpi_request_object, obj);
713
714 NO_ARGS;
715
716 qdata = GET_PROP(obj, queryData);
717 RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
718 }
719 /* }}} */
720
721 /* {{{ proto bool HTTPi_Request::addQueryData(array query_params)
722 *
723 */
724 PHP_METHOD(HTTPi_Request, addQueryData)
725 {
726 zval *qdata, *old_qdata;
727 char *query_data = NULL;
728 getObject(httpi_request_object, obj);
729
730 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
731 RETURN_FALSE;
732 }
733
734 old_qdata = GET_PROP(obj, queryData);
735
736 if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, NULL)) {
737 RETURN_FALSE;
738 }
739
740 UPD_PROP(obj, string, queryData, query_data);
741 efree(query_data);
742
743 RETURN_TRUE;
744 }
745 /* }}} */
746
747 /* {{{ proto void HTTPi_Request::unsetQueryData()
748 *
749 */
750 PHP_METHOD(HTTPi_Request, unsetQueryData)
751 {
752 getObject(httpi_request_object, obj);
753
754 NO_ARGS;
755
756 UPD_PROP(obj, string, queryData, "");
757 }
758 /* }}} */
759
760 /* {{{ proto bool HTTPi_Request::addPostData(array post_data)
761 *
762 */
763 PHP_METHOD(HTTPi_Request, addPostData)
764 {
765 zval *post, *post_data;
766 getObject(httpi_request_object, obj);
767
768 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
769 RETURN_FALSE;
770 }
771
772 post = GET_PROP(obj, postData);
773 array_merge(post_data, post);
774
775 RETURN_TRUE;
776 }
777 /* }}} */
778
779 /* {{{ proto bool HTTPi_Request::setPostData(array post_data)
780 *
781 */
782 PHP_METHOD(HTTPi_Request, setPostData)
783 {
784 zval *post, *post_data;
785 getObject(httpi_request_object, obj);
786
787 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
788 RETURN_FALSE;
789 }
790
791 post = GET_PROP(obj, postData);
792 zend_hash_clean(Z_ARRVAL_P(post));
793 array_copy(post_data, post);
794
795 RETURN_TRUE;
796 }
797 /* }}}*/
798
799 /* {{{ proto array HTTPi_Request::getPostData()
800 *
801 */
802 PHP_METHOD(HTTPi_Request, getPostData)
803 {
804 zval *post_data;
805 getObject(httpi_request_object, obj);
806
807 NO_ARGS;
808
809 post_data = GET_PROP(obj, postData);
810 array_init(return_value);
811 array_copy(post_data, return_value);
812 }
813 /* }}} */
814
815 /* {{{ proto void HTTPi_Request::unsetPostData()
816 *
817 */
818 PHP_METHOD(HTTPi_Request, unsetPostData)
819 {
820 zval *post_data;
821 getObject(httpi_request_object, obj);
822
823 NO_ARGS;
824
825 post_data = GET_PROP(obj, postData);
826 zend_hash_clean(Z_ARRVAL_P(post_data));
827 }
828 /* }}} */
829
830 /* {{{ proto bool HTTPi_Request::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
831 *
832 */
833 PHP_METHOD(HTTPi_Request, addPostFile)
834 {
835 zval *files, *entry;
836 char *name, *file, *type = NULL;
837 int name_len, file_len, type_len = 0;
838 getObject(httpi_request_object, obj);
839
840 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
841 RETURN_FALSE;
842 }
843
844 if (type_len) {
845 if (!strchr(type, '/')) {
846 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
847 RETURN_FALSE;
848 }
849 } else {
850 type = "application/x-octetstream";
851 type_len = sizeof("application/x-octetstream") - 1;
852 }
853
854 MAKE_STD_ZVAL(entry);
855 array_init(entry);
856
857 add_assoc_stringl(entry, "name", name, name_len, 1);
858 add_assoc_stringl(entry, "type", type, type_len, 1);
859 add_assoc_stringl(entry, "file", file, file_len, 1);
860
861 files = GET_PROP(obj, postFiles);
862 add_next_index_zval(files, entry);
863
864 RETURN_TRUE;
865 }
866 /* }}} */
867
868 /* {{{ proto array HTTPi_Request::getPostFiles()
869 *
870 */
871 PHP_METHOD(HTTPi_Request, getPostFiles)
872 {
873 zval *files;
874 getObject(httpi_request_object, obj);
875
876 NO_ARGS;
877
878 files = GET_PROP(obj, postFiles);
879
880 array_init(return_value);
881 array_copy(files, return_value);
882 }
883 /* }}} */
884
885 /* {{{ proto void HTTPi_Request::unsetPostFiles()
886 *
887 */
888 PHP_METHOD(HTTPi_Request, unsetPostFiles)
889 {
890 zval *files;
891 getObject(httpi_request_object, obj);
892
893 NO_ARGS;
894
895 files = GET_PROP(obj, postFiles);
896 zend_hash_clean(Z_ARRVAL_P(files));
897 }
898 /* }}} */
899
900 /* {{{ proto array HTTPi_Request::getResponseData()
901 *
902 */
903 PHP_METHOD(HTTPi_Request, getResponseData)
904 {
905 zval *data;
906 getObject(httpi_request_object, obj);
907
908 NO_ARGS;
909
910 data = GET_PROP(obj, responseData);
911 array_init(return_value);
912 array_copy(data, return_value);
913 }
914 /* }}} */
915
916 /* {{{ proto array HTTPi_Request::getResponseHeaders()
917 *
918 */
919 PHP_METHOD(HTTPi_Request, getResponseHeaders)
920 {
921 zval *data, **headers;
922 getObject(httpi_request_object, obj);
923
924 NO_ARGS;
925
926 array_init(return_value);
927 data = GET_PROP(obj, responseData);
928 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
929 array_copy(*headers, return_value);
930 }
931 }
932 /* }}} */
933
934 /* {{{ proto string HTTPi_Request::getResponseBody()
935 *
936 */
937 PHP_METHOD(HTTPi_Request, getResponseBody)
938 {
939 zval *data, **body;
940 getObject(httpi_request_object, obj);
941
942 NO_ARGS;
943
944 data = GET_PROP(obj, responseData);
945 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
946 RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
947 } else {
948 Z_TYPE_P(return_value) = IS_NULL;
949 }
950 }
951 /* }}} */
952
953 /* {{{ proto array HTTPi_Request::getResponseInfo()
954 *
955 */
956 PHP_METHOD(HTTPi_Request, getResponseInfo)
957 {
958 zval *info;
959 getObject(httpi_request_object, obj);
960
961 NO_ARGS;
962
963 info = GET_PROP(obj, responseInfo);
964 array_init(return_value);
965 array_copy(info, return_value);
966 }
967 /* }}}*/
968
969 /* {{{ proto bool HTTPi_Request::send()
970 *
971 */
972 PHP_METHOD(HTTPi_Request, send)
973 {
974 STATUS status = FAILURE;
975 zval *meth, *URL, *qdata, *opts, *info, *resp;
976 char *response_data, *request_uri;
977 size_t response_len;
978 getObject(httpi_request_object, obj);
979
980 NO_ARGS;
981
982 if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
983 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initilaize cURL");
984 RETURN_FALSE;
985 }
986
987 meth = GET_PROP(obj, method);
988 URL = GET_PROP(obj, url);
989 qdata = GET_PROP(obj, queryData);
990 opts = GET_PROP(obj, options);
991 info = GET_PROP(obj, responseInfo);
992 resp = GET_PROP(obj, responseData);
993
994 // HTTP_URI_MAXLEN+1 big char *
995 request_uri = http_absolute_uri(Z_STRVAL_P(URL), NULL);
996
997 if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
998 if (!strchr(request_uri, '?')) {
999 strcat(request_uri, "?");
1000 } else {
1001 strcat(request_uri, "&");
1002 }
1003 strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
1004 }
1005
1006 switch (Z_LVAL_P(meth))
1007 {
1008 case HTTP_GET:
1009 status = http_get_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1010 break;
1011
1012 case HTTP_HEAD:
1013 status = http_head_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
1014 break;
1015
1016 case HTTP_POST:
1017 {
1018 zval *post_files, *post_data;
1019
1020 post_files = GET_PROP(obj, postFiles);
1021 post_data = GET_PROP(obj, postData);
1022
1023 if (!zend_hash_num_elements(Z_ARRVAL_P(post_files))) {
1024
1025 /* urlencoded post */
1026 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);
1027
1028 } else {
1029
1030 /*
1031 * multipart post
1032 */
1033 char *key = NULL;
1034 long idx;
1035 zval **data;
1036 struct curl_httppost *http_post_data[2] = {NULL, NULL};
1037
1038 /* normal data */
1039 FOREACH_KEYVAL(post_data, key, idx, data) {
1040 if (key) {
1041 convert_to_string_ex(data);
1042 curl_formadd(&http_post_data[0], &http_post_data[1],
1043 CURLFORM_COPYNAME, key,
1044 CURLFORM_COPYCONTENTS, Z_STRVAL_PP(data),
1045 CURLFORM_CONTENTSLENGTH, Z_STRLEN_PP(data),
1046 CURLFORM_END
1047 );
1048
1049 /* reset */
1050 key = NULL;
1051 }
1052 }
1053
1054 /* file data */
1055 FOREACH_VAL(post_files, data) {
1056 zval **file, **type, **name;
1057
1058 if ( SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "name", sizeof("name"), (void **) &name) &&
1059 SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &type) &&
1060 SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "file", sizeof("file"), (void **) &file)) {
1061
1062 curl_formadd(&http_post_data[0], &http_post_data[1],
1063 CURLFORM_COPYNAME, Z_STRVAL_PP(name),
1064 CURLFORM_FILE, Z_STRVAL_PP(file),
1065 CURLFORM_CONTENTTYPE, Z_STRVAL_PP(type),
1066 CURLFORM_END
1067 );
1068 }
1069 }
1070
1071 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);
1072 curl_formfree(http_post_data[0]);
1073 }
1074 }
1075 break;
1076
1077 default:
1078 break;
1079 }
1080
1081 efree(request_uri);
1082
1083 /* final data handling */
1084 if (status != SUCCESS) {
1085 RETURN_FALSE;
1086 } else {
1087 zval *zheaders, *zbody;
1088
1089 MAKE_STD_ZVAL(zbody);
1090 MAKE_STD_ZVAL(zheaders)
1091 array_init(zheaders);
1092
1093 if (SUCCESS != http_split_response_ex(response_data, response_len, zheaders, zbody)) {
1094 zval_dtor(zheaders);
1095 efree(zheaders),
1096 efree(zbody);
1097 efree(response_data);
1098 RETURN_FALSE;
1099 }
1100
1101 add_assoc_zval(resp, "headers", zheaders);
1102 add_assoc_zval(resp, "body", zbody);
1103
1104 efree(response_data);
1105
1106 RETURN_TRUE;
1107 }
1108 /* */
1109 }
1110 /* }}} */
1111 /* }}} */
1112 #endif /* HTTP_HAVE_CURL */
1113
1114 #endif /* ZEND_ENGINE_2 */
1115
1116 /*
1117 * Local variables:
1118 * tab-width: 4
1119 * c-basic-offset: 4
1120 * End:
1121 * vim600: noet sw=4 ts=4 fdm=marker
1122 * vim<600: noet sw=4 ts=4
1123 */
1124