LTP GCOV extension - code coverage report
Current view: directory - ext/http - http_functions.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 543
Code covered: 49.5 % Executed lines: 269
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.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, &params, &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", &param, &param_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                 : 

Generated by: LTP GCOV extension version 1.5