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