LCOV - code coverage report
Current view: top level - http - php_http_env.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 366 403 90.8 %
Date: 2014-11-03 12:21:11 Functions: 36 38 94.7 %
Legend: Lines: hit not hit

          Line data    Source code
       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-2014, Michael Wallner <mike@php.net>            |
      10             :     +--------------------------------------------------------------------+
      11             : */
      12             : 
      13             : #include "php_http_api.h"
      14             : #include "php_variables.h"
      15             : 
      16         408 : PHP_RINIT_FUNCTION(http_env)
      17             : {
      18             :         /* populate form data on non-POST requests */
      19         408 :         if (SG(request_info).request_method && strcasecmp(SG(request_info).request_method, "POST") && SG(request_info).content_type && *SG(request_info).content_type) {
      20           5 :                 uint ct_len = strlen(SG(request_info).content_type);
      21           5 :                 char *ct_str = estrndup(SG(request_info).content_type, ct_len);
      22             :                 php_http_params_opts_t opts;
      23             :                 HashTable params;
      24             : 
      25           5 :                 php_http_params_opts_default_get(&opts);
      26           5 :                 opts.input.str = ct_str;
      27           5 :                 opts.input.len = ct_len;
      28             : 
      29           5 :                 SG(request_info).content_type_dup = ct_str;
      30             : 
      31           5 :                 ZEND_INIT_SYMTABLE(&params);
      32           5 :                 if (php_http_params_parse(&params, &opts TSRMLS_CC)) {
      33             :                         char *key_str;
      34             :                         uint key_len;
      35             :                         ulong key_num;
      36             : 
      37           5 :                         if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(&params, &key_str, &key_len, &key_num, 0, NULL)) {
      38           5 :                                 sapi_post_entry *post_entry = NULL;
      39             : 
      40           5 :                                 if (SUCCESS == zend_hash_find(&SG(known_post_content_types), key_str, key_len, (void *) &post_entry)) {
      41           3 :                                         zval *files = PG(http_globals)[TRACK_VARS_FILES];
      42             : 
      43           3 :                                         if (post_entry) {
      44           3 :                                                 SG(request_info).post_entry = post_entry;
      45             : 
      46           3 :                                                 if (post_entry->post_reader) {
      47           2 :                                                         post_entry->post_reader(TSRMLS_C);
      48             :                                                 }
      49             :                                         }
      50             : 
      51           3 :                                         if (sapi_module.default_post_reader) {
      52           3 :                                                 sapi_module.default_post_reader(TSRMLS_C);
      53             :                                         }
      54             : 
      55           3 :                                         sapi_handle_post(PG(http_globals)[TRACK_VARS_POST] TSRMLS_CC);
      56             : 
      57             :                                         /*
      58             :                                          * the rfc1867 handler is an awkward buddy
      59             :                                          */
      60           3 :                                         if (files != PG(http_globals)[TRACK_VARS_FILES] && PG(http_globals)[TRACK_VARS_FILES]) {
      61           1 :                                                 Z_ADDREF_P(PG(http_globals)[TRACK_VARS_FILES]);
      62           1 :                                                 zend_hash_update(&EG(symbol_table), "_FILES", sizeof("_FILES"), &PG(http_globals)[TRACK_VARS_FILES], sizeof(zval *), NULL);
      63           1 :                                                 if (files) {
      64           1 :                                                         zval_ptr_dtor(&files);
      65             :                                                 }
      66             :                                         }
      67             :                                 }
      68             :                         }
      69           5 :                         zend_hash_destroy(&params);
      70             :                 }
      71             :         }
      72             : 
      73         408 :         STR_SET(SG(request_info).content_type_dup, NULL);
      74             : 
      75         408 :         return SUCCESS;
      76             : }
      77             : 
      78         408 : PHP_RSHUTDOWN_FUNCTION(http_env)
      79             : {
      80         408 :         if (PHP_HTTP_G->env.request.headers) {
      81          25 :                 zend_hash_destroy(PHP_HTTP_G->env.request.headers);
      82          25 :                 FREE_HASHTABLE(PHP_HTTP_G->env.request.headers);
      83          25 :                 PHP_HTTP_G->env.request.headers = NULL;
      84             :         }
      85         408 :         if (PHP_HTTP_G->env.request.body) {
      86          11 :                 php_http_message_body_free(&PHP_HTTP_G->env.request.body);
      87             :         }
      88             : 
      89         408 :         if (PHP_HTTP_G->env.server_var) {
      90           9 :                 zval_ptr_dtor(&PHP_HTTP_G->env.server_var);
      91           9 :                 PHP_HTTP_G->env.server_var = NULL;
      92             :         }
      93             : 
      94         408 :         return SUCCESS;
      95             : }
      96             : 
      97          83 : void php_http_env_get_request_headers(HashTable *headers TSRMLS_DC)
      98             : {
      99          83 :         php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
     100             :         zval **hsv, **header;
     101             :         HashPosition pos;
     102             : 
     103          83 :         if (!PHP_HTTP_G->env.request.headers) {
     104          25 :                 ALLOC_HASHTABLE(PHP_HTTP_G->env.request.headers);
     105          25 :                 zend_hash_init(PHP_HTTP_G->env.request.headers, 0, NULL, ZVAL_PTR_DTOR, 0);
     106             : 
     107          25 :                 zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
     108             : 
     109          25 :                 if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) {
     110        2481 :                         FOREACH_KEY(pos, *hsv, key) {
     111        2456 :                                 if (key.type == HASH_KEY_IS_STRING && key.len > 6 && *key.str == 'H' && !strncmp(key.str, "HTTP_", 5)) {
     112          18 :                                         key.len -= 5;
     113          18 :                                         key.str = php_http_pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1);
     114             : 
     115          18 :                                         zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
     116          18 :                                         Z_ADDREF_P(*header);
     117          18 :                                         zend_symtable_update(PHP_HTTP_G->env.request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
     118             : 
     119          18 :                                         efree(key.str);
     120        2438 :                                 } else if (key.type == HASH_KEY_IS_STRING && key.len > 9 && *key.str == 'C' && !strncmp(key.str, "CONTENT_", 8)) {
     121          12 :                                         key.str = php_http_pretty_key(estrndup(key.str, key.len - 1), key.len - 1, 1, 1);
     122             : 
     123          12 :                                         zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
     124          12 :                                         Z_ADDREF_P(*header);
     125          12 :                                         zend_symtable_update(PHP_HTTP_G->env.request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
     126             : 
     127          12 :                                         efree(key.str);
     128             :                                 }
     129             :                         }
     130             :                 }
     131             :         }
     132             : 
     133          83 :         if (headers) {
     134          11 :                 zend_hash_copy(headers, PHP_HTTP_G->env.request.headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     135             :         }
     136          83 : }
     137             : 
     138          78 : char *php_http_env_get_request_header(const char *name_str, size_t name_len, size_t *len, php_http_message_t *request TSRMLS_DC)
     139             : {
     140             :         HashTable *request_headers;
     141          78 :         zval **zvalue = NULL;
     142          78 :         char *val = NULL, *key = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
     143             : 
     144          78 :         if (request) {
     145          16 :                 request_headers = &request->hdrs;
     146             :         } else {
     147          62 :                 php_http_env_get_request_headers(NULL TSRMLS_CC);
     148          62 :                 request_headers = PHP_HTTP_G->env.request.headers;
     149             :         }
     150             : 
     151          78 :         if (SUCCESS == zend_symtable_find(request_headers, key, name_len + 1, (void *) &zvalue)) {
     152          27 :                 zval *zcopy = php_http_ztyp(IS_STRING, *zvalue);
     153             : 
     154          27 :                 val = estrndup(Z_STRVAL_P(zcopy), Z_STRLEN_P(zcopy));
     155          27 :                 if (len) {
     156          16 :                         *len = Z_STRLEN_P(zcopy);
     157             :                 }
     158          27 :                 zval_ptr_dtor(&zcopy);
     159             :         }
     160             : 
     161          78 :         efree(key);
     162             : 
     163          78 :         return val;
     164             : }
     165             : 
     166          13 : int php_http_env_got_request_header(const char *name_str, size_t name_len, php_http_message_t *request TSRMLS_DC)
     167             : {
     168             :         HashTable *request_headers;
     169          13 :         char *key = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
     170             :         int got;
     171             : 
     172          13 :         if (request) {
     173           3 :                 request_headers = &request->hdrs;
     174             :         } else {
     175          10 :                 php_http_env_get_request_headers(NULL TSRMLS_CC);
     176          10 :                 request_headers = PHP_HTTP_G->env.request.headers;
     177             :         }
     178          13 :         got = zend_symtable_exists(request_headers, key, name_len + 1);
     179          13 :         efree(key);
     180             : 
     181          13 :         return got;
     182             : }
     183             : 
     184          76 : zval *php_http_env_get_superglobal(const char *key, size_t key_len TSRMLS_DC)
     185             : {
     186             :         zval **hsv;
     187             : 
     188          76 :         zend_is_auto_global(key, key_len TSRMLS_CC);
     189             : 
     190          76 :         if ((SUCCESS != zend_hash_find(&EG(symbol_table), key, key_len + 1, (void *) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) {
     191           0 :                 return NULL;
     192             :         }
     193             : 
     194          76 :         return *hsv;
     195             : }
     196             : 
     197          82 : zval *php_http_env_get_server_var(const char *key, size_t key_len, zend_bool check TSRMLS_DC)
     198             : {
     199             :         zval *hsv, **var;
     200             :         char *env;
     201             : 
     202             :         /* if available, this is a lot faster than accessing $_SERVER */
     203          82 :         if (sapi_module.getenv) {
     204          36 :                 if ((!(env = sapi_module.getenv((char *) key, key_len TSRMLS_CC))) || (check && !*env)) {
     205          20 :                         return NULL;
     206             :                 }
     207          16 :                 if (PHP_HTTP_G->env.server_var) {
     208           7 :                         zval_ptr_dtor(&PHP_HTTP_G->env.server_var);
     209             :                 }
     210          16 :                 MAKE_STD_ZVAL(PHP_HTTP_G->env.server_var);
     211          16 :                 ZVAL_STRING(PHP_HTTP_G->env.server_var, env, 1);
     212          16 :                 return PHP_HTTP_G->env.server_var;
     213             :         }
     214             : 
     215          46 :         if (!(hsv = php_http_env_get_superglobal(ZEND_STRL("_SERVER") TSRMLS_CC))) {
     216           0 :                 return NULL;
     217             :         }
     218          46 :         if ((SUCCESS != zend_symtable_find(Z_ARRVAL_P(hsv), key, key_len + 1, (void *) &var))) {
     219          44 :                 return NULL;
     220             :         }
     221           2 :         if (check && !((Z_TYPE_PP(var) == IS_STRING) && Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
     222           0 :                 return NULL;
     223             :         }
     224           2 :         return *var;
     225             : }
     226             : 
     227          11 : php_http_message_body_t *php_http_env_get_request_body(TSRMLS_D)
     228             : {
     229          11 :         if (!PHP_HTTP_G->env.request.body) {
     230          11 :                 php_stream *s = php_stream_temp_new();
     231             : #if PHP_VERSION_ID >= 50600
     232          11 :                 php_stream *input = php_stream_open_wrapper("php://input", "r", 0, NULL);
     233             : 
     234             :                 /* php://input does not support stat */
     235          11 :                 php_stream_copy_to_stream_ex(input, s, -1, NULL);
     236          11 :                 php_stream_close(input);
     237             : #else
     238             :                 if (SG(request_info).post_data || SG(request_info).raw_post_data) {
     239             :                         /* php://input does not support seek() in PHP <= 5.5 */
     240             :                         if (SG(request_info).raw_post_data) {
     241             :                                 php_stream_write(s, SG(request_info).raw_post_data, SG(request_info).raw_post_data_length);
     242             :                         } else {
     243             :                                 php_stream_write(s, SG(request_info).post_data, SG(request_info).post_data_length);
     244             :                         }
     245             :                 } else if (sapi_module.read_post && !SG(read_post_bytes)) {
     246             :                         char *buf = emalloc(4096);
     247             :                         int len;
     248             : 
     249             :                         while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
     250             :                                 SG(read_post_bytes) += len;
     251             :                                 php_stream_write(s, buf, len);
     252             : 
     253             :                                 if (len < 4096) {
     254             :                                         break;
     255             :                                 }
     256             :                         }
     257             :                         efree(buf);
     258             :                 }
     259             : #endif
     260          11 :                 php_stream_rewind(s);
     261          11 :                 PHP_HTTP_G->env.request.body = php_http_message_body_init(NULL, s TSRMLS_CC);
     262             :         }
     263             : 
     264          11 :         return PHP_HTTP_G->env.request.body;
     265             : }
     266             : 
     267          12 : const char *php_http_env_get_request_method(php_http_message_t *request TSRMLS_DC)
     268             : {
     269             :         const char *m;
     270             : 
     271          12 :         if (PHP_HTTP_MESSAGE_TYPE(REQUEST, request)) {
     272           2 :                 m = request->http.info.request.method;
     273             :         } else {
     274          10 :                 m = SG(request_info).request_method;
     275             :         }
     276             : 
     277          12 :         return m ? m : "GET";
     278             : }
     279             : 
     280          17 : php_http_range_status_t php_http_env_get_request_ranges(HashTable *ranges, size_t length, php_http_message_t *request TSRMLS_DC)
     281             : {
     282             :         zval *zentry;
     283             :         char *range, *rp, c;
     284          17 :         long begin = -1, end = -1, *ptr;
     285             : 
     286          17 :         if (!(range = php_http_env_get_request_header(ZEND_STRL("Range"), NULL, request TSRMLS_CC))) {
     287          12 :                 return PHP_HTTP_RANGE_NO;
     288             :         }
     289           5 :         if (strncmp(range, "bytes=", lenof("bytes="))) {
     290           0 :                 STR_FREE(range);
     291           0 :                 return PHP_HTTP_RANGE_NO;
     292             :         }
     293             : 
     294           5 :         rp  = range + lenof("bytes=");
     295           5 :         ptr = &begin;
     296             : 
     297             :         do {
     298          44 :                 switch (c = *(rp++)) {
     299             :                         case '0':
     300             :                                 /* allow 000... - shall we? */
     301           9 :                                 if (*ptr != -10) {
     302           6 :                                         *ptr *= 10;
     303             :                                 }
     304           9 :                                 break;
     305             : 
     306             :                         case '1': case '2': case '3':
     307             :                         case '4': case '5': case '6':
     308             :                         case '7': case '8': case '9':
     309             :                                 /*
     310             :                                  * If the value of the pointer is already set (non-negative)
     311             :                                  * then multiply its value by ten and add the current value,
     312             :                                  * else initialise the pointers value with the current value
     313             :                                  * --
     314             :                                  * This let us recognize empty fields when validating the
     315             :                                  * ranges, i.e. a "-10" for begin and "12345" for the end
     316             :                                  * was the following range request: "Range: bytes=0-12345";
     317             :                                  * While a "-1" for begin and "12345" for the end would
     318             :                                  * have been: "Range: bytes=-12345".
     319             :                                  */
     320          17 :                                 if (*ptr > 0) {
     321           4 :                                         *ptr *= 10;
     322           4 :                                         *ptr += c - '0';
     323             :                                 } else {
     324          13 :                                         *ptr = c - '0';
     325             :                                 }
     326          17 :                                 break;
     327             : 
     328             :                         case '-':
     329           9 :                                 ptr = &end;
     330           9 :                                 break;
     331             : 
     332             :                         case ' ':
     333           0 :                                 break;
     334             : 
     335             :                         case 0:
     336             :                         case ',':
     337             : 
     338           9 :                                 if (length) {
     339             :                                         /* validate ranges */
     340           9 :                                         switch (begin) {
     341             :                                                 /* "0-12345" */
     342             :                                                 case -10:
     343           2 :                                                         switch (end) {
     344             :                                                                 /* "0-" */
     345             :                                                                 case -1:
     346           0 :                                                                         STR_FREE(range);
     347           0 :                                                                         return PHP_HTTP_RANGE_NO;
     348             : 
     349             :                                                                 /* "0-0" */
     350             :                                                                 case -10:
     351           1 :                                                                         end = 0;
     352           1 :                                                                         break;
     353             : 
     354             :                                                                 default:
     355           1 :                                                                         if (length <= (size_t) end) {
     356           0 :                                                                                 end = length - 1;
     357             :                                                                         }
     358           1 :                                                                         break;
     359             :                                                         }
     360           2 :                                                         begin = 0;
     361           2 :                                                         break;
     362             : 
     363             :                                                 /* "-12345" */
     364             :                                                 case -1:
     365             :                                                         /* "-", "-0" */
     366           1 :                                                         if (end == -1 || end == -10) {
     367           0 :                                                                 STR_FREE(range);
     368           0 :                                                                 return PHP_HTTP_RANGE_ERR;
     369             :                                                         }
     370           1 :                                                         begin = length - end;
     371           1 :                                                         end = length - 1;
     372           1 :                                                         break;
     373             : 
     374             :                                                 /* "12345-(NNN)" */
     375             :                                                 default:
     376           6 :                                                         if (length <= (size_t) begin) {
     377           1 :                                                                 STR_FREE(range);
     378           1 :                                                                 return PHP_HTTP_RANGE_ERR;
     379             :                                                         }
     380           5 :                                                         switch (end) {
     381             :                                                                 /* "12345-0" */
     382             :                                                                 case -10:
     383           0 :                                                                         STR_FREE(range);
     384           0 :                                                                         return PHP_HTTP_RANGE_ERR;
     385             : 
     386             :                                                                 /* "12345-" */
     387             :                                                                 case -1:
     388           1 :                                                                         end = length - 1;
     389           1 :                                                                         break;
     390             : 
     391             :                                                                 /* "12345-67890" */
     392             :                                                                 default:
     393           4 :                                                                         if (length <= (size_t) end) {
     394           0 :                                                                                 end = length - 1;
     395           4 :                                                                         } else if (end <  begin) {
     396           0 :                                                                                 STR_FREE(range);
     397           0 :                                                                                 return PHP_HTTP_RANGE_ERR;
     398             :                                                                         }
     399           4 :                                                                         break;
     400             :                                                         }
     401           5 :                                                         break;
     402             :                                         }
     403             :                                 }
     404             : 
     405           8 :                                 MAKE_STD_ZVAL(zentry);
     406           8 :                                 array_init(zentry);
     407           8 :                                 add_index_long(zentry, 0, begin);
     408           8 :                                 add_index_long(zentry, 1, end);
     409           8 :                                 zend_hash_next_index_insert(ranges, &zentry, sizeof(zval *), NULL);
     410             : 
     411           8 :                                 begin = -1;
     412           8 :                                 end = -1;
     413           8 :                                 ptr = &begin;
     414             : 
     415           8 :                                 break;
     416             : 
     417             :                         default:
     418           0 :                                 STR_FREE(range);
     419           0 :                                 return PHP_HTTP_RANGE_NO;
     420             :                 }
     421          43 :         } while (c != 0);
     422             : 
     423           4 :         STR_FREE(range);
     424           4 :         return PHP_HTTP_RANGE_OK;
     425             : }
     426             : 
     427          25 : static void grab_headers(void *data, void *arg TSRMLS_DC)
     428             : {
     429          25 :         php_http_buffer_appendl(PHP_HTTP_BUFFER(arg), ((sapi_header_struct *)data)->header);
     430          25 :         php_http_buffer_appends(PHP_HTTP_BUFFER(arg), PHP_HTTP_CRLF);
     431          25 : }
     432             : 
     433          22 : STATUS php_http_env_get_response_headers(HashTable *headers_ht TSRMLS_DC)
     434             : {
     435             :         STATUS status;
     436             :         php_http_buffer_t headers;
     437             : 
     438          22 :         php_http_buffer_init(&headers);
     439          22 :         zend_llist_apply_with_argument(&SG(sapi_headers).headers, grab_headers, &headers TSRMLS_CC);
     440          22 :         php_http_buffer_fix(&headers);
     441             : 
     442          22 :         status = php_http_header_parse(headers.data, headers.used, headers_ht, NULL, NULL TSRMLS_CC);
     443          22 :         php_http_buffer_dtor(&headers);
     444             : 
     445          22 :         return status;
     446             : }
     447             : 
     448           1 : char *php_http_env_get_response_header(const char *name_str, size_t name_len TSRMLS_DC)
     449             : {
     450           1 :         char *val = NULL;
     451             :         HashTable headers;
     452             : 
     453           1 :         zend_hash_init(&headers, 0, NULL, ZVAL_PTR_DTOR, 0);
     454           1 :         if (SUCCESS == php_http_env_get_response_headers(&headers TSRMLS_CC)) {
     455             :                 zval **zvalue;
     456           1 :                 char *key = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
     457             : 
     458           1 :                 if (SUCCESS == zend_symtable_find(&headers, key, name_len + 1, (void *) &zvalue)) {
     459           1 :                         zval *zcopy = php_http_ztyp(IS_STRING, *zvalue);
     460             : 
     461           1 :                         val = estrndup(Z_STRVAL_P(zcopy), Z_STRLEN_P(zcopy));
     462           1 :                         zval_ptr_dtor(&zcopy);
     463             :                 }
     464             : 
     465           1 :                 efree(key);
     466             :         }
     467           1 :         zend_hash_destroy(&headers);
     468             : 
     469           1 :         return val;
     470             : }
     471             : 
     472          17 : long php_http_env_get_response_code(TSRMLS_D)
     473             : {
     474          17 :         long code = SG(sapi_headers).http_response_code;
     475          17 :         return code ? code : 200;
     476             : }
     477             : 
     478          14 : STATUS php_http_env_set_response_code(long http_code TSRMLS_DC)
     479             : {
     480          14 :         return sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) http_code TSRMLS_CC);
     481             : }
     482             : 
     483           9 : STATUS php_http_env_set_response_status_line(long code, php_http_version_t *v TSRMLS_DC)
     484             : {
     485           9 :         sapi_header_line h = {NULL, 0, 0};
     486             :         STATUS ret;
     487             : 
     488           9 :         h.line_len = spprintf(&h.line, 0, "HTTP/%u.%u %ld %s", v->major, v->minor, code, php_http_env_get_response_status_for_code(code));
     489           9 :         ret = sapi_header_op(SAPI_HEADER_REPLACE, (void *) &h TSRMLS_CC);
     490           9 :         efree(h.line);
     491             : 
     492           9 :         return ret;
     493             : }
     494             : 
     495           9 : STATUS php_http_env_set_response_protocol_version(php_http_version_t *v TSRMLS_DC)
     496             : {
     497           9 :         return php_http_env_set_response_status_line(php_http_env_get_response_code(TSRMLS_C), v TSRMLS_CC);
     498             : }
     499             : 
     500           0 : STATUS php_http_env_set_response_header(long http_code, const char *header_str, size_t header_len, zend_bool replace TSRMLS_DC)
     501             : {
     502           0 :         sapi_header_line h = {estrndup(header_str, header_len), header_len, http_code};
     503           0 :         STATUS ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, (void *) &h TSRMLS_CC);
     504           0 :         efree(h.line);
     505           0 :         return ret;
     506             : }
     507             : 
     508          39 : STATUS php_http_env_set_response_header_va(long http_code, zend_bool replace, const char *fmt, va_list argv TSRMLS_DC)
     509             : {
     510          39 :         STATUS ret = FAILURE;
     511          39 :         sapi_header_line h = {NULL, 0, http_code};
     512             : 
     513          39 :         h.line_len = vspprintf(&h.line, 0, fmt, argv);
     514             : 
     515          39 :         if (h.line) {
     516          39 :                 if (h.line_len) {
     517          39 :                         ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, (void *) &h TSRMLS_CC);
     518             :                 }
     519          39 :                 efree(h.line);
     520             :         }
     521          39 :         return ret;
     522             : }
     523             : 
     524           0 : STATUS php_http_env_set_response_header_format(long http_code, zend_bool replace TSRMLS_DC, const char *fmt, ...)
     525             : {
     526             :         STATUS ret;
     527             :         va_list args;
     528             : 
     529           0 :         va_start(args, fmt);
     530           0 :         ret = php_http_env_set_response_header_va(http_code, replace, fmt, args TSRMLS_CC);
     531           0 :         va_end(args);
     532             : 
     533           0 :         return ret;
     534             : }
     535             : 
     536          12 : STATUS php_http_env_set_response_header_value(long http_code, const char *name_str, size_t name_len, zval *value, zend_bool replace TSRMLS_DC)
     537             : {
     538          12 :         if (!value) {
     539           6 :                 sapi_header_line h = {(char *) name_str, name_len, http_code};
     540             : 
     541           6 :                 return sapi_header_op(SAPI_HEADER_DELETE, (void *) &h TSRMLS_CC);
     542             :         }
     543             : 
     544           6 :         if(Z_TYPE_P(value) == IS_ARRAY || Z_TYPE_P(value) == IS_OBJECT) {
     545             :                 HashPosition pos;
     546           1 :                 int first = replace;
     547             :                 zval **data_ptr;
     548             : 
     549           4 :                 FOREACH_HASH_VAL(pos, HASH_OF(value), data_ptr) {
     550           3 :                         if (SUCCESS != php_http_env_set_response_header_value(http_code, name_str, name_len, *data_ptr, first TSRMLS_CC)) {
     551           0 :                                 return FAILURE;
     552             :                         }
     553           3 :                         first = 0;
     554             :                 }
     555             : 
     556           1 :                 return SUCCESS;
     557             :         } else {
     558           5 :                 zval *data = php_http_ztyp(IS_STRING, value);
     559             : 
     560           5 :                 if (!Z_STRLEN_P(data)) {
     561           0 :                         zval_ptr_dtor(&data);
     562           0 :                         return php_http_env_set_response_header_value(http_code, name_str, name_len, NULL, replace TSRMLS_CC);
     563             :                 } else {
     564             :                         sapi_header_line h;
     565             :                         STATUS ret;
     566             : 
     567           5 :                         if (name_len > INT_MAX) {
     568           0 :                                 name_len = INT_MAX;
     569             :                         }
     570           5 :                         h.response_code = http_code;
     571           5 :                         h.line_len = spprintf(&h.line, 0, "%.*s: %.*s", (int) name_len, name_str, Z_STRLEN_P(data), Z_STRVAL_P(data));
     572             : 
     573           5 :                         ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, (void *) &h TSRMLS_CC);
     574             : 
     575           5 :                         zval_ptr_dtor(&data);
     576           5 :                         STR_FREE(h.line);
     577             : 
     578           5 :                         return ret;
     579             :                 }
     580             :         }
     581             : }
     582             : 
     583             : static PHP_HTTP_STRLIST(php_http_env_response_status) =
     584             :         PHP_HTTP_STRLIST_ITEM("Continue")
     585             :         PHP_HTTP_STRLIST_ITEM("Switching Protocols")
     586             :         PHP_HTTP_STRLIST_ITEM("Processing")
     587             :         PHP_HTTP_STRLIST_NEXT
     588             :         PHP_HTTP_STRLIST_ITEM("OK")
     589             :         PHP_HTTP_STRLIST_ITEM("Created")
     590             :         PHP_HTTP_STRLIST_ITEM("Accepted")
     591             :         PHP_HTTP_STRLIST_ITEM("Non-Authoritative Information")
     592             :         PHP_HTTP_STRLIST_ITEM("No Content")
     593             :         PHP_HTTP_STRLIST_ITEM("Reset Content")
     594             :         PHP_HTTP_STRLIST_ITEM("Partial Content")
     595             :         PHP_HTTP_STRLIST_ITEM("Multi-Status")
     596             :         PHP_HTTP_STRLIST_ITEM("Already Reported")
     597             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     598             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     599             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     600             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     601             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     602             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     603             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     604             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     605             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     606             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     607             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     608             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     609             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     610             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     611             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     612             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     613             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     614             :         PHP_HTTP_STRLIST_ITEM("IM Used")
     615             :         PHP_HTTP_STRLIST_NEXT
     616             :         PHP_HTTP_STRLIST_ITEM("Multiple Choices")
     617             :         PHP_HTTP_STRLIST_ITEM("Moved Permanently")
     618             :         PHP_HTTP_STRLIST_ITEM("Found")
     619             :         PHP_HTTP_STRLIST_ITEM("See Other")
     620             :         PHP_HTTP_STRLIST_ITEM("Not Modified")
     621             :         PHP_HTTP_STRLIST_ITEM("Use Proxy")
     622             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     623             :         PHP_HTTP_STRLIST_ITEM("Temporary Redirect")
     624             :         PHP_HTTP_STRLIST_ITEM("Permanent Redirect")
     625             :         PHP_HTTP_STRLIST_NEXT
     626             :         PHP_HTTP_STRLIST_ITEM("Bad Request")
     627             :         PHP_HTTP_STRLIST_ITEM("Unauthorized")
     628             :         PHP_HTTP_STRLIST_ITEM("Payment Required")
     629             :         PHP_HTTP_STRLIST_ITEM("Forbidden")
     630             :         PHP_HTTP_STRLIST_ITEM("Not Found")
     631             :         PHP_HTTP_STRLIST_ITEM("Method Not Allowed")
     632             :         PHP_HTTP_STRLIST_ITEM("Not Acceptable")
     633             :         PHP_HTTP_STRLIST_ITEM("Proxy Authentication Required")
     634             :         PHP_HTTP_STRLIST_ITEM("Request Timeout")
     635             :         PHP_HTTP_STRLIST_ITEM("Conflict")
     636             :         PHP_HTTP_STRLIST_ITEM("Gone")
     637             :         PHP_HTTP_STRLIST_ITEM("Length Required")
     638             :         PHP_HTTP_STRLIST_ITEM("Precondition Failed")
     639             :         PHP_HTTP_STRLIST_ITEM("Request Entity Too Large")
     640             :         PHP_HTTP_STRLIST_ITEM("Request URI Too Long")
     641             :         PHP_HTTP_STRLIST_ITEM("Unsupported Media Type")
     642             :         PHP_HTTP_STRLIST_ITEM("Requested Range Not Satisfiable")
     643             :         PHP_HTTP_STRLIST_ITEM("Expectation Failed")
     644             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     645             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     646             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     647             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     648             :         PHP_HTTP_STRLIST_ITEM("Unprocessible Entity")
     649             :         PHP_HTTP_STRLIST_ITEM("Locked")
     650             :         PHP_HTTP_STRLIST_ITEM("Failed Dependency")
     651             :         PHP_HTTP_STRLIST_ITEM("(Reserved)")
     652             :         PHP_HTTP_STRLIST_ITEM("Upgrade Required")
     653             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     654             :         PHP_HTTP_STRLIST_ITEM("Precondition Required")
     655             :         PHP_HTTP_STRLIST_ITEM("Too Many Requests")
     656             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     657             :         PHP_HTTP_STRLIST_ITEM("Request Header Fields Too Large")
     658             :         PHP_HTTP_STRLIST_NEXT
     659             :         PHP_HTTP_STRLIST_ITEM("Internal Server Error")
     660             :         PHP_HTTP_STRLIST_ITEM("Not Implemented")
     661             :         PHP_HTTP_STRLIST_ITEM("Bad Gateway")
     662             :         PHP_HTTP_STRLIST_ITEM("Service Unavailable")
     663             :         PHP_HTTP_STRLIST_ITEM("Gateway Timeout")
     664             :         PHP_HTTP_STRLIST_ITEM("HTTP Version Not Supported")
     665             :         PHP_HTTP_STRLIST_ITEM("Variant Also Negotiates")
     666             :         PHP_HTTP_STRLIST_ITEM("Insufficient Storage")
     667             :         PHP_HTTP_STRLIST_ITEM("Loop Detected")
     668             :         PHP_HTTP_STRLIST_ITEM("(Unused)")
     669             :         PHP_HTTP_STRLIST_ITEM("Not Extended")
     670             :         PHP_HTTP_STRLIST_ITEM("Network Authentication Required")
     671             :         PHP_HTTP_STRLIST_STOP
     672             : ;
     673             : 
     674         641 : const char *php_http_env_get_response_status_for_code(unsigned code)
     675             : {
     676         641 :         return php_http_strlist_find(php_http_env_response_status, 100, code);
     677             : }
     678             : 
     679             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getRequestHeader, 0, 0, 0)
     680             :         ZEND_ARG_INFO(0, header_name)
     681             : ZEND_END_ARG_INFO();
     682           4 : static PHP_METHOD(HttpEnv, getRequestHeader)
     683             : {
     684           4 :         char *header_name_str = NULL;
     685           4 :         int header_name_len = 0;
     686             : 
     687           4 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &header_name_str, &header_name_len)) {
     688           2 :                 return;
     689             :         }
     690           5 :         if (header_name_str && header_name_len) {
     691             :                 size_t header_length;
     692           3 :                 char *header_value = php_http_env_get_request_header(header_name_str, header_name_len, &header_length, NULL TSRMLS_CC);
     693             : 
     694           3 :                 if (header_value) {
     695           2 :                         RETURN_STRINGL(header_value, header_length, 0);
     696             :                 }
     697             :         } else {
     698           1 :                 array_init(return_value);
     699           1 :                 php_http_env_get_request_headers(Z_ARRVAL_P(return_value) TSRMLS_CC);
     700             :         }
     701             : }
     702             : 
     703             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getRequestBody, 0, 0, 0)
     704             :         ZEND_ARG_INFO(0, body_class_name)
     705             : ZEND_END_ARG_INFO();
     706           1 : static PHP_METHOD(HttpEnv, getRequestBody)
     707             : {
     708             :         zend_object_value ov;
     709             :         php_http_message_body_t *body;
     710           1 :         zend_class_entry *class_entry = php_http_message_body_class_entry;
     711             : 
     712           2 :         php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &class_entry), invalid_arg, return);
     713             : 
     714           1 :         body = php_http_env_get_request_body(TSRMLS_C);
     715           1 :         if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_message_body_object_new_ex, php_http_message_body_class_entry, body, NULL TSRMLS_CC)) {
     716           1 :                 php_http_message_body_addref(body);
     717           1 :                 RETVAL_OBJVAL(ov, 0);
     718             :         }
     719             : }
     720             : 
     721             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseStatusForCode, 0, 0, 1)
     722             :         ZEND_ARG_INFO(0, code)
     723             : ZEND_END_ARG_INFO();
     724         602 : static PHP_METHOD(HttpEnv, getResponseStatusForCode)
     725             : {
     726             :         long code;
     727             : 
     728         602 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
     729           0 :                 return;
     730             :         }
     731         602 :         RETURN_STRING(php_http_env_get_response_status_for_code(code), 1);
     732             : }
     733             : 
     734             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseStatusForAllCodes, 0, 0, 0)
     735             : ZEND_END_ARG_INFO();
     736           1 : static PHP_METHOD(HttpEnv, getResponseStatusForAllCodes)
     737             : {
     738             :         const char *s;
     739             :         unsigned c;
     740             :         php_http_strlist_iterator_t i;
     741             : 
     742           1 :         if (SUCCESS != zend_parse_parameters_none()) {
     743           1 :                 return;
     744             :         }
     745             : 
     746           1 :         array_init(return_value);
     747         169 :         for (   php_http_strlist_iterator_init(&i, php_http_env_response_status, 100);
     748          84 :                         *(s = php_http_strlist_iterator_this(&i, &c));
     749          83 :                         php_http_strlist_iterator_next(&i)
     750             :         ) {
     751          83 :                 add_index_string(return_value, c, s, 1);
     752             :         }
     753             : }
     754             : 
     755             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseHeader, 0, 0, 0)
     756             :         ZEND_ARG_INFO(0, header_name)
     757             : ZEND_END_ARG_INFO();
     758           2 : static PHP_METHOD(HttpEnv, getResponseHeader)
     759             : {
     760           2 :         char *header_name_str = NULL;
     761           2 :         int header_name_len = 0;
     762             : 
     763           2 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &header_name_str, &header_name_len)) {
     764           1 :                 return;
     765             :         }
     766           2 :         if (header_name_str && header_name_len) {
     767           1 :                 char *header_value = php_http_env_get_response_header(header_name_str, header_name_len TSRMLS_CC);
     768             : 
     769           1 :                 if (header_value) {
     770           1 :                         RETURN_STRING(header_value, 0);
     771             :                 }
     772             :         } else {
     773           1 :                 array_init(return_value);
     774           1 :                 php_http_env_get_response_headers(Z_ARRVAL_P(return_value) TSRMLS_CC);
     775             :         }
     776             : }
     777             : 
     778             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_getResponseCode, 0, 0, 0)
     779             : ZEND_END_ARG_INFO();
     780           1 : static PHP_METHOD(HttpEnv, getResponseCode)
     781             : {
     782           1 :         if (SUCCESS != zend_parse_parameters_none()) {
     783           0 :                 return;
     784             :         }
     785           1 :         RETURN_LONG(php_http_env_get_response_code(TSRMLS_C));
     786             : }
     787             : 
     788             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_setResponseHeader, 0, 0, 1)
     789             :         ZEND_ARG_INFO(0, header_name)
     790             :         ZEND_ARG_INFO(0, header_value)
     791             :         ZEND_ARG_INFO(0, response_code)
     792             :         ZEND_ARG_INFO(0, replace_header)
     793             : ZEND_END_ARG_INFO();
     794           4 : static PHP_METHOD(HttpEnv, setResponseHeader)
     795             : {
     796             :         char *header_name_str;
     797             :         int header_name_len;
     798           4 :         zval *header_value = NULL;
     799           4 :         long code = 0;
     800           4 :         zend_bool replace_header = 1;
     801             : 
     802           4 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z!lb", &header_name_str, &header_name_len, &header_value, &code, &replace_header)) {
     803           0 :                 return;
     804             :         }
     805           4 :         RETURN_BOOL(SUCCESS == php_http_env_set_response_header_value(code, header_name_str, header_name_len, header_value, replace_header TSRMLS_CC));
     806             : }
     807             : 
     808             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_setResponseCode, 0, 0, 1)
     809             :         ZEND_ARG_INFO(0, code)
     810             : ZEND_END_ARG_INFO();
     811           1 : static PHP_METHOD(HttpEnv, setResponseCode)
     812             : {
     813             :         long code;
     814             : 
     815           1 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
     816           0 :                 return;
     817             :         }
     818           1 :         RETURN_BOOL(SUCCESS == php_http_env_set_response_code(code TSRMLS_CC));
     819             : }
     820             : 
     821             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateLanguage, 0, 0, 1)
     822             :         ZEND_ARG_INFO(0, supported)
     823             :         ZEND_ARG_INFO(1, result_array)
     824             : ZEND_END_ARG_INFO();
     825           3 : static PHP_METHOD(HttpEnv, negotiateLanguage)
     826             : {
     827             :         HashTable *supported;
     828           3 :         zval *rs_array = NULL;
     829             : 
     830           3 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
     831           3 :                 return;
     832             :         }
     833           3 :         if (rs_array) {
     834           3 :                 zval_dtor(rs_array);
     835           3 :                 array_init(rs_array);
     836             :         }
     837             : 
     838           3 :         PHP_HTTP_DO_NEGOTIATE(language, supported, rs_array);
     839             : }
     840             : 
     841             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateCharset, 0, 0, 1)
     842             :         ZEND_ARG_INFO(0, supported)
     843             :         ZEND_ARG_INFO(1, result_array)
     844             : ZEND_END_ARG_INFO();
     845           3 : static PHP_METHOD(HttpEnv, negotiateCharset)
     846             : {
     847             :         HashTable *supported;
     848           3 :         zval *rs_array = NULL;
     849             : 
     850           3 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
     851           3 :                 return;
     852             :         }
     853           3 :         if (rs_array) {
     854           3 :                 zval_dtor(rs_array);
     855           3 :                 array_init(rs_array);
     856             :         }
     857           3 :         PHP_HTTP_DO_NEGOTIATE(charset, supported, rs_array);
     858             : }
     859             : 
     860             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateEncoding, 0, 0, 1)
     861             :         ZEND_ARG_INFO(0, supported)
     862             :         ZEND_ARG_INFO(1, result_array)
     863             : ZEND_END_ARG_INFO();
     864           2 : static PHP_METHOD(HttpEnv, negotiateEncoding)
     865             : {
     866             :         HashTable *supported;
     867           2 :         zval *rs_array = NULL;
     868             : 
     869           2 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
     870           2 :                 return;
     871             :         }
     872           2 :         if (rs_array) {
     873           2 :                 zval_dtor(rs_array);
     874           2 :                 array_init(rs_array);
     875             :         }
     876           2 :         PHP_HTTP_DO_NEGOTIATE(encoding, supported, rs_array);
     877             : }
     878             : 
     879             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiateContentType, 0, 0, 1)
     880             :         ZEND_ARG_INFO(0, supported)
     881             :         ZEND_ARG_INFO(1, result_array)
     882             : ZEND_END_ARG_INFO();
     883           3 : static PHP_METHOD(HttpEnv, negotiateContentType)
     884             : {
     885             :         HashTable *supported;
     886           3 :         zval *rs_array = NULL;
     887             : 
     888           3 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
     889           3 :                 return;
     890             :         }
     891           3 :         if (rs_array) {
     892           3 :                 zval_dtor(rs_array);
     893           3 :                 array_init(rs_array);
     894             :         }
     895           3 :         PHP_HTTP_DO_NEGOTIATE(content_type, supported, rs_array);
     896             : }
     897             : 
     898             : ZEND_BEGIN_ARG_INFO_EX(ai_HttpEnv_negotiate, 0, 0, 2)
     899             :         ZEND_ARG_INFO(0, params)
     900             :         ZEND_ARG_INFO(0, supported)
     901             :         ZEND_ARG_INFO(0, primary_type_separator)
     902             :         ZEND_ARG_INFO(1, result_array)
     903             : ZEND_END_ARG_INFO();
     904           1 : static PHP_METHOD(HttpEnv, negotiate)
     905             : {
     906             :         HashTable *supported, *rs;
     907           1 :         zval *rs_array = NULL;
     908           1 :         char *value_str, *sep_str = NULL;
     909           1 :         int value_len, sep_len = 0;
     910             : 
     911           1 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sH|s!z", &value_str, &value_len, &supported, &sep_str, &sep_len, &rs_array)) {
     912           1 :                 return;
     913             :         }
     914             : 
     915             : 
     916           1 :         if (rs_array) {
     917           1 :                 zval_dtor(rs_array);
     918           1 :                 array_init(rs_array);
     919             :         }
     920             : 
     921           1 :         if ((rs = php_http_negotiate(value_str, value_len, supported, sep_str, sep_len TSRMLS_CC))) {
     922           1 :                 PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs, supported, rs_array);
     923             :         } else {
     924           0 :                 PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array);
     925             :         }
     926             : }
     927             : 
     928             : static zend_function_entry php_http_env_methods[] = {
     929             :         PHP_ME(HttpEnv, getRequestHeader,              ai_HttpEnv_getRequestHeader,              ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     930             :         PHP_ME(HttpEnv, getRequestBody,                ai_HttpEnv_getRequestBody,                ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     931             : 
     932             :         PHP_ME(HttpEnv, getResponseStatusForCode,      ai_HttpEnv_getResponseStatusForCode,      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     933             :         PHP_ME(HttpEnv, getResponseStatusForAllCodes,  ai_HttpEnv_getResponseStatusForAllCodes,  ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     934             : 
     935             :         PHP_ME(HttpEnv, getResponseHeader,             ai_HttpEnv_getResponseHeader,             ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     936             :         PHP_ME(HttpEnv, getResponseCode,               ai_HttpEnv_getResponseCode,               ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     937             :         PHP_ME(HttpEnv, setResponseHeader,             ai_HttpEnv_setResponseHeader,             ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     938             :         PHP_ME(HttpEnv, setResponseCode,               ai_HttpEnv_setResponseCode,               ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     939             : 
     940             :         PHP_ME(HttpEnv, negotiateLanguage,             ai_HttpEnv_negotiateLanguage,             ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     941             :         PHP_ME(HttpEnv, negotiateContentType,          ai_HttpEnv_negotiateContentType,          ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     942             :         PHP_ME(HttpEnv, negotiateEncoding,             ai_HttpEnv_negotiateEncoding,             ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     943             :         PHP_ME(HttpEnv, negotiateCharset,              ai_HttpEnv_negotiateCharset,              ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     944             :         PHP_ME(HttpEnv, negotiate,                     ai_HttpEnv_negotiate,                     ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     945             : 
     946             :         EMPTY_FUNCTION_ENTRY
     947             : };
     948             : 
     949             : #ifdef PHP_HTTP_HAVE_JSON
     950             : #include "ext/json/php_json.h"
     951             : 
     952           2 : static SAPI_POST_HANDLER_FUNC(php_http_json_post_handler)
     953             : {
     954           2 :         zval *zarg = arg;
     955           2 :         char *json_str = NULL;
     956           2 :         size_t json_len = 0;
     957             : 
     958             : #if PHP_VERSION_ID >= 50600
     959           2 :         if (SG(request_info).request_body) {
     960             :                 /* FG(stream_wrappers) not initialized yet, so we cannot use php://input */
     961           2 :                 php_stream_rewind(SG(request_info).request_body);
     962           2 :                 json_len = php_stream_copy_to_mem(SG(request_info).request_body, &json_str, PHP_STREAM_COPY_ALL, 0);
     963             :         }
     964             : #else
     965             :         json_str = SG(request_info).raw_post_data;
     966             :         json_len = SG(request_info).raw_post_data_length;
     967             : #endif
     968             : 
     969           2 :         if (json_len) {
     970             :                 zval zjson;
     971             : 
     972           2 :                 INIT_ZVAL(zjson);
     973           2 :                 php_json_decode(&zjson, json_str, json_len, 1, PG(max_input_nesting_level) TSRMLS_CC);
     974           2 :                 if (Z_TYPE(zjson) != IS_NULL) {
     975           2 :                         zval_dtor(zarg);
     976           2 :                         ZVAL_COPY_VALUE(zarg, (&zjson));
     977             :                 }
     978             :         }
     979             : #if PHP_VERSION_ID >= 50600
     980           2 :         STR_FREE(json_str);
     981             : #endif
     982           2 : }
     983             : 
     984         408 : static void php_http_env_register_json_handler(TSRMLS_D)
     985             : {
     986         408 :         sapi_post_entry entry = {NULL, 0, NULL, NULL};
     987             : 
     988         408 :         entry.post_reader = sapi_read_standard_form_data;
     989         408 :         entry.post_handler = php_http_json_post_handler;
     990             : 
     991         408 :         entry.content_type = "text/json";
     992         408 :         entry.content_type_len = lenof("text/json");
     993         408 :         sapi_register_post_entry(&entry TSRMLS_CC);
     994             : 
     995         408 :         entry.content_type = "application/json";
     996         408 :         entry.content_type_len = lenof("application/json");
     997         408 :         sapi_register_post_entry(&entry TSRMLS_CC);
     998         408 : }
     999             : #endif
    1000             : 
    1001             : zend_class_entry *php_http_env_class_entry;
    1002             : 
    1003         408 : PHP_MINIT_FUNCTION(http_env)
    1004             : {
    1005         408 :         zend_class_entry ce = {0};
    1006             : 
    1007         408 :         INIT_NS_CLASS_ENTRY(ce, "http", "Env", php_http_env_methods);
    1008         408 :         php_http_env_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
    1009             : 
    1010             : #ifdef PHP_HTTP_HAVE_JSON
    1011         408 :         php_http_env_register_json_handler(TSRMLS_C);
    1012             : #endif
    1013             : 
    1014         408 :         return SUCCESS;
    1015             : }
    1016             : 
    1017             : 
    1018             : /*
    1019             :  * Local variables:
    1020             :  * tab-width: 4
    1021             :  * c-basic-offset: 4
    1022             :  * End:
    1023             :  * vim600: noet sw=4 ts=4 fdm=marker
    1024             :  * vim<600: noet sw=4 ts=4
    1025             :  */

Generated by: LCOV version 1.11