715d904ae495daebdc3e0c66406f142526e8776d
[m6w6/ext-http] / http_methods.c
1 /*
2
3 +----------------------------------------------------------------------+
4
5 | PECL :: http |
6
7 +----------------------------------------------------------------------+
8
9 | This source file is subject to version 3.0 of the PHP license, that |
10
11 | is bundled with this package in the file LICENSE, and is available |
12
13 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
14
15 | If you did not receive a copy of the PHP license and are unable to |
16
17 | obtain it through the world-wide-web, please send a note to |
18
19 | license@php.net so we can mail you a copy immediately. |
20
21 +----------------------------------------------------------------------+
22
23 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
24
25 +----------------------------------------------------------------------+
26
27 */
28
29
30
31 /* $Id$ */
32
33
34
35 #ifdef HAVE_CONFIG_H
36
37 # include "config.h"
38
39 #endif
40
41
42
43 #include "php.h"
44
45 #include "php_http.h"
46
47 #include "php_http_std_defs.h"
48
49 #include "php_http_api.h"
50
51 #include "php_http_cache_api.h"
52
53 #include "php_http_request_api.h"
54
55 #include "php_http_date_api.h"
56
57 #include "php_http_headers_api.h"
58
59 #include "php_http_message_api.h"
60
61 #include "php_http_send_api.h"
62
63 #include "php_http_url_api.h"
64
65
66
67 #include "php_http_message_object.h"
68
69 #include "php_http_response_object.h"
70
71 #include "php_http_request_object.h"
72
73 #include "php_http_exception_object.h"
74
75
76
77 #ifdef ZEND_ENGINE_2
78
79
80
81 /* {{{ HttpResponse */
82
83
84
85 /* {{{ proto void HttpResponse::__construct(bool cache, bool gzip)
86
87 *
88
89 * Instantiates a new HttpResponse object, which can be used to send
90
91 * any data/resource/file to an HTTP client with caching and multiple
92
93 * ranges/resuming support.
94
95 *
96
97 * NOTE: GZIPping is not implemented yet.
98
99 */
100
101 PHP_METHOD(HttpResponse, __construct)
102
103 {
104
105 zend_bool do_cache = 0, do_gzip = 0;
106
107 getObject(http_response_object, obj);
108
109
110
111 SET_EH_THROW_HTTP();
112
113 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &do_cache, &do_gzip)) {
114
115 UPD_PROP(obj, long, cache, do_cache);
116
117 UPD_PROP(obj, long, gzip, do_gzip);
118
119 }
120
121 SET_EH_NORMAL();
122
123 }
124
125 /* }}} */
126
127
128
129 /* {{{ proto bool HttpResponse::setCache(bool cache)
130
131 *
132
133 * Whether it sould be attempted to cache the entitity.
134
135 * This will result in necessary caching headers and checks of clients
136
137 * "If-Modified-Since" and "If-None-Match" headers. If one of those headers
138
139 * matches a "304 Not Modified" status code will be issued.
140
141 *
142
143 * NOTE: If you're using sessions, be shure that you set session.cache_limiter
144
145 * to something more appropriate than "no-cache"!
146
147 */
148
149 PHP_METHOD(HttpResponse, setCache)
150
151 {
152
153 zend_bool do_cache = 0;
154
155 getObject(http_response_object, obj);
156
157
158
159 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
160
161 RETURN_FALSE;
162
163 }
164
165
166
167 UPD_PROP(obj, long, cache, do_cache);
168
169 RETURN_TRUE;
170
171 }
172
173 /* }}} */
174
175
176
177 /* {{{ proto bool HttpResponse::getCache()
178
179 *
180
181 * Get current caching setting.
182
183 */
184
185 PHP_METHOD(HttpResponse, getCache)
186
187 {
188
189 zval *do_cache = NULL;
190
191 getObject(http_response_object, obj);
192
193
194
195 NO_ARGS;
196
197
198
199 do_cache = GET_PROP(obj, cache);
200
201 RETURN_BOOL(Z_LVAL_P(do_cache));
202
203 }
204
205 /* }}}*/
206
207
208
209 /* {{{ proto bool HttpResponse::setGzip(bool gzip)
210
211 *
212
213 * Enable on-thy-fly gzipping of the sent entity. NOT IMPLEMENTED YET.
214
215 */
216
217 PHP_METHOD(HttpResponse, setGzip)
218
219 {
220
221 zend_bool do_gzip = 0;
222
223 getObject(http_response_object, obj);
224
225
226
227 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
228
229 RETURN_FALSE;
230
231 }
232
233
234
235 UPD_PROP(obj, long, gzip, do_gzip);
236
237 RETURN_TRUE;
238
239 }
240
241 /* }}} */
242
243
244
245 /* {{{ proto bool HttpResponse::getGzip()
246
247 *
248
249 * Get current gzipping setting.
250
251 */
252
253 PHP_METHOD(HttpResponse, getGzip)
254
255 {
256
257 zval *do_gzip = NULL;
258
259 getObject(http_response_object, obj);
260
261
262
263 NO_ARGS;
264
265
266
267 do_gzip = GET_PROP(obj, gzip);
268
269 RETURN_BOOL(Z_LVAL_P(do_gzip));
270
271 }
272
273 /* }}} */
274
275
276
277 /* {{{ proto bool HttpResponse::setCacheControl(string control[, bool raw = false])
278
279 *
280
281 * Set a custom cache-control header, usually being "private" or "public"; if
282
283 * $raw is set to true the header will be sent as-is.
284
285 */
286
287 PHP_METHOD(HttpResponse, setCacheControl)
288
289 {
290
291 char *ccontrol;
292
293 int cc_len;
294
295 zend_bool raw = 0;
296
297 getObject(http_response_object, obj);
298
299
300
301 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &ccontrol, &cc_len, &raw)) {
302
303 RETURN_FALSE;
304
305 }
306
307
308
309 if ((!raw) && (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache"))) {
310
311 http_error_ex(E_WARNING, HTTP_E_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
312
313 RETURN_FALSE;
314
315 }
316
317
318
319 UPD_PROP(obj, long, raw_cache_header, raw);
320
321 UPD_PROP(obj, string, cacheControl, ccontrol);
322
323 RETURN_TRUE;
324
325 }
326
327 /* }}} */
328
329
330
331 /* {{{ proto string HttpResponse::getCacheControl()
332
333 *
334
335 * Get current Cache-Control header setting.
336
337 */
338
339 PHP_METHOD(HttpResponse, getCacheControl)
340
341 {
342
343 zval *ccontrol;
344
345 getObject(http_response_object, obj);
346
347
348
349 NO_ARGS;
350
351
352
353 ccontrol = GET_PROP(obj, cacheControl);
354
355 RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
356
357 }
358
359 /* }}} */
360
361
362
363 /* {{{ proto bool HttpResponse::setContentType(string content_type)
364
365 *
366
367 * Set the content-type of the sent entity.
368
369 */
370
371 PHP_METHOD(HttpResponse, setContentType)
372
373 {
374
375 char *ctype;
376
377 int ctype_len;
378
379 getObject(http_response_object, obj);
380
381
382
383 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
384
385 RETURN_FALSE;
386
387 }
388
389
390
391 if (!strchr(ctype, '/')) {
392
393 http_error_ex(E_WARNING, HTTP_E_PARAM, "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
394
395 RETURN_FALSE;
396
397 }
398
399
400
401 UPD_PROP(obj, string, contentType, ctype);
402
403
404
405 RETURN_TRUE;
406
407 }
408
409 /* }}} */
410
411
412
413 /* {{{ proto string HttpResponse::getContentType()
414
415 *
416
417 * Get current Content-Type header setting.
418
419 */
420
421 PHP_METHOD(HttpResponse, getContentType)
422
423 {
424
425 zval *ctype;
426
427 getObject(http_response_object, obj);
428
429
430
431 NO_ARGS;
432
433
434
435 ctype = GET_PROP(obj, contentType);
436
437 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
438
439 }
440
441 /* }}} */
442
443
444
445 /* {{{ proto bool HttpResponse::setContentDisposition(string filename[, bool inline = false])
446
447 *
448
449 * Set the Content-Disposition of the sent entity. This setting aims to suggest
450
451 * the receiveing user agent how to handle the sent entity; usually the client
452
453 * will show the user a "Save As..." popup.
454
455 */
456
457 PHP_METHOD(HttpResponse, setContentDisposition)
458
459 {
460
461 char *file;
462
463 int file_len;
464
465 zend_bool is_inline = 0;
466
467 getObject(http_response_object, obj);
468
469
470
471 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &is_inline)) {
472
473 RETURN_FALSE;
474
475 }
476
477
478
479 UPD_PROP(obj, string, dispoFile, file);
480
481 UPD_PROP(obj, long, dispoInline, is_inline);
482
483 RETURN_TRUE;
484
485 }
486
487 /* }}} */
488
489
490
491 /* {{{ proto array HttpResponse::getContentDisposition()
492
493 *
494
495 * Get current Content-Disposition setting.
496
497 * Will return an associative array like:
498
499 * <pre>
500
501 * array(
502
503 * 'filename' => 'foo.bar',
504
505 * 'inline' => false
506
507 * )
508
509 * </pre>
510
511 */
512
513 PHP_METHOD(HttpResponse, getContentDisposition)
514
515 {
516
517 zval *file;
518
519 zval *is_inline;
520
521 getObject(http_response_object, obj);
522
523
524
525 if (ZEND_NUM_ARGS()) {
526
527 WRONG_PARAM_COUNT;
528
529 }
530
531
532
533 file = GET_PROP(obj, dispoFile);
534
535 is_inline = GET_PROP(obj, dispoInline);
536
537
538
539 array_init(return_value);
540
541 add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
542
543 add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
544
545 }
546
547 /* }}} */
548
549
550
551 /* {{{ proto bool HttpResponse::setETag(string etag)
552
553 *
554
555 * Set a custom ETag. Use this only if you know what you're doing.
556
557 */
558
559 PHP_METHOD(HttpResponse, setETag)
560
561 {
562
563 char *etag;
564
565 int etag_len;
566
567 getObject(http_response_object, obj);
568
569
570
571 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
572
573 RETURN_FALSE;
574
575 }
576
577
578
579 UPD_PROP(obj, string, eTag, etag);
580
581 RETURN_TRUE;
582
583 }
584
585 /* }}} */
586
587
588
589 /* {{{ proto string HttpResponse::getETag()
590
591 *
592
593 * Get the previously set custom ETag.
594
595 */
596
597 PHP_METHOD(HttpResponse, getETag)
598
599 {
600
601 zval *etag;
602
603 getObject(http_response_object, obj);
604
605
606
607 NO_ARGS;
608
609
610
611 etag = GET_PROP(obj, eTag);
612
613 RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
614
615 }
616
617 /* }}} */
618
619
620
621 /* {{{ proto bool HttpResponse::setData(string data)
622
623 *
624
625 * Set the data to be sent.
626
627 */
628
629 PHP_METHOD(HttpResponse, setData)
630
631 {
632
633 zval *the_data;
634
635 getObject(http_response_object, obj);
636
637
638
639 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) {
640
641 RETURN_FALSE;
642
643 }
644
645
646
647 convert_to_string_ex(&the_data);
648
649 SET_PROP(obj, data, the_data);
650
651 UPD_PROP(obj, long, lastModified, http_last_modified(the_data, SEND_DATA));
652
653 UPD_PROP(obj, long, send_mode, SEND_DATA);
654
655 RETURN_TRUE;
656
657 }
658
659 /* }}} */
660
661
662
663 /* {{{ proto string HttpResponse::getData()
664
665 *
666
667 * Get the previously set data to be sent.
668
669 */
670
671 PHP_METHOD(HttpResponse, getData)
672
673 {
674
675 zval *the_data;
676
677 getObject(http_response_object, obj);
678
679
680
681 NO_ARGS;
682
683
684
685 the_data = GET_PROP(obj, data);
686
687 RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
688
689 }
690
691 /* }}} */
692
693
694
695 /* {{{ proto bool HttpResponse::setStream(resource stream)
696
697 *
698
699 * Set the resource to be sent.
700
701 */
702
703 PHP_METHOD(HttpResponse, setStream)
704
705 {
706
707 zval *the_stream;
708
709 php_stream *the_real_stream;
710
711 getObject(http_response_object, obj);
712
713
714
715 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
716
717 RETURN_FALSE;
718
719 }
720
721
722
723 php_stream_from_zval(the_real_stream, &the_stream);
724
725
726
727 SET_PROP(obj, stream, the_stream);
728
729 UPD_PROP(obj, long, lastModified, http_last_modified(the_real_stream, SEND_RSRC));
730
731 UPD_PROP(obj, long, send_mode, SEND_RSRC);
732
733 RETURN_TRUE;
734
735 }
736
737 /* }}} */
738
739
740
741 /* {{{ proto resource HttpResponse::getStream()
742
743 *
744
745 * Get the previously set resource to be sent.
746
747 */
748
749 PHP_METHOD(HttpResponse, getStream)
750
751 {
752
753 zval *the_stream;
754
755 getObject(http_response_object, obj);
756
757
758
759 NO_ARGS;
760
761
762
763 the_stream = GET_PROP(obj, stream);
764
765 RETURN_RESOURCE(Z_LVAL_P(the_stream));
766
767 }
768
769 /* }}} */
770
771
772
773 /* {{{ proto bool HttpResponse::setFile(string file)
774
775 *
776
777 * Set the file to be sent.
778
779 */
780
781 PHP_METHOD(HttpResponse, setFile)
782
783 {
784
785 zval *the_file;
786
787 getObject(http_response_object, obj);
788
789
790
791 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_file)) {
792
793 RETURN_FALSE;
794
795 }
796
797
798
799 convert_to_string_ex(&the_file);
800
801
802
803 UPD_PROP(obj, string, file, Z_STRVAL_P(the_file));
804
805 UPD_PROP(obj, long, lastModified, http_last_modified(the_file, -1));
806
807 UPD_PROP(obj, long, send_mode, -1);
808
809 RETURN_TRUE;
810
811 }
812
813 /* }}} */
814
815
816
817 /* {{{ proto string HttpResponse::getFile()
818
819 *
820
821 * Get the previously set file to be sent.
822
823 */
824
825 PHP_METHOD(HttpResponse, getFile)
826
827 {
828
829 zval *the_file;
830
831 getObject(http_response_object, obj);
832
833
834
835 NO_ARGS;
836
837
838
839 the_file = GET_PROP(obj, file);
840
841 RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
842
843 }
844
845 /* }}} */
846
847
848
849 /* {{{ proto bool HttpResponse::send()
850
851 *
852
853 * Finally send the entity.
854
855 *
856
857 * Example:
858
859 * <pre>
860
861 * <?php
862
863 * $r = new HttpResponse(true);
864
865 * $r->setFile('../hidden/contract.pdf');
866
867 * $r->setContentType('application/pdf');
868
869 * $r->send();
870
871 * ?>
872
873 * </pre>
874
875 *
876
877 */
878
879 PHP_METHOD(HttpResponse, send)
880
881 {
882
883 zval *do_cache, *do_gzip;
884
885 getObject(http_response_object, obj);
886
887
888
889 NO_ARGS;
890
891
892
893 do_cache = GET_PROP(obj, cache);
894
895 do_gzip = GET_PROP(obj, gzip);
896
897
898
899 /* gzip */
900
901 if (Z_LVAL_P(do_gzip)) {
902
903 php_start_ob_buffer_named("ob_gzhandler", 0, 1 TSRMLS_CC);
904
905 }
906
907
908
909 /* caching */
910
911 if (Z_LVAL_P(do_cache)) {
912
913 zval *cctrl, *etag, *lmod, *ccraw;
914
915
916
917 etag = GET_PROP(obj, eTag);
918
919 lmod = GET_PROP(obj, lastModified);
920
921 cctrl = GET_PROP(obj, cacheControl);
922
923 ccraw = GET_PROP(obj, raw_cache_header);
924
925
926
927 if (Z_LVAL_P(ccraw)) {
928
929 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
930
931 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));
932
933 } else {
934
935 char cc_header[42] = {0};
936
937 sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
938
939 http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_header, strlen(cc_header));
940
941 http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_header, strlen(cc_header));
942
943 }
944
945 }
946
947
948
949 /* content type */
950
951 {
952
953 zval *ctype = GET_PROP(obj, contentType);
954
955 if (Z_STRLEN_P(ctype)) {
956
957 http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
958
959 } else {
960
961 http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
962
963 }
964
965 }
966
967
968
969 /* content disposition */
970
971 {
972
973 zval *dispo_file = GET_PROP(obj, dispoFile);
974
975 if (Z_STRLEN_P(dispo_file)) {
976
977 zval *dispo_inline = GET_PROP(obj, dispoInline);
978
979 http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), (zend_bool) Z_LVAL_P(dispo_inline));
980
981 }
982
983 }
984
985
986
987 /* send */
988
989 {
990
991 zval *send_mode = GET_PROP(obj, send_mode);
992
993 switch (Z_LVAL_P(send_mode))
994
995 {
996
997 case SEND_DATA:
998
999 {
1000
1001 zval *zdata = GET_PROP(obj, data);
1002
1003 RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
1004
1005 }
1006
1007
1008
1009 case SEND_RSRC:
1010
1011 {
1012
1013 php_stream *the_real_stream;
1014
1015 zval *the_stream = GET_PROP(obj, stream);
1016
1017 php_stream_from_zval(the_real_stream, &the_stream);
1018
1019 RETURN_SUCCESS(http_send_stream(the_real_stream));
1020
1021 }
1022
1023
1024
1025 default:
1026
1027 {
1028
1029 zval *zfile = GET_PROP(obj, file);
1030
1031 RETURN_SUCCESS(http_send_file(Z_STRVAL_P(zfile)));
1032
1033 }
1034
1035 }
1036
1037 }
1038
1039 }
1040
1041 /* }}} */
1042
1043 /* }}} */
1044
1045
1046
1047 /* {{{ HttpMessage */
1048
1049
1050
1051 /* {{{ proto static HttpMessage HttpMessage::fromString(string raw_message)
1052
1053 *
1054
1055 * Create an HttpMessage object from a string.
1056
1057 */
1058
1059 PHP_METHOD(HttpMessage, fromString)
1060
1061 {
1062
1063 char *string = NULL;
1064
1065 int length = 0;
1066
1067 http_message *msg = NULL;
1068
1069 http_message_object obj;
1070
1071
1072
1073 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &length)) {
1074
1075 RETURN_NULL();
1076
1077 }
1078
1079
1080
1081 if (!(msg = http_message_parse(string, length))) {
1082
1083 RETURN_NULL();
1084
1085 }
1086
1087
1088
1089 Z_TYPE_P(return_value) = IS_OBJECT;
1090
1091 return_value->value.obj = http_message_object_from_msg(msg);
1092
1093 }
1094
1095 /* }}} */
1096
1097
1098
1099 /* {{{ proto void HttpMessage::__construct([string message])
1100
1101 *
1102
1103 * Instantiate a new HttpMessage object.
1104
1105 */
1106
1107 PHP_METHOD(HttpMessage, __construct)
1108
1109 {
1110
1111 char *message = NULL;
1112
1113 int length = 0;
1114
1115 getObject(http_message_object, obj);
1116
1117
1118
1119 SET_EH_THROW_HTTP();
1120
1121 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) {
1122
1123 if (obj->message = http_message_parse(message, length)) {
1124
1125 if (obj->message->parent) {
1126
1127 obj->parent = http_message_object_from_msg(obj->message->parent);
1128
1129 }
1130
1131 }
1132
1133 } else if (!obj->message) {
1134
1135 obj->message = http_message_new();
1136
1137 }
1138
1139 SET_EH_NORMAL();
1140
1141 }
1142
1143 /* }}} */
1144
1145
1146
1147 /* {{{ proto string HttpMessage::getBody()
1148
1149 *
1150
1151 * Get the body of the parsed Message.
1152
1153 */
1154
1155 PHP_METHOD(HttpMessage, getBody)
1156
1157 {
1158
1159 zval *body;
1160
1161 getObject(http_message_object, obj);
1162
1163
1164
1165 NO_ARGS;
1166
1167
1168
1169 RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
1170
1171 }
1172
1173 /* }}} */
1174
1175
1176
1177 /* {{{ proto array HttpMessage::getHeaders()
1178
1179 *
1180
1181 * Get Message Headers.
1182
1183 */
1184
1185 PHP_METHOD(HttpMessage, getHeaders)
1186
1187 {
1188
1189 zval headers;
1190
1191 getObject(http_message_object, obj);
1192
1193
1194
1195 NO_ARGS;
1196
1197
1198
1199 Z_ARRVAL(headers) = &obj->message->hdrs;
1200
1201 array_init(return_value);
1202
1203 array_copy(&headers, return_value);
1204
1205 }
1206
1207 /* }}} */
1208
1209
1210
1211 /* {{{ proto void HttpMessage::setHeaders(array headers)
1212
1213 *
1214
1215 * Sets new headers.
1216
1217 */
1218
1219 PHP_METHOD(HttpMessage, setHeaders)
1220
1221 {
1222
1223 zval *new_headers, old_headers;
1224
1225 getObject(http_message_object, obj);
1226
1227
1228
1229 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &new_headers)) {
1230
1231 return;
1232
1233 }
1234
1235
1236
1237 zend_hash_clean(&obj->message->hdrs);
1238
1239 Z_ARRVAL(old_headers) = &obj->message->hdrs;
1240
1241 array_copy(new_headers, &old_headers);
1242
1243 }
1244
1245 /* }}} */
1246
1247
1248
1249 /* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
1250
1251 *
1252
1253 * Add headers. If append is true, headers with the same name will be separated, else overwritten.
1254
1255 */
1256
1257 PHP_METHOD(HttpMessage, addHeaders)
1258
1259 {
1260
1261 zval old_headers, *new_headers;
1262
1263 zend_bool append = 0;
1264
1265 getObject(http_message_object, obj);
1266
1267
1268
1269 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
1270
1271 return;
1272
1273 }
1274
1275
1276
1277 Z_ARRVAL(old_headers) = &obj->message->hdrs;
1278
1279 if (append) {
1280
1281 array_append(new_headers, &old_headers);
1282
1283 } else {
1284
1285 array_merge(new_headers, &old_headers);
1286
1287 }
1288
1289 }
1290
1291 /* }}} */
1292
1293
1294
1295 /* {{{ proto long HttpMessage::getType()
1296
1297 *
1298
1299 * Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
1300
1301 */
1302
1303 PHP_METHOD(HttpMessage, getType)
1304
1305 {
1306
1307 getObject(http_message_object, obj);
1308
1309
1310
1311 NO_ARGS;
1312
1313
1314
1315 RETURN_LONG(obj->message->type);
1316
1317 }
1318
1319 /* }}} */
1320
1321
1322
1323 /* {{{ proto void HttpMessage::setType(long type)
1324
1325 *
1326
1327 * Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE)
1328
1329 */
1330
1331 PHP_METHOD(HttpMessage, setType)
1332
1333 {
1334
1335 long type;
1336
1337 getObject(http_message_object, obj);
1338
1339
1340
1341 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
1342
1343 return;
1344
1345 }
1346
1347 http_message_set_type(obj->message, type);
1348
1349 }
1350
1351 /* }}} */
1352
1353
1354
1355 /* {{{ proto long HttpMessage::getResponseCode()
1356
1357 *
1358
1359 * Get the Response Code of the Message.
1360
1361 */
1362
1363 PHP_METHOD(HttpMessage, getResponseCode)
1364
1365 {
1366
1367 getObject(http_message_object, obj);
1368
1369
1370
1371 NO_ARGS;
1372
1373
1374
1375 if (!HTTP_MSG_TYPE(RESPONSE, obj->message)) {
1376
1377 http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
1378
1379 RETURN_NULL();
1380
1381 }
1382
1383
1384
1385 RETURN_LONG(obj->message->info.response.code);
1386
1387 }
1388
1389 /* }}} */
1390
1391
1392
1393 /* {{{ proto bool HttpMessage::setResponseCode(long code)
1394
1395 *
1396
1397 * Set the response code of an HTTP Response Message.
1398
1399 * Returns false if the Message is not of type HTTP_MSG_RESPONSE,
1400
1401 * or if the response code is out of range (100-510).
1402
1403 */
1404
1405 PHP_METHOD(HttpMessage, setResponseCode)
1406
1407 {
1408
1409 long code;
1410
1411 getObject(http_message_object, obj);
1412
1413
1414
1415 if (obj->message->type != HTTP_MSG_RESPONSE) {
1416
1417 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_RESPONSE");
1418
1419 RETURN_FALSE;
1420
1421 }
1422
1423
1424
1425 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
1426
1427 RETURN_FALSE;
1428
1429 }
1430
1431 if (code < 100 || code > 510) {
1432
1433 http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid response code (100-510): %ld", code);
1434
1435 RETURN_FALSE;
1436
1437 }
1438
1439
1440
1441 obj->message->info.response.code = code;
1442
1443 RETURN_TRUE;
1444
1445 }
1446
1447 /* }}} */
1448
1449
1450
1451 /* {{{ proto string HttpMessage::getRequestMethod()
1452
1453 *
1454
1455 * Get the Request Method of the Message.
1456
1457 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
1458
1459 */
1460
1461 PHP_METHOD(HttpMessage, getRequestMethod)
1462
1463 {
1464
1465 getObject(http_message_object, obj);
1466
1467
1468
1469 NO_ARGS;
1470
1471
1472
1473 if (obj->message->type != HTTP_MSG_REQUEST) {
1474
1475 http_error(E_NOTICE, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
1476
1477 RETURN_NULL();
1478
1479 }
1480
1481
1482
1483 RETURN_STRING(obj->message->info.request.method, 1);
1484
1485 }
1486
1487 /* }}} */
1488
1489
1490
1491 /* {{{ proto bool HttpMessage::setRequestMethod(string method)
1492
1493 *
1494
1495 * Set the Request Method of the HTTP Message.
1496
1497 * Returns false if the Message is not of type HTTP_MSG_REQUEST.
1498
1499 */
1500
1501 PHP_METHOD(HttpMessage, setRequestMethod)
1502
1503 {
1504
1505 char *method;
1506
1507 int method_len;
1508
1509 getObject(http_message_object, obj);
1510
1511
1512
1513 if (obj->message->type != HTTP_MSG_REQUEST) {
1514
1515 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
1516
1517 RETURN_FALSE;
1518
1519 }
1520
1521
1522
1523 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
1524
1525 RETURN_FALSE;
1526
1527 }
1528
1529 if (method_len < 1) {
1530
1531 http_error(E_WARNING, HTTP_E_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
1532
1533 RETURN_FALSE;
1534
1535 }
1536
1537 if (SUCCESS != http_check_method(method)) {
1538
1539 http_error_ex(E_WARNING, HTTP_E_PARAM, "Unkown request method: %s", method);
1540
1541 RETURN_FALSE;
1542
1543 }
1544
1545
1546
1547 if (obj->message->info.request.method) {
1548
1549 efree(obj->message->info.request.method);
1550
1551 }
1552
1553 obj->message->info.request.method = estrndup(method, method_len);
1554
1555 RETURN_TRUE;
1556
1557 }
1558
1559 /* }}} */
1560
1561
1562
1563 /* {{{ proto string HttpMessage::getRequestUri()
1564
1565 *
1566
1567 * Get the Request URI of the Message.
1568
1569 */
1570
1571 PHP_METHOD(HttpMessage, getRequestUri)
1572
1573 {
1574
1575 zval *uri;
1576
1577 getObject(http_message_object, obj);
1578
1579
1580
1581 NO_ARGS;
1582
1583
1584
1585 if (obj->message->type != HTTP_MSG_REQUEST) {
1586
1587 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
1588
1589 RETURN_NULL();
1590
1591 }
1592
1593
1594
1595 RETURN_STRING(obj->message->info.request.URI, 1);
1596
1597 }
1598
1599 /* }}} */
1600
1601
1602
1603 /* {{{ proto bool HttpMessage::setRequestUri(string URI)
1604
1605 *
1606
1607 * Set the Request URI of the HTTP Message.
1608
1609 * Returns false if the Message is not of type HTTP_MSG_REQUEST,
1610
1611 * or if paramtere URI was empty.
1612
1613 */
1614
1615 PHP_METHOD(HttpMessage, setRequestUri)
1616
1617 {
1618
1619 char *URI;
1620
1621 int URIlen;
1622
1623 getObject(http_message_object, obj);
1624
1625
1626
1627 if (obj->message->type != HTTP_MSG_REQUEST) {
1628
1629 http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is not of type HTTP_MSG_REQUEST");
1630
1631 RETURN_FALSE;
1632
1633 }
1634
1635 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) {
1636
1637 RETURN_FALSE;
1638
1639 }
1640
1641 if (URIlen < 1) {
1642
1643 http_error(E_WARNING, HTTP_E_PARAM, "Cannot set HttpMessage::requestUri to an empty string");
1644
1645 RETURN_FALSE;
1646
1647 }
1648
1649
1650
1651 if (obj->message->info.request.URI) {
1652
1653 efree(obj->message->info.request.URI);
1654
1655 }
1656
1657 obj->message->info.request.URI = estrndup(URI, URIlen);
1658
1659 RETURN_TRUE;
1660
1661 }
1662
1663 /* }}} */
1664
1665
1666
1667 /* {{{ proto string HttpMessage::getHttpVersion()
1668
1669 *
1670
1671 * Get the HTTP Protocol Version of the Message.
1672
1673 */
1674
1675 PHP_METHOD(HttpMessage, getHttpVersion)
1676
1677 {
1678
1679 char ver[4] = {0};
1680
1681 float version;
1682
1683 getObject(http_message_object, obj);
1684
1685
1686
1687 NO_ARGS;
1688
1689
1690
1691 switch (obj->message->type)
1692
1693 {
1694
1695 case HTTP_MSG_RESPONSE:
1696
1697 version = obj->message->info.response.http_version;
1698
1699 break;
1700
1701
1702
1703 case HTTP_MSG_REQUEST:
1704
1705 version = obj->message->info.request.http_version;
1706
1707 break;
1708
1709
1710
1711 case HTTP_MSG_NONE:
1712
1713 default:
1714
1715 RETURN_NULL();
1716
1717 }
1718
1719 sprintf(ver, "%1.1f", version);
1720
1721 RETURN_STRINGL(ver, 3, 1);
1722
1723 }
1724
1725 /* }}} */
1726
1727
1728
1729 /* {{{ proto bool HttpMessage::setHttpVersion(string version)
1730
1731 *
1732
1733 * Set the HTTP Protocol version of the Message.
1734
1735 * Returns false if version is invalid (1.0 and 1.1).
1736
1737 */
1738
1739 PHP_METHOD(HttpMessage, setHttpVersion)
1740
1741 {
1742
1743 char v[4];
1744
1745 zval *zv, *version;
1746
1747 getObject(http_message_object, obj);
1748
1749
1750
1751 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) {
1752
1753 return;
1754
1755 }
1756
1757
1758
1759 if (obj->message->type == HTTP_MSG_NONE) {
1760
1761 http_error(E_WARNING, HTTP_E_MSG, "Message is neither of type HTTP_MSG_RESPONSE nor HTTP_MSG_REQUEST");
1762
1763 RETURN_FALSE;
1764
1765 }
1766
1767
1768
1769 convert_to_double_ex(&zv);
1770
1771 sprintf(v, "%1.1f", Z_DVAL_P(zv));
1772
1773 if (strcmp(v, "1.0") && strcmp(v, "1.1")) {
1774
1775 http_error_ex(E_WARNING, HTTP_E_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %s", v);
1776
1777 RETURN_FALSE;
1778
1779 }
1780
1781
1782
1783 if (obj->message->type == HTTP_MSG_RESPONSE) {
1784
1785 obj->message->info.response.http_version = (float) Z_DVAL_P(zv);
1786
1787 } else {
1788
1789 obj->message->info.request.http_version = (float) Z_DVAL_P(zv);
1790
1791 }
1792
1793 RETURN_TRUE;
1794
1795 }
1796
1797 /* }}} */
1798
1799
1800
1801 /* {{{ proto HttpMessage HttpMessage::getParentMessage()
1802
1803 *
1804
1805 * Get parent Message.
1806
1807 */
1808
1809 PHP_METHOD(HttpMessage, getParentMessage)
1810
1811 {
1812
1813 getObject(http_message_object, obj);
1814
1815
1816
1817 NO_ARGS;
1818
1819
1820
1821 if (obj->message->parent) {
1822
1823 RETVAL_OBJVAL(obj->parent);
1824
1825 } else {
1826
1827 RETVAL_NULL();
1828
1829 }
1830
1831 }
1832
1833 /* }}} */
1834
1835
1836
1837 /* {{{ proto bool HttpMessage::send()
1838
1839 *
1840
1841 * Send the Message according to its type as Response or Request.
1842
1843 */
1844
1845 PHP_METHOD(HttpMessage, send)
1846
1847 {
1848
1849 getObject(http_message_object, obj);
1850
1851
1852
1853 NO_ARGS;
1854
1855
1856
1857 RETURN_SUCCESS(http_message_send(obj->message));
1858
1859 }
1860
1861 /* }}} */
1862
1863
1864
1865 /* {{{ proto string HttpMessage::toString([bool include_parent = true])
1866
1867 *
1868
1869 * Get the string representation of the Message.
1870
1871 */
1872
1873 PHP_METHOD(HttpMessage, toString)
1874
1875 {
1876
1877 char *string;
1878
1879 size_t length;
1880
1881 zend_bool include_parent = 1;
1882
1883 getObject(http_message_object, obj);
1884
1885
1886
1887 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
1888
1889 RETURN_FALSE;
1890
1891 }
1892
1893
1894
1895 if (include_parent) {
1896
1897 http_message_serialize(obj->message, &string, &length);
1898
1899 } else {
1900
1901 http_message_tostring(obj->message, &string, &length);
1902
1903 }
1904
1905 RETURN_STRINGL(string, length, 0);
1906
1907 }
1908
1909 /* }}} */
1910
1911
1912
1913 /* }}} */
1914
1915
1916
1917 #ifdef HTTP_HAVE_CURL
1918
1919 /* {{{ HttpRequest */
1920
1921
1922
1923 /* {{{ proto void HttpRequest::__construct([string url[, long request_method = HTTP_GET]])
1924
1925 *
1926
1927 * Instantiate a new HttpRequest object which can be used to issue HEAD, GET
1928
1929 * and POST (including posting files) HTTP requests.
1930
1931 */
1932
1933 PHP_METHOD(HttpRequest, __construct)
1934
1935 {
1936
1937 char *URL = NULL;
1938
1939 int URL_len;
1940
1941 long meth = -1;
1942
1943 getObject(http_request_object, obj);
1944
1945
1946
1947 SET_EH_THROW_HTTP();
1948
1949 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
1950
1951 INIT_PARR(obj, options);
1952
1953 INIT_PARR(obj, responseInfo);
1954
1955 INIT_PARR(obj, responseData);
1956
1957 INIT_PARR(obj, postData);
1958
1959 INIT_PARR(obj, postFiles);
1960
1961
1962
1963 if (URL) {
1964
1965 UPD_PROP(obj, string, url, URL);
1966
1967 }
1968
1969 if (meth > -1) {
1970
1971 UPD_PROP(obj, long, method, meth);
1972
1973 }
1974
1975 }
1976
1977 SET_EH_NORMAL();
1978
1979 }
1980
1981 /* }}} */
1982
1983
1984
1985 /* {{{ proto void HttpRequest::__destruct()
1986
1987 *
1988
1989 * Destroys the HttpRequest object.
1990
1991 */
1992
1993 PHP_METHOD(HttpRequest, __destruct)
1994
1995 {
1996
1997 getObject(http_request_object, obj);
1998
1999
2000
2001 NO_ARGS;
2002
2003
2004
2005 FREE_PARR(obj, options);
2006
2007 FREE_PARR(obj, responseInfo);
2008
2009 FREE_PARR(obj, responseData);
2010
2011 FREE_PARR(obj, postData);
2012
2013 FREE_PARR(obj, postFiles);
2014
2015 }
2016
2017 /* }}} */
2018
2019
2020
2021 /* {{{ proto bool HttpRequest::setOptions(array options)
2022
2023 *
2024
2025 * Set the request options to use. See http_get() for a full list of available options.
2026
2027 */
2028
2029 PHP_METHOD(HttpRequest, setOptions)
2030
2031 {
2032
2033 char *key = NULL;
2034
2035 long idx = 0;
2036
2037 zval *opts, *old_opts, **opt;
2038
2039 getObject(http_request_object, obj);
2040
2041
2042
2043 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
2044
2045 RETURN_FALSE;
2046
2047 }
2048
2049
2050
2051 old_opts = GET_PROP(obj, options);
2052
2053
2054
2055 /* headers and cookies need extra attention -- thus cannot use array_merge() directly */
2056
2057 FOREACH_KEYVAL(opts, key, idx, opt) {
2058
2059 if (key) {
2060
2061 if (!strcmp(key, "headers")) {
2062
2063 zval **headers;
2064
2065 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
2066
2067 array_merge(*opt, *headers);
2068
2069 continue;
2070
2071 }
2072
2073 } else if (!strcmp(key, "cookies")) {
2074
2075 zval **cookies;
2076
2077 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
2078
2079 array_merge(*opt, *cookies);
2080
2081 continue;
2082
2083 }
2084
2085 }
2086
2087 zval_add_ref(opt);
2088
2089 add_assoc_zval(old_opts, key, *opt);
2090
2091
2092
2093 /* reset */
2094
2095 key = NULL;
2096
2097 }
2098
2099 }
2100
2101
2102
2103 RETURN_TRUE;
2104
2105 }
2106
2107 /* }}} */
2108
2109
2110
2111 /* {{{ proto array HttpRequest::getOptions()
2112
2113 *
2114
2115 * Get current set options.
2116
2117 */
2118
2119 PHP_METHOD(HttpRequest, getOptions)
2120
2121 {
2122
2123 zval *opts;
2124
2125 getObject(http_request_object, obj);
2126
2127
2128
2129 NO_ARGS;
2130
2131
2132
2133 opts = GET_PROP(obj, options);
2134
2135 array_init(return_value);
2136
2137 array_copy(opts, return_value);
2138
2139 }
2140
2141 /* }}} */
2142
2143
2144
2145 /* {{{ proto void HttpRequest::unsetOptions()
2146
2147 *
2148
2149 * Unset all options/headers/cookies.
2150
2151 */
2152
2153 PHP_METHOD(HttpRequest, unsetOptions)
2154
2155 {
2156
2157 getObject(http_request_object, obj);
2158
2159
2160
2161 NO_ARGS;
2162
2163
2164
2165 FREE_PARR(obj, options);
2166
2167 INIT_PARR(obj, options);
2168
2169 }
2170
2171 /* }}} */
2172
2173
2174
2175 /* {{{ proto bool HttpRequest::setSslOptions(array options)
2176
2177 *
2178
2179 * Set additional SSL options.
2180
2181 */
2182
2183 PHP_METHOD(HttpRequest, setSslOptions)
2184
2185 {
2186
2187 zval *opts, *old_opts, **ssl_options;
2188
2189 getObject(http_request_object, obj);
2190
2191
2192
2193 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
2194
2195 RETURN_FALSE;
2196
2197 }
2198
2199
2200
2201 old_opts = GET_PROP(obj, options);
2202
2203
2204
2205 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "ssl", sizeof("ssl"), (void **) &ssl_options)) {
2206
2207 array_merge(opts, *ssl_options);
2208
2209 } else {
2210
2211 zval_add_ref(&opts);
2212
2213 add_assoc_zval(old_opts, "ssl", opts);
2214
2215 }
2216
2217
2218
2219 RETURN_TRUE;
2220
2221 }
2222
2223 /* }}} */
2224
2225
2226
2227 /* {{{ proto array HttpRequest::getSslOtpions()
2228
2229 *
2230
2231 * Get previously set SSL options.
2232
2233 */
2234
2235 PHP_METHOD(HttpRequest, getSslOptions)
2236
2237 {
2238
2239 zval *opts, **ssl_options;
2240
2241 getObject(http_request_object, obj);
2242
2243
2244
2245 NO_ARGS;
2246
2247
2248
2249 opts = GET_PROP(obj, options);
2250
2251
2252
2253 array_init(return_value);
2254
2255
2256
2257 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "ssl", sizeof("ssl"), (void **) &ssl_options)) {
2258
2259 array_copy(*ssl_options, return_value);
2260
2261 }
2262
2263 }
2264
2265 /* }}} */
2266
2267
2268
2269 /* {{{ proto void HttpRequest::unsetSslOptions()
2270
2271 *
2272
2273 * Unset previously set SSL options.
2274
2275 */
2276
2277 PHP_METHOD(HttpRequest, unsetSslOptions)
2278
2279 {
2280
2281 zval *opts;
2282
2283 getObject(http_request_object, obj);
2284
2285
2286
2287 NO_ARGS;
2288
2289
2290
2291 opts = GET_PROP(obj, options);
2292
2293 zend_hash_del(Z_ARRVAL_P(opts), "ssl", sizeof("ssl"));
2294
2295 }
2296
2297 /* }}} */
2298
2299
2300
2301 /* {{{ proto bool HttpRequest::addHeaders(array headers)
2302
2303 *
2304
2305 * Add request header name/value pairs.
2306
2307 */
2308
2309 PHP_METHOD(HttpRequest, addHeaders)
2310
2311 {
2312
2313 zval *opts, **headers, *new_headers;
2314
2315 getObject(http_request_object, obj);
2316
2317
2318
2319 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &new_headers)) {
2320
2321 RETURN_FALSE;
2322
2323 }
2324
2325
2326
2327 opts = GET_PROP(obj, options);
2328
2329
2330
2331 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void **) &headers)) {
2332
2333 array_merge(new_headers, *headers);
2334
2335 } else {
2336
2337 zval_add_ref(&new_headers);
2338
2339 add_assoc_zval(opts, "headers", new_headers);
2340
2341 }
2342
2343
2344
2345 RETURN_TRUE;
2346
2347 }
2348
2349 /* }}} */
2350
2351
2352
2353 /* {{{ proto array HttpRequest::getHeaders()
2354
2355 *
2356
2357 * Get previously set request headers.
2358
2359 */
2360
2361 PHP_METHOD(HttpRequest, getHeaders)
2362
2363 {
2364
2365 zval *opts, **headers;
2366
2367 getObject(http_request_object, obj);
2368
2369
2370
2371 NO_ARGS;
2372
2373
2374
2375 opts = GET_PROP(obj, options);
2376
2377
2378
2379 array_init(return_value);
2380
2381
2382
2383 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void **) &headers)) {
2384
2385 array_copy(*headers, return_value);
2386
2387 }
2388
2389 }
2390
2391 /* }}} */
2392
2393
2394
2395 /* {{{ proto void HttpRequest::unsetHeaders()
2396
2397 *
2398
2399 * Unset previously set request headers.
2400
2401 */
2402
2403 PHP_METHOD(HttpRequest, unsetHeaders)
2404
2405 {
2406
2407 zval *opts;
2408
2409 getObject(http_request_object, obj);
2410
2411
2412
2413 NO_ARGS;
2414
2415
2416
2417 opts = GET_PROP(obj, options);
2418
2419 zend_hash_del(Z_ARRVAL_P(opts), "headers", sizeof("headers"));
2420
2421 }
2422
2423 /* }}} */
2424
2425
2426
2427 /* {{{ proto bool HttpRequest::addCookies(array cookies)
2428
2429 *
2430
2431 * Add cookies.
2432
2433 */
2434
2435 PHP_METHOD(HttpRequest, addCookies)
2436
2437 {
2438
2439 zval *opts, **cookies, *new_cookies;
2440
2441 getObject(http_request_object, obj);
2442
2443
2444
2445 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &new_cookies)) {
2446
2447 RETURN_FALSE;
2448
2449 }
2450
2451
2452
2453 opts = GET_PROP(obj, options);
2454
2455
2456
2457 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
2458
2459 array_merge(new_cookies, *cookies);
2460
2461 } else {
2462
2463 zval_add_ref(&new_cookies);
2464
2465 add_assoc_zval(opts, "cookies", new_cookies);
2466
2467 }
2468
2469
2470
2471 RETURN_TRUE;
2472
2473 }
2474
2475 /* }}} */
2476
2477
2478
2479 /* {{{ proto array HttpRequest::getCookies()
2480
2481 *
2482
2483 * Get previously set cookies.
2484
2485 */
2486
2487 PHP_METHOD(HttpRequest, getCookies)
2488
2489 {
2490
2491 zval *opts, **cookies;
2492
2493 getObject(http_request_object, obj);
2494
2495
2496
2497 NO_ARGS;
2498
2499
2500
2501 opts = GET_PROP(obj, options);
2502
2503
2504
2505 array_init(return_value);
2506
2507
2508
2509 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
2510
2511 array_copy(*cookies, return_value);
2512
2513 }
2514
2515 }
2516
2517 /* }}} */
2518
2519
2520
2521 /* {{{ proto void HttpRequest::unsetCookies()
2522
2523 *
2524
2525 */
2526
2527 PHP_METHOD(HttpRequest, unsetCookies)
2528
2529 {
2530
2531 zval *opts;
2532
2533 getObject(http_request_object, obj);
2534
2535
2536
2537 NO_ARGS;
2538
2539
2540
2541 opts = GET_PROP(obj, options);
2542
2543 zend_hash_del(Z_ARRVAL_P(opts), "cookies", sizeof("cookies"));
2544
2545 }
2546
2547 /* }}} */
2548
2549
2550
2551 /* {{{ proto bool HttpRequest::setURL(string url)
2552
2553 *
2554
2555 * Set the request URL.
2556
2557 */
2558
2559 PHP_METHOD(HttpRequest, setURL)
2560
2561 {
2562
2563 char *URL = NULL;
2564
2565 int URL_len;
2566
2567 getObject(http_request_object, obj);
2568
2569
2570
2571 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
2572
2573 RETURN_FALSE;
2574
2575 }
2576
2577
2578
2579 UPD_PROP(obj, string, url, URL);
2580
2581 RETURN_TRUE;
2582
2583 }
2584
2585 /* }}} */
2586
2587
2588
2589 /* {{{ proto string HttpRequest::getUrl()
2590
2591 *
2592
2593 * Get the previously set request URL.
2594
2595 */
2596
2597 PHP_METHOD(HttpRequest, getURL)
2598
2599 {
2600
2601 zval *URL;
2602
2603 getObject(http_request_object, obj);
2604
2605
2606
2607 NO_ARGS;
2608
2609
2610
2611 URL = GET_PROP(obj, url);
2612
2613 RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
2614
2615 }
2616
2617 /* }}} */
2618
2619
2620
2621 /* {{{ proto bool HttpRequest::setMethod(long request_method)
2622
2623 *
2624
2625 * Set the request methods; one of the <tt>HTTP_HEAD</tt>, <tt>HTTP_GET</tt> or
2626
2627 * <tt>HTTP_POST</tt> constants.
2628
2629 */
2630
2631 PHP_METHOD(HttpRequest, setMethod)
2632
2633 {
2634
2635 long meth;
2636
2637 getObject(http_request_object, obj);
2638
2639
2640
2641 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
2642
2643 RETURN_FALSE;
2644
2645 }
2646
2647
2648
2649 UPD_PROP(obj, long, method, meth);
2650
2651 RETURN_TRUE;
2652
2653 }
2654
2655 /* }}} */
2656
2657
2658
2659 /* {{{ proto long HttpRequest::getMethod()
2660
2661 *
2662
2663 * Get the previously set request method.
2664
2665 */
2666
2667 PHP_METHOD(HttpRequest, getMethod)
2668
2669 {
2670
2671 zval *meth;
2672
2673 getObject(http_request_object, obj);
2674
2675
2676
2677 NO_ARGS;
2678
2679
2680
2681 meth = GET_PROP(obj, method);
2682
2683 RETURN_LONG(Z_LVAL_P(meth));
2684
2685 }
2686
2687 /* }}} */
2688
2689
2690
2691 /* {{{ proto bool HttpRequest::setContentType(string content_type)
2692
2693 *
2694
2695 * Set the content type the post request should have.
2696
2697 * Use this only if you know what you're doing.
2698
2699 */
2700
2701 PHP_METHOD(HttpRequest, setContentType)
2702
2703 {
2704
2705 char *ctype;
2706
2707 int ct_len;
2708
2709 getObject(http_request_object, obj);
2710
2711
2712
2713 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
2714
2715 RETURN_FALSE;
2716
2717 }
2718
2719
2720
2721 if (!strchr(ctype, '/')) {
2722
2723 http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", ctype);
2724
2725 RETURN_FALSE;
2726
2727 }
2728
2729
2730
2731 UPD_PROP(obj, string, contentType, ctype);
2732
2733 RETURN_TRUE;
2734
2735 }
2736
2737 /* }}} */
2738
2739
2740
2741 /* {{{ proto string HttpRequest::getContentType()
2742
2743 *
2744
2745 * Get the previously content type.
2746
2747 */
2748
2749 PHP_METHOD(HttpRequest, getContentType)
2750
2751 {
2752
2753 zval *ctype;
2754
2755 getObject(http_request_object, obj);
2756
2757
2758
2759 NO_ARGS;
2760
2761
2762
2763 ctype = GET_PROP(obj, contentType);
2764
2765 RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
2766
2767 }
2768
2769 /* }}} */
2770
2771
2772
2773 /* {{{ proto bool HttpRequest::setQueryData(mixed query_data)
2774
2775 *
2776
2777 * Set the URL query parameters to use.
2778
2779 * Overwrites previously set query parameters.
2780
2781 * Affects any request types.
2782
2783 */
2784
2785 PHP_METHOD(HttpRequest, setQueryData)
2786
2787 {
2788
2789 zval *qdata;
2790
2791 char *query_data = NULL;
2792
2793 getObject(http_request_object, obj);
2794
2795
2796
2797 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &qdata)) {
2798
2799 RETURN_FALSE;
2800
2801 }
2802
2803
2804
2805 if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
2806
2807 if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) {
2808
2809 RETURN_FALSE;
2810
2811 }
2812
2813 UPD_PROP(obj, string, queryData, query_data);
2814
2815 efree(query_data);
2816
2817 RETURN_TRUE;
2818
2819 }
2820
2821
2822
2823 convert_to_string(qdata);
2824
2825 UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
2826
2827 RETURN_TRUE;
2828
2829 }
2830
2831 /* }}} */
2832
2833
2834
2835 /* {{{ proto string HttpRequest::getQueryData()
2836
2837 *
2838
2839 * Get the current query data in form of an urlencoded query string.
2840
2841 */
2842
2843 PHP_METHOD(HttpRequest, getQueryData)
2844
2845 {
2846
2847 zval *qdata;
2848
2849 getObject(http_request_object, obj);
2850
2851
2852
2853 NO_ARGS;
2854
2855
2856
2857 qdata = GET_PROP(obj, queryData);
2858
2859 RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
2860
2861 }
2862
2863 /* }}} */
2864
2865
2866
2867 /* {{{ proto bool HttpRequest::addQueryData(array query_params)
2868
2869 *
2870
2871 * Add parameters to the query parameter list.
2872
2873 * Affects any request type.
2874
2875 */
2876
2877 PHP_METHOD(HttpRequest, addQueryData)
2878
2879 {
2880
2881 zval *qdata, *old_qdata;
2882
2883 char *query_data = NULL;
2884
2885 getObject(http_request_object, obj);
2886
2887
2888
2889 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
2890
2891 RETURN_FALSE;
2892
2893 }
2894
2895
2896
2897 old_qdata = GET_PROP(obj, queryData);
2898
2899
2900
2901 if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, NULL)) {
2902
2903 RETURN_FALSE;
2904
2905 }
2906
2907
2908
2909 UPD_PROP(obj, string, queryData, query_data);
2910
2911 efree(query_data);
2912
2913
2914
2915 RETURN_TRUE;
2916
2917 }
2918
2919 /* }}} */
2920
2921
2922
2923 /* {{{ proto void HttpRequest::unsetQueryData()
2924
2925 *
2926
2927 * Clean the query parameters.
2928
2929 * Affects any request type.
2930
2931 */
2932
2933 PHP_METHOD(HttpRequest, unsetQueryData)
2934
2935 {
2936
2937 getObject(http_request_object, obj);
2938
2939
2940
2941 NO_ARGS;
2942
2943
2944
2945 UPD_PROP(obj, string, queryData, "");
2946
2947 }
2948
2949 /* }}} */
2950
2951
2952
2953 /* {{{ proto bool HttpRequest::addPostData(array post_data)
2954
2955 *
2956
2957 * Adds POST data entries.
2958
2959 * Affects only POST requests.
2960
2961 */
2962
2963 PHP_METHOD(HttpRequest, addPostData)
2964
2965 {
2966
2967 zval *post, *post_data;
2968
2969 getObject(http_request_object, obj);
2970
2971
2972
2973 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
2974
2975 RETURN_FALSE;
2976
2977 }
2978
2979
2980
2981 post = GET_PROP(obj, postData);
2982
2983 array_merge(post_data, post);
2984
2985
2986
2987 RETURN_TRUE;
2988
2989 }
2990
2991 /* }}} */
2992
2993
2994
2995 /* {{{ proto bool HttpRequest::setPostData(array post_data)
2996
2997 *
2998
2999 * Set the POST data entries.
3000
3001 * Overwrites previously set POST data.
3002
3003 * Affects only POST requests.
3004
3005 */
3006
3007 PHP_METHOD(HttpRequest, setPostData)
3008
3009 {
3010
3011 zval *post, *post_data;
3012
3013 getObject(http_request_object, obj);
3014
3015
3016
3017 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
3018
3019 RETURN_FALSE;
3020
3021 }
3022
3023
3024
3025 post = GET_PROP(obj, postData);
3026
3027 zend_hash_clean(Z_ARRVAL_P(post));
3028
3029 array_copy(post_data, post);
3030
3031
3032
3033 RETURN_TRUE;
3034
3035 }
3036
3037 /* }}}*/
3038
3039
3040
3041 /* {{{ proto array HttpRequest::getPostData()
3042
3043 *
3044
3045 * Get previously set POST data.
3046
3047 */
3048
3049 PHP_METHOD(HttpRequest, getPostData)
3050
3051 {
3052
3053 zval *post_data;
3054
3055 getObject(http_request_object, obj);
3056
3057
3058
3059 NO_ARGS;
3060
3061
3062
3063 post_data = GET_PROP(obj, postData);
3064
3065 array_init(return_value);
3066
3067 array_copy(post_data, return_value);
3068
3069 }
3070
3071 /* }}} */
3072
3073
3074
3075 /* {{{ proto void HttpRequest::unsetPostData()
3076
3077 *
3078
3079 * Clean POST data entires.
3080
3081 * Affects only POST requests.
3082
3083 */
3084
3085 PHP_METHOD(HttpRequest, unsetPostData)
3086
3087 {
3088
3089 zval *post_data;
3090
3091 getObject(http_request_object, obj);
3092
3093
3094
3095 NO_ARGS;
3096
3097
3098
3099 post_data = GET_PROP(obj, postData);
3100
3101 zend_hash_clean(Z_ARRVAL_P(post_data));
3102
3103 }
3104
3105 /* }}} */
3106
3107
3108
3109 /* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
3110
3111 *
3112
3113 * Add a file to the POST request.
3114
3115 * Affects only POST requests.
3116
3117 */
3118
3119 PHP_METHOD(HttpRequest, addPostFile)
3120
3121 {
3122
3123 zval *files, *entry;
3124
3125 char *name, *file, *type = NULL;
3126
3127 int name_len, file_len, type_len = 0;
3128
3129 getObject(http_request_object, obj);
3130
3131
3132
3133 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
3134
3135 RETURN_FALSE;
3136
3137 }
3138
3139
3140
3141 if (type_len) {
3142
3143 if (!strchr(type, '/')) {
3144
3145 http_error_ex(E_WARNING, HTTP_E_PARAM, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
3146
3147 RETURN_FALSE;
3148
3149 }
3150
3151 } else {
3152
3153 type = "application/x-octetstream";
3154
3155 type_len = sizeof("application/x-octetstream") - 1;
3156
3157 }
3158
3159
3160
3161 MAKE_STD_ZVAL(entry);
3162
3163 array_init(entry);
3164
3165
3166
3167 add_assoc_stringl(entry, "name", name, name_len, 1);
3168
3169 add_assoc_stringl(entry, "type", type, type_len, 1);
3170
3171 add_assoc_stringl(entry, "file", file, file_len, 1);
3172
3173
3174
3175 files = GET_PROP(obj, postFiles);
3176
3177 add_next_index_zval(files, entry);
3178
3179
3180
3181 RETURN_TRUE;
3182
3183 }
3184
3185 /* }}} */
3186
3187
3188
3189 /* {{{ proto array HttpRequest::getPostFiles()
3190
3191 *
3192
3193 * Get all previously added POST files.
3194
3195 */
3196
3197 PHP_METHOD(HttpRequest, getPostFiles)
3198
3199 {
3200
3201 zval *files;
3202
3203 getObject(http_request_object, obj);
3204
3205
3206
3207 NO_ARGS;
3208
3209
3210
3211 files = GET_PROP(obj, postFiles);
3212
3213
3214
3215 array_init(return_value);
3216
3217 array_copy(files, return_value);
3218
3219 }
3220
3221 /* }}} */
3222
3223
3224
3225 /* {{{ proto void HttpRequest::unsetPostFiles()
3226
3227 *
3228
3229 * Unset the POST files list.
3230
3231 * Affects only POST requests.
3232
3233 */
3234
3235 PHP_METHOD(HttpRequest, unsetPostFiles)
3236
3237 {
3238
3239 zval *files;
3240
3241 getObject(http_request_object, obj);
3242
3243
3244
3245 NO_ARGS;
3246
3247
3248
3249 files = GET_PROP(obj, postFiles);
3250
3251 zend_hash_clean(Z_ARRVAL_P(files));
3252
3253 }
3254
3255 /* }}} */
3256
3257
3258
3259 /* {{{ proto array HttpRequest::getResponseData()
3260
3261 *
3262
3263 * Get all response data after the request has been sent.
3264
3265 */
3266
3267 PHP_METHOD(HttpRequest, getResponseData)
3268
3269 {
3270
3271 zval *data;
3272
3273 getObject(http_request_object, obj);
3274
3275
3276
3277 NO_ARGS;
3278
3279
3280
3281 data = GET_PROP(obj, responseData);
3282
3283 array_init(return_value);
3284
3285 array_copy(data, return_value);
3286
3287 }
3288
3289 /* }}} */
3290
3291
3292
3293 /* {{{ proto mixed HttpRequest::getResponseHeader([string name])
3294
3295 *
3296
3297 * Get response header(s) after the request has been sent.
3298
3299 */
3300
3301 PHP_METHOD(HttpRequest, getResponseHeader)
3302
3303 {
3304
3305 zval *data, **headers, **header;
3306
3307 char *header_name = NULL;
3308
3309 int header_len = 0;
3310
3311 getObject(http_response_object, obj);
3312
3313
3314
3315 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) {
3316
3317 RETURN_FALSE;
3318
3319 }
3320
3321
3322
3323 data = GET_PROP(obj, responseData);
3324
3325 if (SUCCESS != zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
3326
3327 RETURN_FALSE;
3328
3329 }
3330
3331
3332
3333 if (!header_len || !header_name) {
3334
3335 array_init(return_value);
3336
3337 array_copy(*headers, return_value);
3338
3339 } else if (SUCCESS == zend_hash_find(Z_ARRVAL_PP(headers), pretty_key(header_name, header_len, 1, 1), header_len + 1, (void **) &header)) {
3340
3341 RETURN_STRINGL(Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
3342
3343 } else {
3344
3345 RETURN_FALSE;
3346
3347 }
3348
3349 }
3350
3351 /* }}} */
3352
3353
3354
3355 /* {{{ proto array HttpRequest::getResponseCookie([string name])
3356
3357 *
3358
3359 * Get response cookie(s) after the request has been sent.
3360
3361 */
3362
3363 PHP_METHOD(HttpRequest, getResponseCookie)
3364
3365 {
3366
3367 zval *data, **headers;
3368
3369 char *cookie_name = NULL;
3370
3371 int cookie_len = 0;
3372
3373 getObject(http_request_object, obj);
3374
3375
3376
3377 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cookie_name, &cookie_len)) {
3378
3379 RETURN_FALSE;
3380
3381 }
3382
3383
3384
3385 array_init(return_value);
3386
3387
3388
3389 data = GET_PROP(obj, responseData);
3390
3391 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
3392
3393 ulong idx = 0;
3394
3395 char *key = NULL;
3396
3397 zval **header = NULL;
3398
3399
3400
3401 FOREACH_HASH_KEYVAL(Z_ARRVAL_PP(headers), key, idx, header) {
3402
3403 if (key && !strcasecmp(key, "Set-Cookie")) {
3404
3405 /* several cookies? */
3406
3407 if (Z_TYPE_PP(header) == IS_ARRAY) {
3408
3409 zval **cookie;
3410
3411
3412
3413 FOREACH_HASH_VAL(Z_ARRVAL_PP(header), cookie) {
3414
3415 zval *cookie_hash;
3416
3417 MAKE_STD_ZVAL(cookie_hash);
3418
3419 array_init(cookie_hash);
3420
3421
3422
3423 if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(cookie), Z_ARRVAL_P(cookie_hash))) {
3424
3425 if (!cookie_len) {
3426
3427 add_next_index_zval(return_value, cookie_hash);
3428
3429 } else {
3430
3431 zval **name;
3432
3433
3434
3435 if ( (SUCCESS == zend_hash_find(Z_ARRVAL_P(cookie_hash), "name", sizeof("name"), (void **) &name)) &&
3436
3437 (!strcmp(Z_STRVAL_PP(name), cookie_name))) {
3438
3439 add_next_index_zval(return_value, cookie_hash);
3440
3441 return; /* <<< FOUND >>> */
3442
3443 } else {
3444
3445 zval_dtor(cookie_hash);
3446
3447 efree(cookie_hash);
3448
3449 }
3450
3451 }
3452
3453 } else {
3454
3455 zval_dtor(cookie_hash);
3456
3457 efree(cookie_hash);
3458
3459 }
3460
3461 }
3462
3463 } else {
3464
3465 zval *cookie_hash;
3466
3467 MAKE_STD_ZVAL(cookie_hash);
3468
3469 array_init(cookie_hash);
3470
3471
3472
3473 if (SUCCESS == http_parse_cookie(Z_STRVAL_PP(header), Z_ARRVAL_P(cookie_hash))) {
3474
3475 if (!cookie_len) {
3476
3477 add_next_index_zval(return_value, cookie_hash);
3478
3479 } else {
3480
3481 zval **name;
3482
3483
3484
3485 if ( (SUCCESS == zend_hash_find(Z_ARRVAL_P(cookie_hash), "name", sizeof("name"), (void **) &name)) &&
3486
3487 (!strcmp(Z_STRVAL_PP(name), cookie_name))) {
3488
3489 add_next_index_zval(return_value, cookie_hash);
3490
3491 } else {
3492
3493 zval_dtor(cookie_hash);
3494
3495 efree(cookie_hash);
3496
3497 }
3498
3499 }
3500
3501 } else {
3502
3503 zval_dtor(cookie_hash);
3504
3505 efree(cookie_hash);
3506
3507 }
3508
3509 }
3510
3511 break;
3512
3513 }
3514
3515 /* reset key */
3516
3517 key = NULL;
3518
3519 }
3520
3521 }
3522
3523 }
3524
3525 /* }}} */
3526
3527
3528
3529 /* {{{ proto string HttpRequest::getResponseBody()
3530
3531 *
3532
3533 * Get the response body after the request has been sent.
3534
3535 */
3536
3537 PHP_METHOD(HttpRequest, getResponseBody)
3538
3539 {
3540
3541 zval *data, **body;
3542
3543 getObject(http_request_object, obj);
3544
3545
3546
3547 NO_ARGS;
3548
3549
3550
3551 data = GET_PROP(obj, responseData);
3552
3553 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
3554
3555 RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
3556
3557 } else {
3558
3559 RETURN_FALSE;
3560
3561 }
3562
3563 }
3564
3565 /* }}} */
3566
3567
3568
3569 /* {{{ proto int HttpRequest::getResponseCode()
3570
3571 *
3572
3573 * Get the response code after the request has been sent.
3574
3575 */
3576
3577 PHP_METHOD(HttpRequest, getResponseCode)
3578
3579 {
3580
3581 zval *code;
3582
3583 getObject(http_request_object, obj);
3584
3585
3586
3587 NO_ARGS;
3588
3589
3590
3591 code = GET_PROP(obj, responseCode);
3592
3593 RETURN_LONG(Z_LVAL_P(code));
3594
3595 }
3596
3597 /* }}} */
3598
3599
3600
3601 /* {{{ proto array HttpRequest::getResponseInfo([string name])
3602
3603 *
3604
3605 * Get response info after the request has been sent.
3606
3607 * See http_get() for a full list of returned info.
3608
3609 */
3610
3611 PHP_METHOD(HttpRequest, getResponseInfo)
3612
3613 {
3614
3615 zval *info, **infop;
3616
3617 char *info_name = NULL;
3618
3619 int info_len = 0;
3620
3621 getObject(http_request_object, obj);
3622
3623
3624
3625 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) {
3626
3627 RETURN_FALSE;
3628
3629 }
3630
3631
3632
3633 info = GET_PROP(obj, responseInfo);
3634
3635
3636
3637 if (info_len && info_name) {
3638
3639 if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void **) &infop)) {
3640
3641 RETURN_ZVAL(*infop, 1, ZVAL_PTR_DTOR);
3642
3643 } else {
3644
3645 http_error_ex(E_NOTICE, HTTP_E_PARAM, "Could not find response info named %s", info_name);
3646
3647 RETURN_FALSE;
3648
3649 }
3650
3651 } else {
3652
3653 array_init(return_value);
3654
3655 array_copy(info, return_value);
3656
3657 }
3658
3659 }
3660
3661 /* }}}*/
3662
3663
3664
3665 /* {{{ proto HttpMessage HttpRequest::getResponseMessage()
3666
3667 *
3668
3669 * Get the full response as HttpMessage object.
3670
3671 */
3672
3673 PHP_METHOD(HttpRequest, getResponseMessage)
3674
3675 {
3676
3677 zval *message;
3678
3679 getObject(http_request_object, obj);
3680
3681
3682
3683 NO_ARGS;
3684
3685
3686
3687 message = GET_PROP(obj, responseMessage);
3688
3689 Z_TYPE_P(return_value) = IS_OBJECT;
3690
3691 return_value->is_ref = 1;
3692
3693 return_value->value.obj = message->value.obj;
3694
3695 zval_add_ref(&return_value);
3696
3697 }
3698
3699
3700
3701 /* {{{ proto bool HttpRequest::send()
3702
3703 *
3704
3705 * Send the HTTP request.
3706
3707 *
3708
3709 * GET example:
3710
3711 * <pre>
3712
3713 * <?php
3714
3715 * $r = new HttpRequest('http://example.com/feed.rss', HTTP_GET);
3716
3717 * $r->setOptions(array('lastmodified' => filemtime('local.rss')));
3718
3719 * $r->addQueryData(array('category' => 3));
3720
3721 * try {
3722
3723 * $r->send();
3724
3725 * if ($r->getResponseCode() == 200) {
3726
3727 * file_put_contents('local.rss', $r->getResponseBody());
3728
3729 * }
3730
3731 * } catch (HttpException $ex) {
3732
3733 * echo $ex;
3734
3735 * }
3736
3737 * ?>
3738
3739 * </pre>
3740
3741 *
3742
3743 * POST example:
3744
3745 * <pre>
3746
3747 * <?php
3748
3749 * $r = new HttpRequest('http://example.com/form.php', HTTP_POST);
3750
3751 * $r->setOptions(array('cookies' => array('lang' => 'de')));
3752
3753 * $r->addPostData(array('user' => 'mike', 'pass' => 's3c|r3t'));
3754
3755 * $r->addPostFile('image', 'profile.jpg', 'image/jpeg');
3756
3757 * if ($r->send()) {
3758
3759 * echo $r->getResponseBody();
3760
3761 * }
3762
3763 * ?>
3764
3765 * </pre>
3766
3767 */
3768
3769 PHP_METHOD(HttpRequest, send)
3770
3771 {
3772
3773 STATUS status = FAILURE;
3774
3775 zval *meth, *URL, *qdata, *opts, *info, *resp;
3776
3777 char *request_uri;
3778
3779 getObject(http_request_object, obj);
3780
3781
3782
3783 NO_ARGS;
3784
3785
3786
3787 SET_EH_THROW_HTTP();
3788
3789
3790
3791 if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
3792
3793 http_error(E_WARNING, HTTP_E_CURL, "Could not initilaize curl");
3794
3795 RETURN_FALSE;
3796
3797 }
3798
3799
3800
3801 meth = GET_PROP(obj, method);
3802
3803 URL = GET_PROP(obj, url);
3804
3805 qdata = GET_PROP(obj, queryData);
3806
3807 opts = GET_PROP(obj, options);
3808
3809 info = GET_PROP(obj, responseInfo);
3810
3811 resp = GET_PROP(obj, responseData);
3812
3813
3814
3815 // HTTP_URI_MAXLEN+1 long char *
3816
3817 request_uri = http_absolute_uri_ex(Z_STRVAL_P(URL), Z_STRLEN_P(URL), NULL, 0, NULL, 0, 0);
3818
3819
3820
3821 if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
3822
3823 if (!strchr(request_uri, '?')) {
3824
3825 strcat(request_uri, "?");
3826
3827 } else {
3828
3829 strcat(request_uri, "&");
3830
3831 }
3832
3833 strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
3834
3835 }
3836
3837
3838
3839 switch (Z_LVAL_P(meth))
3840
3841 {
3842
3843 case HTTP_GET:
3844
3845 case HTTP_HEAD:
3846
3847 status = http_request_ex(obj->ch, Z_LVAL_P(meth), request_uri, NULL, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
3848
3849 break;
3850
3851
3852
3853 case HTTP_PUT:
3854
3855 break;
3856
3857
3858
3859 case HTTP_POST:
3860
3861 default:
3862
3863 {
3864
3865 http_request_body body;
3866
3867 zval *fields = GET_PROP(obj, postData), *files = GET_PROP(obj, postFiles);
3868
3869
3870
3871 if (SUCCESS == (status = http_request_body_fill(&body, Z_ARRVAL_P(fields), Z_ARRVAL_P(files)))) {
3872
3873 status = http_request_ex(obj->ch, Z_LVAL_P(meth), request_uri, &body, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &obj->response);
3874
3875 http_request_body_dtor(&body);
3876
3877 }
3878
3879 }
3880
3881 break;
3882
3883 }
3884
3885
3886
3887 efree(request_uri);
3888
3889
3890
3891 /* final data handling */
3892
3893 if (status == SUCCESS) {
3894
3895 http_message *msg;
3896
3897
3898
3899 if (msg = http_message_parse(PHPSTR_VAL(&obj->response), PHPSTR_LEN(&obj->response))) {
3900
3901 zval *headers, *message;
3902
3903 char *body;
3904
3905 size_t body_len;
3906
3907
3908
3909 UPD_PROP(obj, long, responseCode, msg->info.response.code);
3910
3911
3912
3913 MAKE_STD_ZVAL(headers)
3914
3915 array_init(headers);
3916
3917
3918
3919 zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
3920
3921 phpstr_data(PHPSTR(msg), &body, &body_len);
3922
3923
3924
3925 add_assoc_zval(resp, "headers", headers);
3926
3927 add_assoc_stringl(resp, "body", body, body_len, 0);
3928
3929
3930
3931 message = GET_PROP(obj, responseMessage);
3932
3933 zval_dtor(message);
3934
3935 Z_TYPE_P(message) = IS_OBJECT;
3936
3937 message->value.obj = http_message_object_from_msg(msg);
3938
3939 SET_PROP(obj, responseMessage, message);
3940
3941 } else {
3942
3943 status = FAILURE;
3944
3945 }
3946
3947 }
3948
3949
3950
3951 SET_EH_NORMAL();
3952
3953 RETURN_SUCCESS(status);
3954
3955 }
3956
3957 /* }}} */
3958
3959 /* }}} */
3960
3961 #endif /* HTTP_HAVE_CURL */
3962
3963
3964
3965 #endif /* ZEND_ENGINE_2 */
3966
3967
3968
3969 /*
3970
3971 * Local variables:
3972
3973 * tab-width: 4
3974
3975 * c-basic-offset: 4
3976
3977 * End:
3978
3979 * vim600: noet sw=4 ts=4 fdm=marker
3980
3981 * vim<600: noet sw=4 ts=4
3982
3983 */
3984