PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - http - http_functions.c
Test: PHP Code Coverage
Date: 2008-09-05 Instrumented lines: 543
Code covered: 37.6 % Executed lines: 204
Legend: not executed executed

       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.171 2008/07/01 07:34:37 tony2001 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|HTTP_URL_FROM_ENV[, 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|HTTP_URL_FROM_ENV;
      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_DEFAULT(supported) \
     152                 :         { \
     153                 :                 zval **value; \
     154                 :                  \
     155                 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \
     156                 :                 if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void *) &value)) { \
     157                 :                         RETVAL_ZVAL(*value, 1, 0); \
     158                 :                 } else { \
     159                 :                         RETVAL_NULL(); \
     160                 :                 } \
     161                 :         }
     162                 : #define HTTP_DO_NEGOTIATE(type, supported, rs_array) \
     163                 : { \
     164                 :         HashTable *result; \
     165                 :         if ((result = http_negotiate_ ##type(supported))) { \
     166                 :                 char *key; \
     167                 :                 uint key_len; \
     168                 :                 ulong idx; \
     169                 :                  \
     170                 :                 if (zend_hash_num_elements(result) && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \
     171                 :                         RETVAL_STRINGL(key, key_len-1, 0); \
     172                 :                 } else { \
     173                 :                         HTTP_DO_NEGOTIATE_DEFAULT(supported); \
     174                 :                 } \
     175                 :                 \
     176                 :                 if (rs_array) { \
     177                 :                         zend_hash_copy(Z_ARRVAL_P(rs_array), result, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); \
     178                 :                 } \
     179                 :                 \
     180                 :                 zend_hash_destroy(result); \
     181                 :                 FREE_HASHTABLE(result); \
     182                 :                 \
     183                 :         } else { \
     184                 :                 HTTP_DO_NEGOTIATE_DEFAULT(supported); \
     185                 :                 \
     186                 :                 if (rs_array) { \
     187                 :                         HashPosition pos; \
     188                 :                         zval **value; \
     189                 :                          \
     190                 :                         FOREACH_VAL(pos, supported, value) { \
     191                 :                                 convert_to_string_ex(value); \
     192                 :                                 add_assoc_double(rs_array, Z_STRVAL_PP(value), 1.0); \
     193                 :                         } \
     194                 :                 } \
     195                 :         } \
     196                 : }
     197                 : 
     198                 : /* {{{ proto string http_negotiate_language(array supported[, array &result])
     199                 :         Negotiate the clients preferred language. */
     200                 : PHP_FUNCTION(http_negotiate_language)
     201               3 : {
     202               3 :         zval *supported, *rs_array = NULL;
     203                 : 
     204               3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
     205               0 :                 RETURN_FALSE;
     206                 :         }
     207                 :         
     208               3 :         if (rs_array) {
     209               1 :                 zval_dtor(rs_array);
     210               1 :                 array_init(rs_array);
     211                 :         }
     212                 :         
     213               3 :         HTTP_DO_NEGOTIATE(language, supported, rs_array);
     214                 : }
     215                 : /* }}} */
     216                 : 
     217                 : /* {{{ proto string http_negotiate_charset(array supported[, array &result])
     218                 :         Negotiate the clients preferred charset. */
     219                 : PHP_FUNCTION(http_negotiate_charset)
     220               3 : {
     221               3 :         zval *supported, *rs_array = NULL;
     222                 : 
     223               3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) {
     224               0 :                 RETURN_FALSE;
     225                 :         }
     226                 :         
     227               3 :         if (rs_array) {
     228               1 :                 zval_dtor(rs_array);
     229               1 :                 array_init(rs_array);
     230                 :         }
     231                 : 
     232               3 :         HTTP_DO_NEGOTIATE(charset, supported, rs_array);
     233                 : }
     234                 : /* }}} */
     235                 : 
     236                 : /* {{{ proto string http_negotiate_content_type(array supported[, array &result])
     237                 :         Negotiate the clients preferred content type. */
     238                 : PHP_FUNCTION(http_negotiate_content_type)
     239               3 : {
     240               3 :         zval *supported, *rs_array = NULL;
     241                 :         
     242               3 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array)) {
     243               0 :                 RETURN_FALSE;
     244                 :         }
     245                 :         
     246               3 :         if (rs_array) {
     247               1 :                 zval_dtor(rs_array);
     248               1 :                 array_init(rs_array);
     249                 :         }
     250                 :         
     251               3 :         HTTP_DO_NEGOTIATE(content_type, supported, rs_array);
     252                 : }
     253                 : /* }}} */
     254                 : 
     255                 : /* {{{ proto bool http_send_status(int status)
     256                 :         Send HTTP status code. */
     257                 : PHP_FUNCTION(http_send_status)
     258               0 : {
     259               0 :         long status = 0;
     260                 : 
     261               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) {
     262               0 :                 RETURN_FALSE;
     263                 :         }
     264               0 :         if (status < 100 || status > 510) {
     265               0 :                 http_error_ex(HE_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status);
     266               0 :                 RETURN_FALSE;
     267                 :         }
     268                 : 
     269               0 :         RETURN_SUCCESS(http_send_status(status));
     270                 : }
     271                 : /* }}} */
     272                 : 
     273                 : /* {{{ proto bool http_send_last_modified([int timestamp])
     274                 :         Send a "Last-Modified" header with a valid HTTP date. */
     275                 : PHP_FUNCTION(http_send_last_modified)
     276               0 : {
     277               0 :         long t = -1;
     278                 : 
     279               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
     280               0 :                 RETURN_FALSE;
     281                 :         }
     282                 : 
     283               0 :         if (t == -1) {
     284               0 :                 t = HTTP_G->request.time;
     285                 :         }
     286                 : 
     287               0 :         RETURN_SUCCESS(http_send_last_modified(t));
     288                 : }
     289                 : /* }}} */
     290                 : 
     291                 : /* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream'])
     292                 :         Send the Content-Type of the sent entity.  This is particularly important if you use the http_send() API. */
     293                 : PHP_FUNCTION(http_send_content_type)
     294               0 : {
     295               0 :         char *ct = "application/x-octetstream";
     296               0 :         int ct_len = lenof("application/x-octetstream");
     297                 : 
     298               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) {
     299               0 :                 RETURN_FALSE;
     300                 :         }
     301                 : 
     302               0 :         RETURN_SUCCESS(http_send_content_type(ct, ct_len));
     303                 : }
     304                 : /* }}} */
     305                 : 
     306                 : /* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false])
     307                 :         Send the Content-Disposition. */
     308                 : PHP_FUNCTION(http_send_content_disposition)
     309               0 : {
     310                 :         char *filename;
     311                 :         int f_len;
     312               0 :         zend_bool send_inline = 0;
     313                 : 
     314               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) {
     315               0 :                 RETURN_FALSE;
     316                 :         }
     317               0 :         RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline));
     318                 : }
     319                 : /* }}} */
     320                 : 
     321                 : /* {{{ proto bool http_match_modified([int timestamp[, bool for_range = false]])
     322                 :         Matches the given unix timestamp against the clients "If-Modified-Since" resp. "If-Unmodified-Since" HTTP headers. */
     323                 : PHP_FUNCTION(http_match_modified)
     324               0 : {
     325               0 :         long t = -1;
     326               0 :         zend_bool for_range = 0;
     327                 : 
     328               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &t, &for_range) != SUCCESS) {
     329               0 :                 RETURN_FALSE;
     330                 :         }
     331                 : 
     332                 :         // current time if not supplied (senseless though)
     333               0 :         if (t == -1) {
     334               0 :                 t = HTTP_G->request.time;
     335                 :         }
     336                 : 
     337               0 :         if (for_range) {
     338               0 :                 RETURN_BOOL(http_match_last_modified("HTTP_IF_UNMODIFIED_SINCE", t));
     339                 :         }
     340               0 :         RETURN_BOOL(http_match_last_modified("HTTP_IF_MODIFIED_SINCE", t));
     341                 : }
     342                 : /* }}} */
     343                 : 
     344                 : /* {{{ proto bool http_match_etag(string etag[, bool for_range = false])
     345                 :         Matches the given ETag against the clients "If-Match" resp. "If-None-Match" HTTP headers. */
     346                 : PHP_FUNCTION(http_match_etag)
     347               0 : {
     348                 :         int etag_len;
     349                 :         char *etag;
     350               0 :         zend_bool for_range = 0;
     351                 : 
     352               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &etag, &etag_len, &for_range) != SUCCESS) {
     353               0 :                 RETURN_FALSE;
     354                 :         }
     355                 : 
     356               0 :         if (for_range) {
     357               0 :                 RETURN_BOOL(http_match_etag("HTTP_IF_MATCH", etag));
     358                 :         }
     359               0 :         RETURN_BOOL(http_match_etag("HTTP_IF_NONE_MATCH", etag));
     360                 : }
     361                 : /* }}} */
     362                 : 
     363                 : /* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]])
     364                 :         Attempts to cache the sent entity by its last modification date. */
     365                 : PHP_FUNCTION(http_cache_last_modified)
     366               0 : {
     367               0 :         long last_modified = 0, send_modified = 0, t;
     368                 :         zval *zlm;
     369                 : 
     370               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
     371               0 :                 RETURN_FALSE;
     372                 :         }
     373                 :         
     374               0 :         HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
     375                 : 
     376               0 :         t = HTTP_G->request.time;
     377                 : 
     378                 :         /* 0 or omitted */
     379               0 :         if (!last_modified) {
     380                 :                 /* does the client have? (att: caching "forever") */
     381               0 :                 if ((zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE", 1))) {
     382               0 :                         last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm));
     383                 :                 /* send current time */
     384                 :                 } else {
     385               0 :                         send_modified = t;
     386                 :                 }
     387                 :         /* negative value is supposed to be expiration time */
     388               0 :         } else if (last_modified < 0) {
     389               0 :                 last_modified += t;
     390               0 :                 send_modified  = t;
     391                 :         /* send supplied time explicitly */
     392                 :         } else {
     393               0 :                 send_modified = last_modified;
     394                 :         }
     395                 : 
     396               0 :         RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
     397                 : }
     398                 : /* }}} */
     399                 : 
     400                 : /* {{{ proto bool http_cache_etag([string etag])
     401                 :         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". */
     402                 : PHP_FUNCTION(http_cache_etag)
     403               0 : {
     404               0 :         char *etag = NULL;
     405               0 :         int etag_len = 0;
     406                 : 
     407               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
     408               0 :                 RETURN_FALSE;
     409                 :         }
     410                 :         
     411               0 :         HTTP_CHECK_HEADERS_SENT(RETURN_FALSE);
     412                 : 
     413               0 :         RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)));
     414                 : }
     415                 : /* }}} */
     416                 : 
     417                 : /* {{{ proto string ob_etaghandler(string data, int mode)
     418                 :         For use with ob_start().  Output buffer handler generating an ETag with the hash algorithm specified with the INI setting "http.etag.mode". */
     419                 : PHP_FUNCTION(ob_etaghandler)
     420               0 : {
     421                 :         char *data;
     422                 :         int data_len;
     423                 :         long mode;
     424                 : 
     425               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
     426               0 :                 RETURN_FALSE;
     427                 :         }
     428                 : 
     429               0 :         Z_TYPE_P(return_value) = IS_STRING;
     430               0 :         http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
     431                 : }
     432                 : /* }}} */
     433                 : 
     434                 : /* {{{ proto void http_throttle(double sec[, int bytes = 40960])
     435                 :         Sets the throttle delay and send buffer size for use with http_send() API. */
     436                 : PHP_FUNCTION(http_throttle)
     437               0 : {
     438               0 :         long chunk_size = HTTP_SENDBUF_SIZE;
     439                 :         double interval;
     440                 : 
     441               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &interval, &chunk_size)) {
     442               0 :                 return;
     443                 :         }
     444                 : 
     445               0 :         HTTP_G->send.throttle_delay = interval;
     446               0 :         HTTP_G->send.buffer_size = chunk_size;
     447                 : }
     448                 : /* }}} */
     449                 : 
     450                 : /* {{{ proto void http_redirect([string url[, array params[, bool session = false[, int status = 302]]]])
     451                 :         Redirect to the given url. */
     452                 : PHP_FUNCTION(http_redirect)
     453               0 : {
     454               0 :         int url_len = 0;
     455               0 :         size_t query_len = 0;
     456               0 :         zend_bool session = 0, free_params = 0;
     457               0 :         zval *params = NULL;
     458               0 :         long status = HTTP_REDIRECT;
     459               0 :         char *query = NULL, *url = NULL, *URI, *LOC, *RED = NULL;
     460                 : 
     461               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bl", &url, &url_len, &params, &session, &status) != SUCCESS) {
     462               0 :                 RETURN_FALSE;
     463                 :         }
     464                 : 
     465                 : #ifdef HTTP_HAVE_SESSION
     466                 :         /* append session info */
     467               0 :         if (session) {
     468               0 :                 if (!params) {
     469               0 :                         free_params = 1;
     470               0 :                         MAKE_STD_ZVAL(params);
     471               0 :                         array_init(params);
     472                 :                 }
     473               0 :                 if (PS(session_status) == php_session_active) {
     474               0 :                         if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
     475               0 :                                 http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not append session information");
     476                 :                         }
     477                 :                 }
     478                 :         }
     479                 : #endif
     480                 : 
     481                 :         /* treat params array with http_build_query() */
     482               0 :         if (params) {
     483               0 :                 if (SUCCESS != http_urlencode_hash_ex(Z_ARRVAL_P(params), 0, NULL, 0, &query, &query_len)) {
     484               0 :                         if (free_params) {
     485               0 :                                 zval_dtor(params);
     486               0 :                                 FREE_ZVAL(params);
     487                 :                         }
     488               0 :                         if (query) {
     489               0 :                                 efree(query);
     490                 :                         }
     491               0 :                         RETURN_FALSE;
     492                 :                 }
     493                 :         }
     494                 : 
     495               0 :         URI = http_absolute_url_ex(url, HTTP_URL_FROM_ENV);
     496                 : 
     497               0 :         if (query_len) {
     498               0 :                 spprintf(&LOC, 0, "Location: %s?%s", URI, query);
     499               0 :                 if (status != 300) {
     500               0 :                         spprintf(&RED, 0, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, query, URI, query);
     501                 :                 }
     502                 :         } else {
     503               0 :                 spprintf(&LOC, 0, "Location: %s", URI);
     504               0 :                 if (status != 300) {
     505               0 :                         spprintf(&RED, 0, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
     506                 :                 }
     507                 :         }
     508                 :         
     509               0 :         efree(URI);
     510               0 :         if (query) {
     511               0 :                 efree(query);
     512                 :         }
     513               0 :         if (free_params) {
     514               0 :                 zval_dtor(params);
     515               0 :                 FREE_ZVAL(params);
     516                 :         }
     517                 :         
     518               0 :         switch (status) {
     519                 :                 case 300:
     520               0 :                         RETVAL_SUCCESS(http_send_status_header(status, LOC));
     521               0 :                         efree(LOC);
     522               0 :                         return;
     523                 :                 
     524                 :                 case HTTP_REDIRECT_PERM:
     525                 :                 case HTTP_REDIRECT_FOUND:
     526                 :                 case HTTP_REDIRECT_POST:
     527                 :                 case HTTP_REDIRECT_PROXY:
     528                 :                 case HTTP_REDIRECT_TEMP:
     529               0 :                         break;
     530                 :                 
     531                 :                 case 306:
     532                 :                 default:
     533               0 :                         http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Unsupported redirection status code: %ld", status);
     534                 :                 case HTTP_REDIRECT:
     535               0 :                         if (    SG(request_info).request_method && 
     536                 :                                         strcasecmp(SG(request_info).request_method, "HEAD") &&
     537                 :                                         strcasecmp(SG(request_info).request_method, "GET")) {
     538               0 :                                 status = HTTP_REDIRECT_POST;
     539                 :                         } else {
     540               0 :                                 status = HTTP_REDIRECT_FOUND;
     541                 :                         }
     542                 :                         break;
     543                 :         }
     544                 :         
     545               0 :         RETURN_SUCCESS(http_exit_ex(status, LOC, RED, 1));
     546                 : }
     547                 : /* }}} */
     548                 : 
     549                 : /* {{{ proto bool http_send_data(string data)
     550                 :         Sends raw data with support for (multiple) range requests. */
     551                 : PHP_FUNCTION(http_send_data)
     552               0 : {
     553                 :         int data_len;
     554                 :         char *data_buf;
     555                 : 
     556               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data_buf, &data_len) != SUCCESS) {
     557               0 :                 RETURN_FALSE;
     558                 :         }
     559                 : 
     560               0 :         RETURN_SUCCESS(http_send_data(data_buf, data_len));
     561                 : }
     562                 : /* }}} */
     563                 : 
     564                 : /* {{{ proto bool http_send_file(string file)
     565                 :         Sends a file with support for (multiple) range requests. */
     566                 : PHP_FUNCTION(http_send_file)
     567               0 : {
     568                 :         char *file;
     569               0 :         int flen = 0;
     570                 : 
     571               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &flen) != SUCCESS) {
     572               0 :                 RETURN_FALSE;
     573                 :         }
     574               0 :         if (!flen) {
     575               0 :                 RETURN_FALSE;
     576                 :         }
     577                 : 
     578               0 :         RETURN_SUCCESS(http_send_file(file));
     579                 : }
     580                 : /* }}} */
     581                 : 
     582                 : /* {{{ proto bool http_send_stream(resource stream)
     583                 :         Sends an already opened stream with support for (multiple) range requests. */
     584                 : PHP_FUNCTION(http_send_stream)
     585               0 : {
     586                 :         zval *zstream;
     587                 :         php_stream *file;
     588                 : 
     589               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) {
     590               0 :                 RETURN_FALSE;
     591                 :         }
     592                 : 
     593               0 :         php_stream_from_zval(file, &zstream);
     594               0 :         RETURN_SUCCESS(http_send_stream(file));
     595                 : }
     596                 : /* }}} */
     597                 : 
     598                 : /* {{{ proto string http_chunked_decode(string encoded)
     599                 :         Decodes a string that was HTTP-chunked encoded. */
     600                 : PHP_FUNCTION(http_chunked_decode)
     601               4 : {
     602               4 :         char *encoded = NULL, *decoded = NULL;
     603               4 :         size_t decoded_len = 0;
     604               4 :         int encoded_len = 0;
     605                 : 
     606               4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) {
     607               0 :                 RETURN_FALSE;
     608                 :         }
     609                 : 
     610               4 :         if (NULL != http_encoding_dechunk(encoded, encoded_len, &decoded, &decoded_len)) {
     611               4 :                 RETURN_STRINGL(decoded, (int) decoded_len, 0);
     612                 :         } else {
     613               0 :                 RETURN_FALSE;
     614                 :         }
     615                 : }
     616                 : /* }}} */
     617                 : 
     618                 : /* {{{ proto object http_parse_message(string message)
     619                 :         Parses (a) http_message(s) into a simple recursive object structure. */
     620                 : PHP_FUNCTION(http_parse_message)
     621               8 : {
     622                 :         char *message;
     623                 :         int message_len;
     624               8 :         http_message *msg = NULL;
     625                 :         
     626               8 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &message, &message_len)) {
     627               0 :                 RETURN_NULL();
     628                 :         }
     629                 :         
     630               8 :         if ((msg = http_message_parse(message, message_len))) {
     631               8 :                 object_init(return_value);
     632               8 :                 http_message_tostruct_recursive(msg, return_value);
     633               8 :                 http_message_free(&msg);
     634                 :         } else {
     635               0 :                 RETURN_NULL();
     636                 :         }
     637                 : }
     638                 : /* }}} */
     639                 : 
     640                 : /* {{{ proto array http_parse_headers(string header)
     641                 :         Parses HTTP headers into an associative array. */
     642                 : PHP_FUNCTION(http_parse_headers)
     643               1 : {
     644                 :         char *header;
     645                 :         int header_len;
     646                 : 
     647               1 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) {
     648               0 :                 RETURN_FALSE;
     649                 :         }
     650                 : 
     651               1 :         array_init(return_value);
     652               1 :         if (SUCCESS != http_parse_headers(header, return_value)) {
     653               0 :                 zval_dtor(return_value);
     654               0 :                 http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse headers");
     655               0 :                 RETURN_FALSE;
     656                 :         }
     657                 : }
     658                 : /* }}}*/
     659                 : 
     660                 : /* {{{ proto object http_parse_cookie(string cookie[, int flags[, array allowed_extras]])
     661                 :         Parses HTTP cookies like sent in a response into a struct. */
     662                 : PHP_FUNCTION(http_parse_cookie)
     663              33 : {
     664              33 :         char *cookie, **allowed_extras = NULL;
     665              33 :         int i = 0, cookie_len;
     666              33 :         long flags = 0;
     667              33 :         zval *allowed_extras_array = NULL, **entry = NULL;
     668                 :         HashPosition pos;
     669                 :         http_cookie_list list;
     670                 :         
     671              33 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!", &cookie, &cookie_len, &flags, &allowed_extras_array)) {
     672               0 :                 RETURN_FALSE;
     673                 :         }
     674                 :         
     675              33 :         if (allowed_extras_array) {
     676               1 :                 allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *));
     677               2 :                 FOREACH_VAL(pos, allowed_extras_array, entry) {
     678               1 :                         ZVAL_ADDREF(*entry);
     679               1 :                         convert_to_string_ex(entry);
     680               1 :                         allowed_extras[i++] = estrndup(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry));
     681               1 :                         zval_ptr_dtor(entry);
     682                 :                 }
     683                 :         }
     684                 :         
     685              33 :         if (http_parse_cookie_ex(&list, cookie, flags, allowed_extras)) {
     686              33 :                 object_init(return_value);
     687              33 :                 http_cookie_list_tostruct(&list, return_value);
     688              33 :                 http_cookie_list_dtor(&list);
     689                 :         } else {
     690               0 :                 RETVAL_FALSE;
     691                 :         }
     692                 :         
     693              33 :         if (allowed_extras) {
     694               2 :                 for (i = 0; allowed_extras[i]; ++i) {
     695               1 :                         efree(allowed_extras[i]);
     696                 :                 }
     697               1 :                 efree(allowed_extras);
     698                 :         }
     699                 : }
     700                 : /* }}} */
     701                 : 
     702                 : /* {{{ proto string http_build_cookie(array cookie)
     703                 :         Build a cookie string from an array/object like returned by http_parse_cookie(). */
     704                 : PHP_FUNCTION(http_build_cookie)
     705               0 : {
     706               0 :         char *str = NULL;
     707               0 :         size_t len = 0;
     708                 :         zval *strct;
     709                 :         http_cookie_list list;
     710                 :         
     711               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &strct)) {
     712               0 :                 RETURN_FALSE;
     713                 :         }
     714                 :         
     715               0 :         http_cookie_list_fromstruct(&list, strct);
     716               0 :         http_cookie_list_tostring(&list, &str, &len);
     717               0 :         http_cookie_list_dtor(&list);
     718                 :         
     719               0 :         RETURN_STRINGL(str, len, 0);
     720                 : }
     721                 : /* }}} */
     722                 : 
     723                 : /* {{{ proto object http_parse_params(string param[, int flags = HTTP_PARAMS_DEFAULT])
     724                 :  Parse parameter list. */
     725                 : PHP_FUNCTION(http_parse_params)
     726               6 : {
     727                 :         char *param;
     728                 :         int param_len;
     729                 :         zval *params;
     730               6 :         long flags = HTTP_PARAMS_DEFAULT;
     731                 :         
     732               6 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &param, &param_len, &flags)) {
     733               0 :                 RETURN_FALSE;
     734                 :         }
     735                 :         
     736               6 :         MAKE_STD_ZVAL(params);
     737               6 :         array_init(params);
     738               6 :         if (SUCCESS != http_parse_params(param, flags, Z_ARRVAL_P(params))) {
     739               0 :                 zval_ptr_dtor(&params);
     740               0 :                 RETURN_FALSE;
     741                 :         }
     742                 :         
     743               6 :         object_init(return_value);
     744               6 :         add_property_zval(return_value, "params", params);
     745                 : #ifdef ZEND_ENGINE_2
     746               6 :         zval_ptr_dtor(&params);
     747                 : #endif
     748                 : }
     749                 : /* }}} */
     750                 : 
     751                 : /* {{{ proto array http_get_request_headers(void)
     752                 :         Get a list of incoming HTTP headers. */
     753                 : PHP_FUNCTION(http_get_request_headers)
     754               1 : {
     755               1 :         NO_ARGS;
     756                 : 
     757               1 :         array_init(return_value);
     758               1 :         http_get_request_headers(Z_ARRVAL_P(return_value));
     759               1 : }
     760                 : /* }}} */
     761                 : 
     762                 : /* {{{ proto string http_get_request_body(void)
     763                 :         Get the raw request body (e.g. POST or PUT data). */
     764                 : PHP_FUNCTION(http_get_request_body)
     765               3 : {
     766                 :         char *body;
     767                 :         size_t length;
     768                 : 
     769               3 :         NO_ARGS;
     770                 : 
     771               3 :         if (SUCCESS == http_get_request_body(&body, &length)) {
     772               3 :                 RETURN_STRINGL(body, (int) length, 0);
     773                 :         } else {
     774               0 :                 RETURN_NULL();
     775                 :         }
     776                 : }
     777                 : /* }}} */
     778                 : 
     779                 : /* {{{ proto resource http_get_request_body_stream(void)
     780                 :         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. */
     781                 : PHP_FUNCTION(http_get_request_body_stream)
     782               1 : {
     783                 :         php_stream *s;
     784                 :         
     785               1 :         NO_ARGS;
     786                 :         
     787               1 :         if ((s = http_get_request_body_stream())) {
     788               1 :                 php_stream_to_zval(s, return_value);
     789                 :         } else {
     790               0 :                 http_error(HE_WARNING, HTTP_E_RUNTIME, "Failed to create request body stream");
     791               0 :                 RETURN_NULL();
     792                 :         }
     793                 : }
     794                 : /* }}} */
     795                 : 
     796                 : /* {{{ proto bool http_match_request_header(string header, string value[, bool match_case = false])
     797                 :         Match an incoming HTTP header. */
     798                 : PHP_FUNCTION(http_match_request_header)
     799               3 : {
     800                 :         char *header, *value;
     801                 :         int header_len, value_len;
     802               3 :         zend_bool match_case = 0;
     803                 : 
     804               3 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &header, &header_len, &value, &value_len, &match_case)) {
     805               0 :                 RETURN_FALSE;
     806                 :         }
     807                 : 
     808               3 :         RETURN_BOOL(http_match_request_header_ex(header, value, match_case));
     809                 : }
     810                 : /* }}} */
     811                 : 
     812                 : /* {{{ proto object http_persistent_handles_count() */
     813                 : PHP_FUNCTION(http_persistent_handles_count)
     814               3 : {
     815               3 :         NO_ARGS;
     816               3 :         object_init(return_value);
     817               3 :         if (!http_persistent_handle_statall_ex(HASH_OF(return_value))) {
     818               0 :                 zval_dtor(return_value);
     819               0 :                 RETURN_NULL();
     820                 :         }
     821                 : }
     822                 : /* }}} */
     823                 : 
     824                 : /* {{{ proto void http_persistent_handles_clean([string name]) */
     825                 : PHP_FUNCTION(http_persistent_handles_clean)
     826               1 : {
     827               1 :         char *name_str = NULL;
     828               1 :         int name_len = 0;
     829                 :         
     830               1 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) {
     831               1 :                 http_persistent_handle_cleanup_ex(name_str, name_len, 1);
     832                 :         }
     833               1 : }
     834                 : /* }}} */
     835                 : 
     836                 : /* {{{ proto string http_persistent_handles_ident([string ident]) */
     837                 : PHP_FUNCTION(http_persistent_handles_ident)
     838               0 : {
     839               0 :         char *ident_str = NULL;
     840               0 :         int ident_len = 0;
     841                 :         
     842               0 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ident_str, &ident_len)) {
     843               0 :                 RETVAL_STRING(zend_ini_string(ZEND_STRS("http.persistent.handles.ident"), 0), 1);
     844               0 :                 if (ident_str && ident_len) {
     845               0 :                         zend_alter_ini_entry(ZEND_STRS("http.persistent.handles.ident"), ident_str, ident_len, ZEND_INI_USER, PHP_INI_STAGE_RUNTIME);
     846                 :                 }
     847                 :         }
     848               0 : }
     849                 : /* }}} */
     850                 : 
     851                 : /* {{{ HAVE_CURL */
     852                 : #ifdef HTTP_HAVE_CURL
     853                 : 
     854                 : #define RETVAL_RESPONSE_OR_BODY(request) \
     855                 :         { \
     856                 :                 zval **bodyonly; \
     857                 :                  \
     858                 :                 /* check if only the body should be returned */ \
     859                 :                 if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void *) &bodyonly)) && i_zend_is_true(*bodyonly)) { \
     860                 :                         http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \
     861                 :                          \
     862                 :                         if (msg) { \
     863                 :                                 RETVAL_STRINGL(PHPSTR_VAL(&msg->body), PHPSTR_LEN(&msg->body), 1); \
     864                 :                                 http_message_free(&msg); \
     865                 :                         } \
     866                 :                 } else { \
     867                 :                         RETVAL_STRINGL(request.conv.response.data, request.conv.response.used, 1); \
     868                 :                 } \
     869                 :         }
     870                 : 
     871                 : /* {{{ proto string http_get(string url[, array options[, array &info]])
     872                 :         Performs an HTTP GET request on the supplied url. */
     873                 : PHP_FUNCTION(http_get)
     874               5 : {
     875               5 :         zval *options = NULL, *info = NULL;
     876                 :         char *URL;
     877                 :         int URL_len;
     878                 :         http_request request;
     879                 : 
     880               5 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
     881               0 :                 RETURN_FALSE;
     882                 :         }
     883                 : 
     884               5 :         if (info) {
     885               2 :                 zval_dtor(info);
     886               2 :                 array_init(info);
     887                 :         }
     888                 : 
     889               5 :         RETVAL_FALSE;
     890                 : 
     891               5 :         http_request_init_ex(&request, NULL, HTTP_GET, URL);
     892               5 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
     893               5 :                 http_request_exec(&request);
     894               5 :                 if (info) {
     895               2 :                         http_request_info(&request, Z_ARRVAL_P(info));
     896                 :                 }
     897               5 :                 RETVAL_RESPONSE_OR_BODY(request);
     898                 :         }
     899               5 :         http_request_dtor(&request);
     900                 : }
     901                 : /* }}} */
     902                 : 
     903                 : /* {{{ proto string http_head(string url[, array options[, array &info]])
     904                 :         Performs an HTTP HEAD request on the supplied url. */
     905                 : PHP_FUNCTION(http_head)
     906               0 : {
     907               0 :         zval *options = NULL, *info = NULL;
     908                 :         char *URL;
     909                 :         int URL_len;
     910                 :         http_request request;
     911                 : 
     912               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
     913               0 :                 RETURN_FALSE;
     914                 :         }
     915                 : 
     916               0 :         if (info) {
     917               0 :                 zval_dtor(info);
     918               0 :                 array_init(info);
     919                 :         }
     920                 : 
     921               0 :         RETVAL_FALSE;
     922                 : 
     923               0 :         http_request_init_ex(&request, NULL, HTTP_HEAD, URL);
     924               0 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
     925               0 :                 http_request_exec(&request);
     926               0 :                 if (info) {
     927               0 :                         http_request_info(&request, Z_ARRVAL_P(info));
     928                 :                 }
     929               0 :                 RETVAL_RESPONSE_OR_BODY(request);
     930                 :         }
     931               0 :         http_request_dtor(&request);
     932                 : }
     933                 : /* }}} */
     934                 : 
     935                 : /* {{{ proto string http_post_data(string url, string data[, array options[, array &info]])
     936                 :         Performs an HTTP POST request on the supplied url. */
     937                 : PHP_FUNCTION(http_post_data)
     938               0 : {
     939               0 :         zval *options = NULL, *info = NULL;
     940                 :         char *URL, *postdata;
     941                 :         int postdata_len, URL_len;
     942                 :         http_request_body body;
     943                 :         http_request request;
     944                 : 
     945               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
     946               0 :                 RETURN_FALSE;
     947                 :         }
     948                 : 
     949               0 :         if (info) {
     950               0 :                 zval_dtor(info);
     951               0 :                 array_init(info);
     952                 :         }
     953                 : 
     954               0 :         RETVAL_FALSE;
     955                 : 
     956               0 :         http_request_init_ex(&request, NULL, HTTP_POST, URL);
     957               0 :         request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, postdata, postdata_len, 0);
     958               0 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
     959               0 :                 http_request_exec(&request);
     960               0 :                 if (info) {
     961               0 :                         http_request_info(&request, Z_ARRVAL_P(info));
     962                 :                 }
     963               0 :                 RETVAL_RESPONSE_OR_BODY(request);
     964                 :         }
     965               0 :         http_request_dtor(&request);
     966                 : }
     967                 : /* }}} */
     968                 : 
     969                 : /* {{{ proto string http_post_fields(string url, array data[, array files[, array options[, array &info]]])
     970                 :         Performs an HTTP POST request on the supplied url. */
     971                 : PHP_FUNCTION(http_post_fields)
     972               0 : {
     973               0 :         zval *options = NULL, *info = NULL, *fields = NULL, *files = NULL;
     974                 :         char *URL;
     975                 :         int URL_len;
     976                 :         http_request_body body;
     977                 :         http_request request;
     978                 : 
     979               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa!|a!a/!z", &URL, &URL_len, &fields, &files, &options, &info) != SUCCESS) {
     980               0 :                 RETURN_FALSE;
     981                 :         }
     982                 : 
     983               0 :         if (!http_request_body_fill(&body, fields ? Z_ARRVAL_P(fields) : NULL, files ? Z_ARRVAL_P(files) : NULL)) {
     984               0 :                 RETURN_FALSE;
     985                 :         }
     986                 : 
     987               0 :         if (info) {
     988               0 :                 zval_dtor(info);
     989               0 :                 array_init(info);
     990                 :         }
     991                 : 
     992               0 :         RETVAL_FALSE;
     993                 : 
     994               0 :         http_request_init_ex(&request, NULL, HTTP_POST, URL);
     995               0 :         request.body = &body;
     996               0 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
     997               0 :                 http_request_exec(&request);
     998               0 :                 if (info) {
     999               0 :                         http_request_info(&request, Z_ARRVAL_P(info));
    1000                 :                 }
    1001               0 :                 RETVAL_RESPONSE_OR_BODY(request);
    1002                 :         }
    1003               0 :         http_request_dtor(&request);
    1004                 : }
    1005                 : /* }}} */
    1006                 : 
    1007                 : /* {{{ proto string http_put_file(string url, string file[, array options[, array &info]])
    1008                 :         Performs an HTTP PUT request on the supplied url. */
    1009                 : PHP_FUNCTION(http_put_file)
    1010               0 : {
    1011                 :         char *URL, *file;
    1012                 :         int URL_len, f_len;
    1013               0 :         zval *options = NULL, *info = NULL;
    1014                 :         php_stream *stream;
    1015                 :         php_stream_statbuf ssb;
    1016                 :         http_request_body body;
    1017                 :         http_request request;
    1018                 : 
    1019               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &file, &f_len, &options, &info)) {
    1020               0 :                 RETURN_FALSE;
    1021                 :         }
    1022                 : 
    1023               0 :         if (!(stream = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) {
    1024               0 :                 RETURN_FALSE;
    1025                 :         }
    1026               0 :         if (php_stream_stat(stream, &ssb)) {
    1027               0 :                 php_stream_close(stream);
    1028               0 :                 RETURN_FALSE;
    1029                 :         }
    1030                 : 
    1031               0 :         if (info) {
    1032               0 :                 zval_dtor(info);
    1033               0 :                 array_init(info);
    1034                 :         }
    1035                 : 
    1036               0 :         RETVAL_FALSE;
    1037                 : 
    1038               0 :         http_request_init_ex(&request, NULL, HTTP_PUT, URL);
    1039               0 :         request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
    1040               0 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
    1041               0 :                 http_request_exec(&request);
    1042               0 :                 if (info) {
    1043               0 :                         http_request_info(&request, Z_ARRVAL_P(info));
    1044                 :                 }
    1045               0 :                 RETVAL_RESPONSE_OR_BODY(request);
    1046                 :         }
    1047               0 :         http_request_dtor(&request);
    1048                 : }
    1049                 : /* }}} */
    1050                 : 
    1051                 : /* {{{ proto string http_put_stream(string url, resource stream[, array options[, array &info]])
    1052                 :         Performs an HTTP PUT request on the supplied url. */
    1053                 : PHP_FUNCTION(http_put_stream)
    1054               0 : {
    1055               0 :         zval *resource, *options = NULL, *info = NULL;
    1056                 :         char *URL;
    1057                 :         int URL_len;
    1058                 :         php_stream *stream;
    1059                 :         php_stream_statbuf ssb;
    1060                 :         http_request_body body;
    1061                 :         http_request request;
    1062                 : 
    1063               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) {
    1064               0 :                 RETURN_FALSE;
    1065                 :         }
    1066                 : 
    1067               0 :         php_stream_from_zval(stream, &resource);
    1068               0 :         if (php_stream_stat(stream, &ssb)) {
    1069               0 :                 RETURN_FALSE;
    1070                 :         }
    1071                 : 
    1072               0 :         if (info) {
    1073               0 :                 zval_dtor(info);
    1074               0 :                 array_init(info);
    1075                 :         }
    1076                 : 
    1077               0 :         RETVAL_FALSE;
    1078                 : 
    1079               0 :         http_request_init_ex(&request, NULL, HTTP_PUT, URL);
    1080               0 :         request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 0);
    1081               0 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
    1082               0 :                 http_request_exec(&request);
    1083               0 :                 if (info) {
    1084               0 :                         http_request_info(&request, Z_ARRVAL_P(info));
    1085                 :                 }
    1086               0 :                 RETVAL_RESPONSE_OR_BODY(request);
    1087                 :         }
    1088               0 :         http_request_dtor(&request);
    1089                 : }
    1090                 : /* }}} */
    1091                 : 
    1092                 : /* {{{ proto string http_put_data(string url, string data[, array options[, array &info]])
    1093                 :         Performs an HTTP PUT request on the supplied url. */
    1094                 : PHP_FUNCTION(http_put_data)
    1095               1 : {
    1096                 :         char *URL, *data;
    1097                 :         int URL_len, data_len;
    1098               1 :         zval *options = NULL, *info = NULL;
    1099                 :         http_request_body body;
    1100                 :         http_request request;
    1101                 :         
    1102               1 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &data, &data_len, &options, &info)) {
    1103               0 :                 RETURN_FALSE;
    1104                 :         }
    1105                 :         
    1106               1 :         if (info) {
    1107               0 :                 zval_dtor(info);
    1108               0 :                 array_init(info);
    1109                 :         }
    1110                 :         
    1111               1 :         RETVAL_FALSE;
    1112                 :         
    1113               1 :         http_request_init_ex(&request, NULL, HTTP_PUT, URL);
    1114               1 :         request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
    1115               1 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
    1116               1 :                 http_request_exec(&request);
    1117               1 :                 if (info) {
    1118               0 :                         http_request_info(&request, Z_ARRVAL_P(info));
    1119                 :                 }
    1120               1 :                 RETVAL_RESPONSE_OR_BODY(request);
    1121                 :         }
    1122               1 :         http_request_dtor(&request);
    1123                 : }
    1124                 : /* }}} */
    1125                 : 
    1126                 : /* {{{ proto string http_request(int method, string url[, string body[, array options[, array &info]]])
    1127                 :         Performs a custom HTTP request on the supplied url. */
    1128                 : PHP_FUNCTION(http_request)
    1129               0 : {
    1130                 :         long meth;
    1131               0 :         char *URL, *data = NULL;
    1132               0 :         int URL_len, data_len = 0;
    1133               0 :         zval *options = NULL, *info = NULL;
    1134                 :         http_request_body body;
    1135                 :         http_request request;
    1136                 :         
    1137               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|sa/!z", &meth, &URL, &URL_len, &data, &data_len, &options, &info)) {
    1138               0 :                 RETURN_FALSE;
    1139                 :         }
    1140                 :         
    1141               0 :         if (info) {
    1142               0 :                 zval_dtor(info);
    1143               0 :                 array_init(info);
    1144                 :         }
    1145                 :         
    1146               0 :         RETVAL_FALSE;
    1147                 :         
    1148               0 :         http_request_init_ex(&request, NULL, meth, URL);
    1149               0 :         request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
    1150               0 :         if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
    1151               0 :                 http_request_exec(&request);
    1152               0 :                 if (info) {
    1153               0 :                         http_request_info(&request, Z_ARRVAL_P(info));
    1154                 :                 }
    1155               0 :                 RETVAL_RESPONSE_OR_BODY(request);
    1156                 :         }
    1157               0 :         http_request_dtor(&request);
    1158                 : }
    1159                 : /* }}} */
    1160                 : 
    1161                 : /* {{{ proto string http_request_body_encode(array fields, array files)
    1162                 :         Generate x-www-form-urlencoded resp. form-data encoded request body. */
    1163                 : PHP_FUNCTION(http_request_body_encode)
    1164               0 : {
    1165               0 :         zval *fields = NULL, *files = NULL;
    1166                 :         HashTable *fields_ht, *files_ht;
    1167                 :         http_request_body body;
    1168                 :         char *buf;
    1169                 :         size_t len;
    1170                 :         
    1171               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!", &fields, &files)) {
    1172               0 :                 RETURN_FALSE;
    1173                 :         }
    1174                 :         
    1175               0 :         fields_ht = (fields && Z_TYPE_P(fields) == IS_ARRAY) ? Z_ARRVAL_P(fields) : NULL;
    1176               0 :         files_ht = (files && Z_TYPE_P(files) == IS_ARRAY) ? Z_ARRVAL_P(files) : NULL;
    1177               0 :         if (http_request_body_fill(&body, fields_ht, files_ht) && (SUCCESS == http_request_body_encode(&body, &buf, &len))) {
    1178               0 :                 RETVAL_STRINGL(buf, len, 0);
    1179                 :         } else {
    1180               0 :                 http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not encode request body");
    1181               0 :                 RETVAL_FALSE;
    1182                 :         }
    1183               0 :         http_request_body_dtor(&body);
    1184                 : }
    1185                 : #endif /* HTTP_HAVE_CURL */
    1186                 : /* }}} HAVE_CURL */
    1187                 : 
    1188                 : /* {{{ proto int http_request_method_register(string method)
    1189                 :         Register a custom request method. */
    1190                 : PHP_FUNCTION(http_request_method_register)
    1191               6 : {
    1192                 :         char *method;
    1193                 :         int method_len;
    1194                 :         ulong existing;
    1195                 : 
    1196               6 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
    1197               0 :                 RETURN_FALSE;
    1198                 :         }
    1199               6 :         if ((existing = http_request_method_exists(1, 0, method))) {
    1200               0 :                 RETURN_LONG((long) existing);