1 : /*
2 : +--------------------------------------------------------------------+
3 : | PECL :: http |
4 : +--------------------------------------------------------------------+
5 : | Redistribution and use in source and binary forms, with or without |
6 : | modification, are permitted provided that the conditions mentioned |
7 : | in the accompanying LICENSE file are met. |
8 : +--------------------------------------------------------------------+
9 : | Copyright (c) 2004-2007, Michael Wallner <mike@php.net> |
10 : +--------------------------------------------------------------------+
11 : */
12 :
13 : /* $Id: http_functions.c,v 1.166 2007/03/27 12:17:02 mike Exp $ */
14 :
15 : #define HTTP_WANT_SAPI
16 : #define HTTP_WANT_CURL
17 : #define HTTP_WANT_ZLIB
18 : #include "php_http.h"
19 :
20 : #include "php_ini.h"
21 : #include "ext/standard/php_string.h"
22 : #include "zend_operators.h"
23 :
24 : #ifdef HTTP_HAVE_SESSION
25 : # include "ext/session/php_session.h"
26 : #endif
27 :
28 : #include "php_http_api.h"
29 : #include "php_http_cache_api.h"
30 : #include "php_http_cookie_api.h"
31 : #include "php_http_date_api.h"
32 : #include "php_http_encoding_api.h"
33 : #include "php_http_headers_api.h"
34 : #include "php_http_message_api.h"
35 : #include "php_http_request_api.h"
36 : #include "php_http_request_method_api.h"
37 : #include "php_http_persistent_handle_api.h"
38 : #include "php_http_send_api.h"
39 : #include "php_http_url_api.h"
40 :
41 : /* {{{ proto string http_date([int timestamp])
42 : Compose a valid HTTP date regarding RFC 1123 looking like: "Wed, 22 Dec 2004 11:34:47 GMT" */
43 : PHP_FUNCTION(http_date)
44 4 : {
45 4 : long t = -1;
46 :
47 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
48 0 : RETURN_FALSE;
49 : }
50 :
51 4 : if (t == -1) {
52 1 : t = HTTP_G->request.time;
53 : }
54 :
55 4 : RETURN_STRING(http_date(t), 0);
56 : }
57 : /* }}} */
58 :
59 : /* {{{ proto string http_build_url([mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE[, array &new_url]]]])
60 : Build an URL. */
61 : PHP_FUNCTION(http_build_url)
62 12 : {
63 12 : char *url_str = NULL;
64 12 : size_t url_len = 0;
65 12 : long flags = HTTP_URL_REPLACE;
66 12 : zval *z_old_url = NULL, *z_new_url = NULL, *z_composed_url = NULL;
67 12 : php_url *old_url = NULL, *new_url = NULL, *composed_url = NULL;
68 :
69 12 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z!/lz", &z_old_url, &z_new_url, &flags, &z_composed_url) != SUCCESS) {
70 0 : RETURN_FALSE;
71 : }
72 :
73 12 : if (z_new_url) {
74 13 : if (Z_TYPE_P(z_new_url) == IS_ARRAY || Z_TYPE_P(z_new_url) == IS_OBJECT) {
75 4 : new_url = http_url_from_struct(NULL, HASH_OF(z_new_url));
76 : } else {
77 5 : convert_to_string(z_new_url);
78 5 : if (!(new_url = php_url_parse_ex(Z_STRVAL_P(z_new_url), Z_STRLEN_P(z_new_url)))) {
79 0 : http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_new_url));
80 0 : RETURN_FALSE;
81 : }
82 : }
83 : }
84 :
85 12 : if (z_old_url) {
86 13 : if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) {
87 1 : old_url = http_url_from_struct(NULL, HASH_OF(z_old_url));
88 : } else {
89 11 : convert_to_string(z_old_url);
90 11 : if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) {
91 0 : if (new_url) {
92 0 : php_url_free(new_url);
93 : }
94 0 : http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_old_url));
95 0 : RETURN_FALSE;
96 : }
97 : }
98 : }
99 :
100 12 : if (z_composed_url) {
101 1 : http_build_url(flags, old_url, new_url, &composed_url, &url_str, &url_len);
102 1 : http_url_tostruct(composed_url, z_composed_url);
103 1 : php_url_free(composed_url);
104 : } else {
105 11 : http_build_url(flags, old_url, new_url, NULL, &url_str, &url_len);
106 : }
107 :
108 12 : if (new_url) {
109 9 : php_url_free(new_url);
110 : }
111 12 : if (old_url) {
112 12 : php_url_free(old_url);
113 : }
114 :
115 12 : RETURN_STRINGL(url_str, url_len, 0);
116 : }
117 : /* }}} */
118 :
119 : /* {{{ proto string http_build_str(array query [, string prefix[, string arg_separator]])
120 : Opponent to parse_str(). */
121 : PHP_FUNCTION(http_build_str)
122 4 : {
123 : zval *formdata;
124 4 : char *prefix = NULL, *arg_sep = INI_STR("arg_separator.output");
125 4 : int prefix_len = 0, arg_sep_len = strlen(arg_sep);
126 : phpstr formstr;
127 :
128 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) {
129 0 : RETURN_FALSE;
130 : }
131 :
132 4 : if (!arg_sep_len) {
133 0 : arg_sep = HTTP_URL_ARGSEP;
134 0 : arg_sep_len = lenof(HTTP_URL_ARGSEP);
135 : }
136 :
137 4 : phpstr_init(&formstr);
138 4 : if (SUCCESS != http_urlencode_hash_recursive(HASH_OF(formdata), &formstr, arg_sep, arg_sep_len, prefix, prefix_len)) {
139 0 : RETURN_FALSE;
140 : }
141 :
142 4 : if (!formstr.used) {
143 0 : phpstr_dtor(&formstr);
144 0 : RETURN_NULL();
145 : }
146 :
147 4 : RETURN_PHPSTR_VAL(&formstr);
148 : }
149 : /* }}} */
150 :
151 : #define HTTP_DO_NEGOTIATE(type, supported, rs_array) \
152 : { \
153 : HashTable *result; \
154 : if ((result = http_negotiate_ ##type(supported))) { \
155 : char *key; \
156 : uint key_len; \
157 : ulong idx; \
158 : \
159 : if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \
160 : RETVAL_STRINGL(key, key_len-1, 0); \
161 : } else { \
162 : RETVAL_NULL(); \
163 : } \
164 : \
165 : if (rs_array) { \
166 : zend_hash_copy(Z_ARRVAL_P(rs_array), result, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); \
167 : } \
168 : \
169 : zend_hash_destroy(result); \
170 : FREE_HASHTABLE(result); \
171 : \
172 : } else { \
173 : zval **value; \
174 : \
175 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \
176 : if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void *) &value)) { \
177 : RETVAL_ZVAL(*value, 1, 0); \
178 : } else { \
179 : RETVAL_NULL(); \
180 : } \
181 : \
182 : if (rs_array) { \
183 : HashPosition pos; \
184 : zval **value; \
185 : \
186 : FOREACH_VAL(pos, supported, value) { \
187 : convert_to_string_ex(value); \
188 : add_assoc_double(rs_array, Z_STRVAL_PP(value), 1.0); \
189 : } \
190 : } \
191 : } \
192 : }
193 :
194 : /* {{{ proto string http_negotiate_language(array supported[, array &result])
195 : Negotiate the clients preferred language. */
196 : PHP_FUNCTION(http_negotiate_language)
197 2 : {
198 2 : zval *supported, *rs_array = NULL;
199 :
200 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
201 0 : RETURN_FALSE;
202 : }
203 :
204 2 : if (rs_array) {
205 1 : zval_dtor(rs_array);
206 1 : array_init(rs_array);
207 : }
208 :
209 2 : HTTP_DO_NEGOTIATE(language, supported, rs_array);
210 : }
211 : /* }}} */
212 :
213 : /* {{{ proto string http_negotiate_charset(array supported[, array &result])
214 : Negotiate the clients preferred charset. */
215 : PHP_FUNCTION(http_negotiate_charset)
216 2 : {
217 2 : zval *supported, *rs_array = NULL;
218 :
219 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
220 0 : RETURN_FALSE;
221 : }
222 :
223 2 : if (rs_array) {
224 1 : zval_dtor(rs_array);
225 1 : array_init(rs_array);
226 : }
227 :
228 2 : HTTP_DO_NEGOTIATE(charset, supported, rs_array);
229 : }
230 : /* }}} */
231 :
232 : /* {{{ proto string http_negotiate_content_type(array supported[, array &result])
233 : Negotiate the clients preferred content type. */
234 : PHP_FUNCTION(http_negotiate_content_type)
235 2 : {
236 2 : zval *supported, *rs_array = NULL;
237 :
238 2 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array)) {
239 0 : RETURN_FALSE;
240 : }
241 :
242 2 : if (rs_array) {
243 1 : zval_dtor(rs_array);
244 1 : array_init(rs_array);
245 : }
246 :
247 2 : HTTP_DO_NEGOTIATE(content_type, supported, rs_array);
248 : }
249 : /* }}} */
250 :
251 : /* {{{ proto bool http_send_status(int status)
252 : Send HTTP status code. */
253 : PHP_FUNCTION(http_send_status)
254 0 : {
255 0 : int status = 0;
256 :
257 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) {
258 0 : RETURN_FALSE;
259 : }
260 0 : if (status < 100 || status > 510) {
261 0 : http_error_ex(HE_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
262 0 : RETURN_FALSE;
263 : }
264 :
265 0 : RETURN_SUCCESS(http_send_status(status));
266 : }
267 : /* }}} */
268 :
269 : /* {{{ proto bool http_send_last_modified([int timestamp])
270 : Send a "Last-Modified" header with a valid HTTP date. */
271 : PHP_FUNCTION(http_send_last_modified)
272 0 : {
273 0 : long t = -1;
274 :
275 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
276 0 : RETURN_FALSE;
277 : }
278 :
279 0 : if (t == -1) {
280 0 : t = HTTP_G->request.time;
281 : }
282 :
283 0 : RETURN_SUCCESS(http_send_last_modified(t));
284 : }
285 : /* }}} */
286 :
287 : /* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream'])
288 : Send the Content-Type of the sent entity. This is particularly important if you use the http_send() API. */
289 : PHP_FUNCTION(http_send_content_type)
290 10 : {
291 10 : char *ct = "application/x-octetstream";
292 10 : int ct_len = lenof("application/x-octetstream");
293 :
294 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) {
295 0 : RETURN_FALSE;
296 : }
297 :
298 10 : RETURN_SUCCESS(http_send_content_type(ct, ct_len));
299 : }
300 : /* }}} */
301 :
302 : /* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false])
303 : Send the Content-Disposition. */
304 : PHP_FUNCTION(http_send_content_disposition)
305 0 : {
306 : char *filename;
307 : int f_len;
308 0 : zend_bool send_inline = 0;
309 :
310 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) {
311 0 : RETURN_FALSE;
312 : }
313 0 : RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline));
314 : }
315 : /* }}} */
316 :
317 : /* {{{ proto bool http_match_modified([int timestamp[, bool for_range = false]])
318 : Matches the given unix timestamp against the clients "If-Modified-Since" resp. "If-Unmodified-Since" HTTP headers. */
319 : PHP_FUNCTION(http_match_modified)
320 0 : {
321 0 : long t = -1;
322 0 : zend_bool for_range = 0;
323 :
324 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &t, &for_range) != SUCCESS) {
325 0 : RETURN_FALSE;
326 : }
327 :
328 : // current time if not supplied (senseless though)
329 0 : if (t == -1) {
330 0 : t = HTTP_G->request.time;
331 : }
332 :
333 0 : if (for_range) {
334 0 : RETURN_BOOL(http_match_last_modified("HTTP_IF_UNMODIFIED_SINCE", t));
335 : }
336 0 : RETURN_BOOL(http_match_last_modified("HTTP_IF_MODIFIED_SINCE", t));
337 : }
338 : /* }}} */
339 :
340 : /* {{{ proto bool http_match_etag(string etag[, bool for_range = false])
341 : Matches the given ETag against the clients "If-Match" resp. "If-None-Match" HTTP headers. */
342 : PHP_FUNCTION(http_match_etag)
343 0 : {
344 : int etag_len;
345 : char *etag;
346 0 : zend_bool for_range = 0;
347 :
348 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &etag, &etag_len, &for_range) != SUCCESS) {
349 0 : RETURN_FALSE;
350 : }
351 :
352 0 : if (for_range) {
353 0 : RETURN_BOOL(http_match_etag("HTTP_IF_MATCH", etag));
354 : }
355 0 : RETURN_BOOL(http_match_etag("HTTP_IF_NONE_MATCH", etag));
356 : }
357 : /* }}} */
358 :
359 : /* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]])
360 : Attempts to cache the sent entity by its last modification date. */
361 : PHP_FUNCTION(http_cache_last_modified)
362 2 : {
363 2 : long last_modified = 0, send_modified = 0, t;
364 : zval *zlm;
365 :
366 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
367 0 : RETURN_FALSE;
368 : }
369 :
370 2 : HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
371 :
372 2 : t = HTTP_G->request.time;
373 :
374 : /* 0 or omitted */
375 2 : if (!last_modified) {
376 : /* does the client have? (att: caching "forever") */
377 1 : if ((zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE", 1))) {
378 0 : last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm));
379 : /* send current time */
380 : } else {
381 1 : send_modified = t;
382 : }
383 : /* negative value is supposed to be expiration time */
384 1 : } else if (last_modified < 0) {
385 1 : last_modified += t;
386 1 : send_modified = t;
387 : /* send supplied time explicitly */
388 : } else {
389 0 : send_modified = last_modified;
390 : }
391 :
392 2 : RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
393 : }
394 : /* }}} */
395 :
396 : /* {{{ proto bool http_cache_etag([string etag])
397 : Attempts to cache the sent entity by its ETag, either supplied or generated by the hash algorithm specified by the INI setting "http.etag.mode". */
398 : PHP_FUNCTION(http_cache_etag)
399 10 : {
400 10 : char *etag = NULL;
401 10 : int etag_len = 0;
402 :
403 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
404 0 : RETURN_FALSE;
405 : }
406 :
407 10 : HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
408 :
409 10 : RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
410 : }
411 : /* }}} */
412 :
413 : /* {{{ proto string ob_etaghandler(string data, int mode)
414 : For use with ob_start(). Output buffer handler generating an ETag with the hash algorithm specified with the INI setting "http.etag.mode". */
415 : PHP_FUNCTION(ob_etaghandler)
416 8 : {
417 : char *data;
418 : int data_len;
419 : long mode;
420 :
421 8 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
422 0 : RETURN_FALSE;
423 : }
424 :
425 8 : Z_TYPE_P(return_value) = IS_STRING;
426 8 : http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
427 : }
428 : /* }}} */
429 :
430 : /* {{{ proto void http_throttle(double sec[, int bytes = 40960])
431 : Sets the throttle delay and send buffer size for use with http_send() API. */
432 : PHP_FUNCTION(http_throttle)
433 1 : {
434 1 : long chunk_size = HTTP_SENDBUF_SIZE;
435 : double interval;
436 :
437 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &interval, &chunk_size)) {
438 0 : return;
439 : }
440 :
441 1 : HTTP_G->send.throttle_delay = interval;
442 1 : HTTP_G->send.buffer_size = chunk_size;
443 : }
444 : /* }}} */
445 :
446 : /* {{{ proto void http_redirect([string url[, array params[, bool session = false[, int status = 302]]]])
447 : Redirect to the given url. */
448 : PHP_FUNCTION(http_redirect)
449 3 : {
450 3 : int url_len = 0;
451 3 : size_t query_len = 0;
452 3 : zend_bool session = 0, free_params = 0;
453 3 : zval *params = NULL;
454 3 : long status = HTTP_REDIRECT;
455 3 : char *query = NULL, *url = NULL, *URI, *LOC, *RED = NULL;
456 :
457 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bl", &url, &url_len, ¶ms, &session, &status) != SUCCESS) {
458 0 : RETURN_FALSE;
459 : }
460 :
461 : #ifdef HTTP_HAVE_SESSION
462 : /* append session info */
463 3 : if (session) {
464 1 : if (!params) {
465 0 : free_params = 1;
466 0 : MAKE_STD_ZVAL(params);
467 0 : array_init(params);
468 : }
469 1 : if (PS(session_status) == php_session_active) {
470 1 : if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
471 0 : http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not append session information");
472 : }
473 : }
474 : }
475 : #endif
476 :
477 : /* treat params array with http_build_query() */
478 3 : if (params) {
479 2 : if (SUCCESS != http_urlencode_hash_ex(Z_ARRVAL_P(params), 0, NULL, 0, &query, &query_len)) {
480 0 : if (free_params) {
481 0 : zval_dtor(params);
482 0 : FREE_ZVAL(params);
483 : }
484 0 : if (query) {
485 0 : efree(query);
486 : }
487 0 : RETURN_FALSE;
488 : }
489 : }
490 :
491 3 : URI = http_absolute_url(url);
492 :
493 3 : if (query_len) {
494 2 : spprintf(&LOC, 0, "Location: %s?%s", URI, query);
495 2 : if (status != 300) {
496 2 : spprintf(&RED, 0, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, query, URI, query);
497 : }
498 : } else {
499 1 : spprintf(&LOC, 0, "Location: %s", URI);
500 1 : if (status != 300) {
501 1 : spprintf(&RED, 0, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
502 : }
503 : }
504 :
505 3 : efree(URI);
506 3 : if (query) {
507 2 : efree(query);
508 : }
509 3 : if (free_params) {
510 0 : zval_dtor(params);
511 0 : FREE_ZVAL(params);
512 : }
513 :
514 3 : switch (status) {
515 : case 300:
516 0 : RETVAL_SUCCESS(http_send_status_header(status, LOC));
517 0 : efree(LOC);
518 0 : return;
519 :
520 : case HTTP_REDIRECT_PERM:
521 : case HTTP_REDIRECT_FOUND:
522 : case HTTP_REDIRECT_POST:
523 : case HTTP_REDIRECT_PROXY:
524 : case HTTP_REDIRECT_TEMP:
525 1 : break;
526 :
527 : case 306:
528 : default:
529 0 : http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Unsupported redirection status code: %ld", status);
530 : case HTTP_REDIRECT:
531 2 : if ( SG(request_info).request_method &&
532 : strcasecmp(SG(request_info).request_method, "HEAD") &&
533 : strcasecmp(SG(request_info).request_method, "GET")) {
534 0 : status = HTTP_REDIRECT_POST;
535 : } else {
536 2 : status = HTTP_REDIRECT_FOUND;
537 : }
538 : break;
539 : }
540 :
541 3 : RETURN_SUCCESS(http_exit_ex(status, LOC, RED, 1));
542 : }
543 : /* }}} */
544 :
545 : /* {{{ proto bool http_send_data(string data)
546 : Sends raw data with support for (multiple) range requests. */
547 : PHP_FUNCTION(http_send_data)
548 14 : {
549 : int data_len;
550 : char *data_buf;
551 :
552 14 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data_buf, &data_len) != SUCCESS) {
553 0 : RETURN_FALSE;
554 : }
555 :
556 14 : RETURN_SUCCESS(http_send_data(data_buf, data_len));
557 : }
558 : /* }}} */
559 :
560 : /* {{{ proto bool http_send_file(string file)
561 : Sends a file with support for (multiple) range requests. */
562 : PHP_FUNCTION(http_send_file)
563 12 : {
564 : char *file;
565 12 : int flen = 0;
566 :
567 12 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &flen) != SUCCESS) {
568 0 : RETURN_FALSE;
569 : }
570 12 : if (!flen) {
571 0 : RETURN_FALSE;
572 : }
573 :
574 12 : RETURN_SUCCESS(http_send_file(file));
575 : }
576 : /* }}} */
577 :
578 : /* {{{ proto bool http_send_stream(resource stream)
579 : Sends an already opened stream with support for (multiple) range requests. */
580 : PHP_FUNCTION(http_send_stream)
581 0 : {
582 : zval *zstream;
583 : php_stream *file;
584 :
585 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) {
586 0 : RETURN_FALSE;
587 : }
588 :
589 0 : php_stream_from_zval(file, &zstream);
590 0 : RETURN_SUCCESS(http_send_stream(file));
591 : }
592 : /* }}} */
593 :
594 : /* {{{ proto string http_chunked_decode(string encoded)
595 : Decodes a string that was HTTP-chunked encoded. */
596 : PHP_FUNCTION(http_chunked_decode)
597 4 : {
598 4 : char *encoded = NULL, *decoded = NULL;
599 4 : size_t decoded_len = 0;
600 4 : int encoded_len = 0;
601 :
602 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) {
603 0 : RETURN_FALSE;
604 : }
605 :
606 4 : if (NULL != http_encoding_dechunk(encoded, encoded_len, &decoded, &decoded_len)) {
607 4 : RETURN_STRINGL(decoded, (int) decoded_len, 0);
608 : } else {
609 0 : RETURN_FALSE;
610 : }
611 : }
612 : /* }}} */
613 :
614 : /* {{{ proto object http_parse_message(string message)
615 : Parses (a) http_message(s) into a simple recursive object structure. */
616 : PHP_FUNCTION(http_parse_message)
617 8 : {
618 : char *message;
619 : int message_len;
620 8 : http_message *msg = NULL;
621 :
622 8 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &message, &message_len)) {
623 0 : RETURN_NULL();
624 : }
625 :
626 8 : if ((msg = http_message_parse(message, message_len))) {
627 8 : object_init(return_value);
628 8 : http_message_tostruct_recursive(msg, return_value);
629 8 : http_message_free(&msg);
630 : } else {
631 0 : RETURN_NULL();
632 : }
633 : }
634 : /* }}} */
635 :
636 : /* {{{ proto array http_parse_headers(string header)
637 : Parses HTTP headers into an associative array. */
638 : PHP_FUNCTION(http_parse_headers)
639 1 : {
640 : char *header;
641 : int header_len;
642 :
643 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) {
644 0 : RETURN_FALSE;
645 : }
646 :
647 1 : array_init(return_value);
648 1 : if (SUCCESS != http_parse_headers(header, return_value)) {
649 0 : zval_dtor(return_value);
650 0 : http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse headers");
651 0 : RETURN_FALSE;
652 : }
653 : }
654 : /* }}}*/
655 :
656 : /* {{{ proto object http_parse_cookie(string cookie[, int flags[, array allowed_extras]])
657 : Parses HTTP cookies like sent in a response into a struct. */
658 : PHP_FUNCTION(http_parse_cookie)
659 33 : {
660 33 : char *cookie, **allowed_extras = NULL;
661 33 : int i = 0, cookie_len;
662 33 : long flags = 0;
663 33 : zval *allowed_extras_array = NULL, **entry = NULL;
664 : HashPosition pos;
665 : http_cookie_list list;
666 :
667 33 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!", &cookie, &cookie_len, &flags, &allowed_extras_array)) {
668 0 : RETURN_FALSE;
669 : }
670 :
671 33 : if (allowed_extras_array) {
672 1 : allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
673 2 : FOREACH_VAL(pos, allowed_extras_array, entry) {
674 1 : ZVAL_ADDREF(*entry);
675 1 : convert_to_string_ex(entry);
676 1 : allowed_extras[i++] = estrndup(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry));
677 1 : zval_ptr_dtor(entry);
678 : }
679 : }
680 :
681 33 : if (http_parse_cookie_ex(&list, cookie, flags, allowed_extras)) {
682 33 : object_init(return_value);
683 33 : http_cookie_list_tostruct(&list, return_value);
684 33 : http_cookie_list_dtor(&list);
685 : } else {
686 0 : RETVAL_FALSE;
687 : }
688 :
689 33 : if (allowed_extras) {
690 2 : for (i = 0; allowed_extras[i]; ++i) {
691 1 : efree(allowed_extras[i]);
692 : }
693 1 : efree(allowed_extras);
694 : }
695 : }
696 : /* }}} */
697 :
698 : /* {{{ proto string http_build_cookie(array cookie)
699 : Build a cookie string from an array/object like returned by http_parse_cookie(). */
700 : PHP_FUNCTION(http_build_cookie)
701 0 : {
702 0 : char *str = NULL;
703 0 : size_t len = 0;
704 : zval *strct;
705 : http_cookie_list list;
706 :
707 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &strct)) {
708 0 : RETURN_FALSE;
709 : }
710 :
711 0 : http_cookie_list_fromstruct(&list, strct);
712 0 : http_cookie_list_tostring(&list, &str, &len);
713 0 : http_cookie_list_dtor(&list);
714 :
715 0 : RETURN_STRINGL(str, len, 0);
716 : }
717 : /* }}} */
718 :
719 : /* {{{ proto object http_parse_params(string param[, int flags = HTTP_PARAMS_DEFAULT])
720 : Parse parameter list. */
721 : PHP_FUNCTION(http_parse_params)
722 6 : {
723 : char *param;
724 : int param_len;
725 : zval *params;
726 6 : long flags = HTTP_PARAMS_DEFAULT;
727 :
728 6 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", ¶m, ¶m_len, &flags)) {
729 0 : RETURN_FALSE;
730 : }
731 :
732 6 : params = ecalloc(1, sizeof(zval));
733 6 : array_init(params);
734 6 : if (SUCCESS != http_parse_params(param, flags, Z_ARRVAL_P(params))) {
735 0 : zval_dtor(params);
736 0 : FREE_ZVAL(params);
737 0 : RETURN_FALSE;
738 : }
739 6 : object_init(return_value);
740 6 : add_property_zval(return_value, "params", params);
741 : }
742 : /* }}} */
743 :
744 : /* {{{ proto array http_get_request_headers(void)
745 : Get a list of incoming HTTP headers. */
746 : PHP_FUNCTION(http_get_request_headers)
747 0 : {
748 0 : NO_ARGS;
749 :
750 0 : array_init(return_value);
751 0 : http_get_request_headers(Z_ARRVAL_P(return_value));
752 0 : }
753 : /* }}} */
754 :
755 : /* {{{ proto string http_get_request_body(void)
756 : Get the raw request body (e.g. POST or PUT data). */
757 : PHP_FUNCTION(http_get_request_body)
758 0 : {
759 : char *body;
760 : size_t length;
761 :
762 0 : NO_ARGS;
763 :
764 0 : if (SUCCESS == http_get_request_body(&body, &length)) {
765 0 : RETURN_STRINGL(body, (int) length, 0);
766 : } else {
767 0 : RETURN_NULL();
768 : }
769 : }
770 : /* }}} */
771 :
772 : /* {{{ proto resource http_get_request_body_stream(void)
773 : Create a stream to read the raw request body (e.g. POST or PUT data). This function can only be used once if the request method was another than POST. */
774 : PHP_FUNCTION(http_get_request_body_stream)
775 0 : {
776 : php_stream *s;
777 :
778 0 : NO_ARGS;
779 :
780 0 : if ((s = http_get_request_body_stream())) {
781 0 : php_stream_to_zval(s, return_value);
782 : } else {
783 0 : http_error(HE_WARNING, HTTP_E_RUNTIME, "Failed to create request body stream");
784 0 : RETURN_NULL();
785 : }
786 : }
787 : /* }}} */
788 :
789 : /* {{{ proto bool http_match_request_header(string header, string value[, bool match_case = false])
790 : Match an incoming HTTP header. */
791 : PHP_FUNCTION(http_match_request_header)
792 3 : {
793 : char *header, *value;
794 : int header_len, value_len;
795 3 : zend_bool match_case = 0;
796 :
797 3 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &header, &header_len, &value, &value_len, &match_case)) {
798 0 : RETURN_FALSE;
799 : }
800 :
801 3 : RETURN_BOOL(http_match_request_header_ex(header, value, match_case));
802 : }
803 : /* }}} */
804 :
805 : /* {{{ proto object http_persistent_handles_count() */
806 : PHP_FUNCTION(http_persistent_handles_count)
807 3 : {
808 3 : NO_ARGS;
809 3 : object_init(return_value);
810 3 : if (!http_persistent_handle_statall_ex(HASH_OF(return_value))) {
811 0 : zval_dtor(return_value);
812 0 : RETURN_NULL();
813 : }
814 : }
815 : /* }}} */
816 :
817 : /* {{{ proto void http_persistent_handles_clean([string name]) */
818 : PHP_FUNCTION(http_persistent_handles_clean)
819 1 : {
820 1 : char *name_str = NULL;
821 1 : int name_len = 0;
822 :
823 1 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) {
824 1 : http_persistent_handle_cleanup_ex(name_str, name_len, 1);
825 : }
826 1 : }
827 : /* }}} */
828 :
829 : /* {{{ proto string http_persistent_handles_ident([string ident]) */
830 : PHP_FUNCTION(http_persistent_handles_ident)
831 0 : {
832 0 : char *ident_str = NULL;
833 0 : int ident_len = 0;
834 :
835 0 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ident_str, &ident_len)) {
836 0 : RETVAL_STRING(zend_ini_string(ZEND_STRS("http.persistent.handles.ident"), 0), 1);
837 0 : if (ident_str && ident_len) {
838 0 : zend_alter_ini_entry(ZEND_STRS("http.persistent.handles.ident"), ident_str, ident_len, ZEND_INI_USER, PHP_INI_STAGE_RUNTIME);
839 : }
840 : }
841 0 : }
842 : /* }}} */
843 :
844 : /* {{{ HAVE_CURL */
845 : #ifdef HTTP_HAVE_CURL
846 :
847 : #define RETVAL_RESPONSE_OR_BODY(request) \
848 : { \
849 : zval **bodyonly; \
850 : \
851 : /* check if only the body should be returned */ \
852 : if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void *) &bodyonly)) && zval_is_true(*bodyonly)) { \
853 : http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \
854 : \
855 : if (msg) { \
856 : RETVAL_STRINGL(PHPSTR_VAL(&msg->body), PHPSTR_LEN(&msg->body), 1); \
857 : http_message_free(&msg); \
858 : } \
859 : } else { \
860 : RETVAL_STRINGL(request.conv.response.data, request.conv.response.used, 1); \
861 : } \
862 : }
863 :
864 : /* {{{ proto string http_get(string url[, array options[, array &info]])
865 : Performs an HTTP GET request on the supplied url. */
866 : PHP_FUNCTION(http_get)
867 5 : {
868 5 : zval *options = NULL, *info = NULL;
869 : char *URL;
870 : int URL_len;
871 : http_request request;
872 :
873 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
874 0 : RETURN_FALSE;
875 : }
876 :
877 5 : if (info) {
878 2 : zval_dtor(info);
879 2 : array_init(info);
880 : }
881 :
882 5 : RETVAL_FALSE;
883 :
884 5 : http_request_init_ex(&request, NULL, HTTP_GET, URL);
885 5 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
886 5 : http_request_exec(&request);
887 5 : if (info) {
888 2 : http_request_info(&request, Z_ARRVAL_P(info));
889 : }
890 5 : RETVAL_RESPONSE_OR_BODY(request);
891 : }
892 5 : http_request_dtor(&request);
893 : }
894 : /* }}} */
895 :
896 : /* {{{ proto string http_head(string url[, array options[, array &info]])
897 : Performs an HTTP HEAD request on the supplied url. */
898 : PHP_FUNCTION(http_head)
899 0 : {
900 0 : zval *options = NULL, *info = NULL;
901 : char *URL;
902 : int URL_len;
903 : http_request request;
904 :
905 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
906 0 : RETURN_FALSE;
907 : }
908 :
909 0 : if (info) {
910 0 : zval_dtor(info);
911 0 : array_init(info);
912 : }
913 :
914 0 : RETVAL_FALSE;
915 :
916 0 : http_request_init_ex(&request, NULL, HTTP_HEAD, URL);
917 0 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
918 0 : http_request_exec(&request);
919 0 : if (info) {
920 0 : http_request_info(&request, Z_ARRVAL_P(info));
921 : }
922 0 : RETVAL_RESPONSE_OR_BODY(request);
923 : }
924 0 : http_request_dtor(&request);
925 : }
926 : /* }}} */
927 :
928 : /* {{{ proto string http_post_data(string url, string data[, array options[, array &info]])
929 : Performs an HTTP POST request on the supplied url. */
930 : PHP_FUNCTION(http_post_data)
931 0 : {
932 0 : zval *options = NULL, *info = NULL;
933 : char *URL, *postdata;
934 : int postdata_len, URL_len;
935 : http_request_body body;
936 : http_request request;
937 :
938 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
939 0 : RETURN_FALSE;
940 : }
941 :
942 0 : if (info) {
943 0 : zval_dtor(info);
944 0 : array_init(info);
945 : }
946 :
947 0 : RETVAL_FALSE;
948 :
949 0 : http_request_init_ex(&request, NULL, HTTP_POST, URL);
950 0 : request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, postdata, postdata_len, 0);
951 0 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
952 0 : http_request_exec(&request);
953 0 : if (info) {
954 0 : http_request_info(&request, Z_ARRVAL_P(info));
955 : }
956 0 : RETVAL_RESPONSE_OR_BODY(request);
957 : }
958 0 : http_request_dtor(&request);
959 : }
960 : /* }}} */
961 :
962 : /* {{{ proto string http_post_fields(string url, array data[, array files[, array options[, array &info]]])
963 : Performs an HTTP POST request on the supplied url. */
964 : PHP_FUNCTION(http_post_fields)
965 0 : {
966 0 : zval *options = NULL, *info = NULL, *fields = NULL, *files = NULL;
967 : char *URL;
968 : int URL_len;
969 : http_request_body body;
970 : http_request request;
971 :
972 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa!|a!a/!z", &URL, &URL_len, &fields, &files, &options, &info) != SUCCESS) {
973 0 : RETURN_FALSE;
974 : }
975 :
976 0 : if (!http_request_body_fill(&body, fields ? Z_ARRVAL_P(fields) : NULL, files ? Z_ARRVAL_P(files) : NULL)) {
977 0 : RETURN_FALSE;
978 : }
979 :
980 0 : if (info) {
981 0 : zval_dtor(info);
982 0 : array_init(info);
983 : }
984 :
985 0 : RETVAL_FALSE;
986 :
987 0 : http_request_init_ex(&request, NULL, HTTP_POST, URL);
988 0 : request.body = &body;
989 0 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
990 0 : http_request_exec(&request);
991 0 : if (info) {
992 0 : http_request_info(&request, Z_ARRVAL_P(info));
993 : }
994 0 : RETVAL_RESPONSE_OR_BODY(request);
995 : }
996 0 : http_request_dtor(&request);
997 : }
998 : /* }}} */
999 :
1000 : /* {{{ proto string http_put_file(string url, string file[, array options[, array &info]])
1001 : Performs an HTTP PUT request on the supplied url. */
1002 : PHP_FUNCTION(http_put_file)
1003 0 : {
1004 : char *URL, *file;
1005 : int URL_len, f_len;
1006 0 : zval *options = NULL, *info = NULL;
1007 : php_stream *stream;
1008 : php_stream_statbuf ssb;
1009 : http_request_body body;
1010 : http_request request;
1011 :
1012 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &file, &f_len, &options, &info)) {
1013 0 : RETURN_FALSE;
1014 : }
1015 :
1016 0 : if (!(stream = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) {
1017 0 : RETURN_FALSE;
1018 : }
1019 0 : if (php_stream_stat(stream, &ssb)) {
1020 0 : php_stream_close(stream);
1021 0 : RETURN_FALSE;
1022 : }
1023 :
1024 0 : if (info) {
1025 0 : zval_dtor(info);
1026 0 : array_init(info);
1027 : }
1028 :
1029 0 : RETVAL_FALSE;
1030 :
1031 0 : http_request_init_ex(&request, NULL, HTTP_PUT, URL);
1032 0 : request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
1033 0 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
1034 0 : http_request_exec(&request);
1035 0 : if (info) {
1036 0 : http_request_info(&request, Z_ARRVAL_P(info));
1037 : }
1038 0 : RETVAL_RESPONSE_OR_BODY(request);
1039 : }
1040 0 : http_request_dtor(&request);
1041 : }
1042 : /* }}} */
1043 :
1044 : /* {{{ proto string http_put_stream(string url, resource stream[, array options[, array &info]])
1045 : Performs an HTTP PUT request on the supplied url. */
1046 : PHP_FUNCTION(http_put_stream)
1047 0 : {
1048 0 : zval *resource, *options = NULL, *info = NULL;
1049 : char *URL;
1050 : int URL_len;
1051 : php_stream *stream;
1052 : php_stream_statbuf ssb;
1053 : http_request_body body;
1054 : http_request request;
1055 :
1056 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) {
1057 0 : RETURN_FALSE;
1058 : }
1059 :
1060 0 : php_stream_from_zval(stream, &resource);
1061 0 : if (php_stream_stat(stream, &ssb)) {
1062 0 : RETURN_FALSE;
1063 : }
1064 :
1065 0 : if (info) {
1066 0 : zval_dtor(info);
1067 0 : array_init(info);
1068 : }
1069 :
1070 0 : RETVAL_FALSE;
1071 :
1072 0 : http_request_init_ex(&request, NULL, HTTP_PUT, URL);
1073 0 : request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 0);
1074 0 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
1075 0 : http_request_exec(&request);
1076 0 : if (info) {
1077 0 : http_request_info(&request, Z_ARRVAL_P(info));
1078 : }
1079 0 : RETVAL_RESPONSE_OR_BODY(request);
1080 : }
1081 0 : http_request_dtor(&request);
1082 : }
1083 : /* }}} */
1084 :
1085 : /* {{{ proto string http_put_data(string url, string data[, array options[, array &info]])
1086 : Performs an HTTP PUT request on the supplied url. */
1087 : PHP_FUNCTION(http_put_data)
1088 1 : {
1089 : char *URL, *data;
1090 : int URL_len, data_len;
1091 1 : zval *options = NULL, *info = NULL;
1092 : http_request_body body;
1093 : http_request request;
1094 :
1095 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &data, &data_len, &options, &info)) {
1096 0 : RETURN_FALSE;
1097 : }
1098 :
1099 1 : if (info) {
1100 0 : zval_dtor(info);
1101 0 : array_init(info);
1102 : }
1103 :
1104 1 : RETVAL_FALSE;
1105 :
1106 1 : http_request_init_ex(&request, NULL, HTTP_PUT, URL);
1107 1 : request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
1108 1 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
1109 1 : http_request_exec(&request);
1110 1 : if (info) {
1111 0 : http_request_info(&request, Z_ARRVAL_P(info));
1112 : }
1113 1 : RETVAL_RESPONSE_OR_BODY(request);
1114 : }
1115 1 : http_request_dtor(&request);
1116 : }
1117 : /* }}} */
1118 :
1119 : /* {{{ proto string http_request(int method, string url[, string body[, array options[, array &info]]])
1120 : Performs a custom HTTP request on the supplied url. */
1121 : PHP_FUNCTION(http_request)
1122 0 : {
1123 : long meth;
1124 0 : char *URL, *data = NULL;
1125 0 : int URL_len, data_len = 0;
1126 0 : zval *options = NULL, *info = NULL;
1127 : http_request_body body;
1128 : http_request request;
1129 :
1130 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|sa/!z", &meth, &URL, &URL_len, &data, &data_len, &options, &info)) {
1131 0 : RETURN_FALSE;
1132 : }
1133 :
1134 0 : if (info) {
1135 0 : zval_dtor(info);
1136 0 : array_init(info);
1137 : }
1138 :
1139 0 : RETVAL_FALSE;
1140 :
1141 0 : http_request_init_ex(&request, NULL, meth, URL);
1142 0 : request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
1143 0 : if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
1144 0 : http_request_exec(&request);
1145 0 : if (info) {
1146 0 : http_request_info(&request, Z_ARRVAL_P(info));
1147 : }
1148 0 : RETVAL_RESPONSE_OR_BODY(request);
1149 : }
1150 0 : http_request_dtor(&request);
1151 : }
1152 : /* }}} */
1153 :
1154 : /* {{{ proto string http_request_body_encode(array fields, array files)
1155 : Generate x-www-form-urlencoded resp. form-data encoded request body. */
1156 : PHP_FUNCTION(http_request_body_encode)
1157 0 : {
1158 0 : zval *fields = NULL, *files = NULL;
1159 : HashTable *fields_ht, *files_ht;
1160 : http_request_body body;
1161 : char *buf;
1162 : size_t len;
1163 :
1164 0 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!", &fields, &files)) {
1165 0 : RETURN_FALSE;
1166 : }
1167 :
1168 0 : fields_ht = (fields && Z_TYPE_P(fields) == IS_ARRAY) ? Z_ARRVAL_P(fields) : NULL;
1169 0 : files_ht = (files && Z_TYPE_P(files) == IS_ARRAY) ? Z_ARRVAL_P(files) : NULL;
1170 0 : if (http_request_body_fill(&body, fields_ht, files_ht) && (SUCCESS == http_request_body_encode(&body, &buf, &len))) {
1171 0 : RETVAL_STRINGL(buf, len, 0);
1172 : } else {
1173 0 : http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not encode request body");
1174 0 : RETVAL_FALSE;
1175 : }
1176 0 : http_request_body_dtor(&body);
1177 : }
1178 : #endif /* HTTP_HAVE_CURL */
1179 : /* }}} HAVE_CURL */
1180 :
1181 : /* {{{ proto int http_request_method_register(string method)
1182 : Register a custom request method. */
1183 : PHP_FUNCTION(http_request_method_register)
1184 6 : {
1185 : char *method;
1186 : int method_len;
1187 : ulong existing;
1188 :
1189 6 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
1190 0 : RETURN_FALSE;
1191 : }
1192 6 : if ((existing = http_request_method_exists(1, 0, method))) {
1193 0 : RETURN_LONG((long) existing);
1194 : }
1195 :
1196 6 : RETVAL_LONG((long) http_request_method_register(method, method_len));
1197 : }
1198 : /* }}} */
1199 :
1200 : /* {{{ proto bool http_request_method_unregister(mixed method)
1201 : Unregister a previously registered custom request method. */
1202 : PHP_FUNCTION(http_request_method_unregister)
1203 5 : {
1204 : zval *method;
1205 :
1206 5 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
1207 0 : RETURN_FALSE;
1208 : }
1209 :
1210 5 : switch (Z_TYPE_P(method)) {
1211 : case IS_OBJECT:
1212 0 : convert_to_string(method);
1213 : case IS_STRING:
1214 5 : if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
1215 0 : convert_to_long(method);
1216 : } else {
1217 : int mn;
1218 5 : if (!(mn = http_request_method_exists(1, 0, Z_STRVAL_P(method)))) {
1219 0 : RETURN_FALSE;
1220 : }
1221 5 : zval_dtor(method);
1222 5 : ZVAL_LONG(method, (long)mn);
1223 : }
1224 : case IS_LONG:
1225 5 : RETURN_SUCCESS(http_request_method_unregister(Z_LVAL_P(method)));
1226 : default:
1227 0 : RETURN_FALSE;
1228 : }
1229 : }
1230 : /* }}} */
1231 :
1232 : /* {{{ proto int http_request_method_exists(mixed method)
1233 : Check if a request method is registered (or available by default). */
1234 : PHP_FUNCTION(http_request_method_exists)
1235 78 : {
1236 78 : if (return_value_used) {
1237 : zval *method;
1238 :
1239 78 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) {
1240 0 : RETURN_FALSE;
1241 : }
1242 :
1243 78 : switch (Z_TYPE_P(method)) {
1244 : case IS_OBJECT:
1245 0 : convert_to_string(method);
1246 : case IS_STRING:
1247 39 : if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) {
1248 0 : convert_to_long(method);
1249 : } else {
1250 39 : RETURN_LONG((long) http_request_method_exists(1, 0, Z_STRVAL_P(method)));
1251 : }
1252 : case IS_LONG:
1253 39 : RETURN_LONG((long) http_request_method_exists(0, (int) Z_LVAL_P(method), NULL));
1254 : default:
1255 0 : RETURN_FALSE;
1256 : }
1257 : }
1258 : }
1259 : /* }}} */
1260 :
1261 : /* {{{ proto string http_request_method_name(int method)
1262 : Get the literal string representation of a standard or registered request method. */
1263 : PHP_FUNCTION(http_request_method_name)
1264 29 : {
1265 29 : if (return_value_used) {
1266 : long method;
1267 :
1268 29 : if ((SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method)) || (method < 0)) {
1269 0 : RETURN_FALSE;
1270 : }
1271 :
1272 29 : RETURN_STRING(estrdup(http_request_method_name((int) method)), 0);
1273 : }
1274 : }
1275 : /* }}} */
1276 :
1277 : /* {{{ */
1278 : #ifdef HTTP_HAVE_ZLIB
1279 :
1280 : /* {{{ proto string http_deflate(string data[, int flags = 0])
1281 : Compress data with gzip, zlib AKA deflate or raw deflate encoding. */
1282 : PHP_FUNCTION(http_deflate)
1283 4 : {
1284 : char *data;
1285 : int data_len;
1286 4 : long flags = 0;
1287 :
1288 4 : RETVAL_NULL();
1289 :
1290 4 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags)) {
1291 : char *encoded;
1292 : size_t encoded_len;
1293 :
1294 4 : if (SUCCESS == http_encoding_deflate(flags, data, data_len, &encoded, &encoded_len)) {
1295 4 : RETURN_STRINGL(encoded, (int) encoded_len, 0);
1296 : }
1297 : }
1298 : }
1299 : /* }}} */
1300 :
1301 : /* {{{ proto string http_inflate(string data)
1302 : Decompress data compressed with either gzip, deflate AKA zlib or raw deflate encoding. */
1303 : PHP_FUNCTION(http_inflate)
1304 6 : {
1305 : char *data;
1306 : int data_len;
1307 :
1308 6 : RETVAL_NULL();
1309 :
1310 6 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
1311 : char *decoded;
1312 : size_t decoded_len;
1313 :
1314 6 : if (SUCCESS == http_encoding_inflate(data, data_len, &decoded, &decoded_len)) {
1315 6 : RETURN_STRINGL(decoded, (int) decoded_len, 0);
1316 : }
1317 : }
1318 : }
1319 : /* }}} */
1320 :
1321 : /* {{{ proto string ob_deflatehandler(string data, int mode)
1322 : For use with ob_start(). The deflate output buffer handler can only be used once. */
1323 : PHP_FUNCTION(ob_deflatehandler)
1324 1 : {
1325 : char *data;
1326 : int data_len;
1327 : long mode;
1328 :
1329 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
1330 0 : RETURN_FALSE;
1331 : }
1332 :
1333 1 : http_ob_deflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
1334 1 : Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
1335 : }
1336 : /* }}} */
1337 :
1338 : /* {{{ proto string ob_inflatehandler(string data, int mode)
1339 : For use with ob_start(). Same restrictions as with ob_deflatehandler apply. */
1340 : PHP_FUNCTION(ob_inflatehandler)
1341 1 : {
1342 : char *data;
1343 : int data_len;
1344 : long mode;
1345 :
1346 1 : if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
1347 0 : RETURN_FALSE;
1348 : }
1349 :
1350 1 : http_ob_inflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
1351 1 : Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
1352 : }
1353 : /* }}} */
1354 :
1355 : #endif /* HTTP_HAVE_ZLIB */
1356 : /* }}} */
1357 :
1358 : /* {{{ proto int http_support([int feature = 0])
1359 : Check for feature that require external libraries. */
1360 : PHP_FUNCTION(http_support)
1361 15 : {
1362 15 : long feature = 0;
1363 :
1364 15 : RETVAL_LONG(0L);
1365 :
1366 15 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &feature)) {
1367 15 : RETVAL_LONG(http_support(feature));
1368 : }
1369 15 : }
1370 : /* }}} */
1371 :
1372 : /*
1373 : * Local variables:
1374 : * tab-width: 4
1375 : * c-basic-offset: 4
1376 : * End:
1377 : * vim600: noet sw=4 ts=4 fdm=marker
1378 : * vim<600: noet sw=4 ts=4
1379 : */
1380 :
|