LTP GCOV extension - code coverage report
Current view: directory - ext/http - http_message_api.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 337
Code covered: 63.2 % Executed lines: 213
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_message_api.c,v 1.86 2007/02/07 11:50:26 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_http_api.h"
      21                 : #include "php_http_encoding_api.h"
      22                 : #include "php_http_headers_api.h"
      23                 : #include "php_http_message_api.h"
      24                 : #include "php_http_request_api.h"
      25                 : #include "php_http_send_api.h"
      26                 : #include "php_http_url_api.h"
      27                 : 
      28                 : #define http_message_info_callback _http_message_info_callback
      29                 : static void _http_message_info_callback(http_message **message, HashTable **headers, http_info *info TSRMLS_DC)
      30             155 : {
      31             155 :         http_message *old = *message;
      32                 :         
      33                 :         /* advance message */
      34             155 :         if (old->type || zend_hash_num_elements(&old->hdrs) || PHPSTR_LEN(old)) {
      35              38 :                 (*message) = http_message_new();
      36              38 :                 (*message)->parent = old;
      37              38 :                 (*headers) = &((*message)->hdrs);
      38                 :         }
      39                 :         
      40             155 :         http_message_set_info(*message, info);
      41             155 : }
      42                 : 
      43                 : #define http_message_init_type _http_message_init_type
      44                 : static inline void _http_message_init_type(http_message *message, http_message_type type)
      45             315 : {
      46             315 :         message->http.version = .0;
      47                 :         
      48             315 :         switch (message->type = type) {
      49                 :                 case HTTP_MSG_RESPONSE:
      50             136 :                         message->http.info.response.code = 0;
      51             136 :                         message->http.info.response.status = NULL;
      52             136 :                         break;
      53                 : 
      54                 :                 case HTTP_MSG_REQUEST:
      55              21 :                         message->http.info.request.method = NULL;
      56              21 :                         message->http.info.request.url = NULL;
      57                 :                         break;
      58                 : 
      59                 :                 case HTTP_MSG_NONE:
      60                 :                 default:
      61                 :                         break;
      62                 :         }
      63             315 : }
      64                 : 
      65                 : PHP_HTTP_API http_message *_http_message_init_ex(http_message *message, http_message_type type ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
      66             158 : {
      67             158 :         if (!message) {
      68             157 :                 message = ecalloc_rel(1, sizeof(http_message));
      69                 :         }
      70                 : 
      71             158 :         http_message_init_type(message, type);
      72             158 :         message->parent = NULL;
      73             158 :         phpstr_init(&message->body);
      74             158 :         zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0);
      75                 : 
      76             158 :         return message;
      77                 : }
      78                 : 
      79                 : PHP_HTTP_API http_message *_http_message_init_env(http_message *message, http_message_type type TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
      80               0 : {
      81                 :         int free_msg;
      82                 :         http_info inf;
      83                 :         zval *sval, tval;
      84                 :         char *body_str;
      85                 :         size_t body_len;
      86                 :         
      87               0 :         if ((free_msg = !message)) {
      88               0 :                 message = http_message_init_rel(NULL, HTTP_MSG_NONE);
      89                 :         }
      90                 :         
      91               0 :         memset(&inf, 0, sizeof(http_info));
      92               0 :         switch (inf.type = type) {
      93                 :                 case HTTP_MSG_REQUEST:
      94               0 :                         if ((sval = http_get_server_var("SERVER_PROTOCOL", 1)) && !strncmp(Z_STRVAL_P(sval), "HTTP/", lenof("HTTP/"))) {
      95               0 :                                 inf.http.version = atof(Z_STRVAL_P(sval) + lenof("HTTP/"));
      96                 :                         } else {
      97               0 :                                 inf.http.version = 1.1;
      98                 :                         }
      99               0 :                         if ((sval = http_get_server_var("REQUEST_METHOD", 1))) {
     100               0 :                                 inf.http.info.request.method = estrdup(Z_STRVAL_P(sval));
     101                 :                         }
     102               0 :                         if ((sval = http_get_server_var("REQUEST_URI", 1))) {
     103               0 :                                 inf.http.info.request.url = estrdup(Z_STRVAL_P(sval));
     104                 :                         }
     105                 :                         
     106               0 :                         http_message_set_info(message, &inf);
     107               0 :                         http_get_request_headers(&message->hdrs);
     108               0 :                         if (SUCCESS == http_get_request_body_ex(&body_str, &body_len, 0)) {
     109               0 :                                 phpstr_from_string_ex(&message->body, body_str, body_len);
     110                 :                         }
     111               0 :                         break;
     112                 :                         
     113                 :                 case HTTP_MSG_RESPONSE:
     114               0 :                         if (!SG(sapi_headers).http_status_line || SUCCESS != http_info_parse_ex(SG(sapi_headers).http_status_line, &inf, 0)) {
     115               0 :                                 inf.http.version = 1.1;
     116               0 :                                 inf.http.info.response.code = 200;
     117               0 :                                 inf.http.info.response.status = estrdup("Ok");
     118                 :                         }
     119                 :                         
     120               0 :                         http_message_set_info(message, &inf);
     121               0 :                         http_get_response_headers(&message->hdrs);
     122               0 :                         if (SUCCESS == php_ob_get_buffer(&tval TSRMLS_CC)) {
     123               0 :                                 message->body.data = Z_STRVAL(tval);
     124               0 :                                 message->body.used = Z_STRLEN(tval);
     125               0 :                                 message->body.free = 1; /* "\0" */
     126                 :                         }
     127               0 :                         break;
     128                 :                         
     129                 :                 default:
     130               0 :                         if (free_msg) {
     131               0 :                                 http_message_free(&message);
     132                 :                         } else {
     133               0 :                                 message = NULL;
     134                 :                         }
     135                 :                         break;
     136                 :         }
     137               0 :         http_info_dtor(&inf);
     138                 :         
     139               0 :         return message;
     140                 : }
     141                 : 
     142                 : PHP_HTTP_API void _http_message_set_type(http_message *message, http_message_type type)
     143             157 : {
     144                 :         /* just act if different */
     145             157 :         if (type != message->type) {
     146                 : 
     147                 :                 /* free request info */
     148             157 :                 switch (message->type) {
     149                 :                         case HTTP_MSG_REQUEST:
     150               0 :                                 STR_FREE(message->http.info.request.method);
     151               0 :                                 STR_FREE(message->http.info.request.url);
     152               0 :                                 break;
     153                 :                         
     154                 :                         case HTTP_MSG_RESPONSE:
     155               0 :                                 STR_FREE(message->http.info.response.status);
     156                 :                                 break;
     157                 :                         
     158                 :                         default:
     159                 :                                 break;
     160                 :                 }
     161                 : 
     162                 :                 /* init */
     163             157 :                 http_message_init_type(message, type);
     164                 :         }
     165             157 : }
     166                 : 
     167                 : PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info)
     168             157 : {
     169             157 :         http_message_set_type(message, info->type);
     170             157 :         message->http.version = info->http.version;
     171             157 :         switch (message->type) {
     172                 :                 case IS_HTTP_REQUEST:
     173              21 :                         STR_SET(HTTP_INFO(message).request.url, HTTP_INFO(info).request.url ? estrdup(HTTP_INFO(info).request.url) : NULL);
     174              21 :                         STR_SET(HTTP_INFO(message).request.method, HTTP_INFO(info).request.method ? estrdup(HTTP_INFO(info).request.method) : NULL);
     175              21 :                         break;
     176                 :                 
     177                 :                 case IS_HTTP_RESPONSE:
     178             136 :                         HTTP_INFO(message).response.code = HTTP_INFO(info).response.code;
     179             136 :                         STR_SET(HTTP_INFO(message).response.status, HTTP_INFO(info).response.status ? estrdup(HTTP_INFO(info).response.status) : NULL);
     180                 :                         break;
     181                 :                 
     182                 :                 default:
     183                 :                         break;
     184                 :         }
     185             157 : }
     186                 : 
     187                 : #define http_message_body_parse(m, ms, ml, c) _http_message_body_parse((m), (ms), (ml), (c) TSRMLS_CC)
     188                 : static inline void _http_message_body_parse(http_message *msg, const char *message, size_t message_length, const char **continue_at TSRMLS_DC)
     189             117 : {
     190                 :         zval *c;
     191                 :         size_t remaining;
     192                 :         const char *body;
     193                 :         
     194             117 :         *continue_at = NULL;
     195             117 :         if ((body = http_locate_body(message))) {
     196              93 :                 remaining = message + message_length - body;
     197                 :                 
     198              93 :                 if ((c = http_message_header(msg, "Transfer-Encoding"))) {
     199              27 :                         if (strstr(Z_STRVAL_P(c), "chunked")) {
     200                 :                                 /* message has chunked transfer encoding */
     201                 :                                 char *decoded;
     202                 :                                 size_t decoded_len;
     203                 :                                 
     204                 :                                 /* decode and replace Transfer-Encoding with Content-Length header */
     205              26 :                                 if ((*continue_at = http_encoding_dechunk(body, message + message_length - body, &decoded, &decoded_len))) {
     206                 :                                         zval *len;
     207                 :                                         char *tmp;
     208                 :                                         int tmp_len;
     209                 :                                         
     210              26 :                                         tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
     211              26 :                                         MAKE_STD_ZVAL(len);
     212              26 :                                         ZVAL_STRINGL(len, tmp, tmp_len, 0);
     213                 :                                         
     214              26 :                                         ZVAL_ADDREF(c);
     215              26 :                                         zend_hash_update(&msg->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &c, sizeof(zval *), NULL);
     216              26 :                                         zend_hash_del(&msg->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding"));
     217              26 :                                         zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length"));
     218              26 :                                         zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
     219                 :                                         
     220              26 :                                         phpstr_from_string_ex(PHPSTR(msg), decoded, decoded_len);
     221              26 :                                         efree(decoded);
     222                 :                                 }
     223                 :                         }
     224              27 :                         zval_ptr_dtor(&c);
     225                 :                 }
     226                 :                 
     227              93 :                 if (!*continue_at && (c = http_message_header(msg, "Content-Length"))) {
     228                 :                         /* message has content-length header */
     229              59 :                         ulong len = strtoul(Z_STRVAL_P(c), NULL, 10);
     230              59 :                         if (len > remaining) {
     231               0 :                                 http_error_ex(HE_NOTICE, HTTP_E_MALFORMED_HEADERS, "The Content-Length header pretends a larger body than actually received (expected %lu bytes; got %lu bytes)", len, remaining);
     232               0 :                                 len = remaining;
     233                 :                         }
     234              59 :                         phpstr_from_string_ex(PHPSTR(msg), body, len);
     235              59 :                         *continue_at = body + len;
     236              59 :                         zval_ptr_dtor(&c);
     237                 :                 }
     238                 :                 
     239              93 :                 if (!*continue_at && (c = http_message_header(msg, "Content-Range"))) {
     240                 :                         /* message has content-range header */
     241               4 :                         ulong total = 0, start = 0, end = 0, len = 0;
     242                 :                         
     243               4 :                         if (!strncasecmp(Z_STRVAL_P(c), "bytes", lenof("bytes")) && 
     244                 :                                         (       Z_STRVAL_P(c)[lenof("bytes")] == ':' ||
     245                 :                                                 Z_STRVAL_P(c)[lenof("bytes")] == ' ' ||
     246                 :                                                 Z_STRVAL_P(c)[lenof("bytes")] == '=')) {
     247               4 :                                 char *total_at = NULL, *end_at = NULL;
     248               4 :                                 char *start_at = Z_STRVAL_P(c) + sizeof("bytes");
     249                 :                                 
     250               4 :                                 start = strtoul(start_at, &end_at, 10);
     251               4 :                                 if (end_at) {
     252               4 :                                         end = strtoul(end_at + 1, &total_at, 10);
     253               4 :                                         if (total_at && strncmp(total_at + 1, "*", 1)) {
     254               4 :                                                 total = strtoul(total_at + 1, NULL, 10);
     255                 :                                         }
     256               4 :                                         if ((len = (end + 1 - start)) > remaining) {
     257               0 :                                                 http_error_ex(HE_NOTICE, HTTP_E_MALFORMED_HEADERS, "The Content-Range header pretends a larger body than actually received (expected %lu bytes; got %lu bytes)", len, remaining);
     258               0 :                                                 len = remaining;
     259                 :                                         }
     260               4 :                                         if (end >= start && (!total || end < total)) {
     261               3 :                                                 phpstr_from_string_ex(PHPSTR(msg), body, len);
     262               3 :                                                 *continue_at = body + len;
     263                 :                                         }
     264                 :                                 }
     265                 :                         }
     266                 :                         
     267               4 :                         if (!*continue_at) {
     268               1 :                                 http_error_ex(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid Content-Range header: %s", Z_STRVAL_P(c));
     269                 :                         }
     270               4 :                         zval_ptr_dtor(&c);
     271                 :                 }
     272                 :                 
     273              93 :                 if (!*continue_at) {
     274                 :                         /* no headers that indicate content length */
     275               6 :                         if (HTTP_MSG_TYPE(RESPONSE, msg)) {
     276               1 :                                 phpstr_from_string_ex(PHPSTR(msg), body, remaining);
     277                 :                         } else {
     278               4 :                                 *continue_at = body;
     279                 :                         }
     280                 :                 }
     281                 :                 
     282                 : #ifdef HTTP_HAVE_ZLIB
     283                 :                 /* check for compressed data */
     284              93 :                 if ((c = http_message_header(msg, "Vary"))) {
     285              32 :                         zval_ptr_dtor(&c);
     286                 :                         
     287              32 :                         if ((c = http_message_header(msg, "Content-Encoding"))) {
     288              11 :                                 char *decoded = NULL;
     289              11 :                                 size_t decoded_len = 0;
     290                 :                                 
     291              11 :                                 if (    !strcasecmp(Z_STRVAL_P(c), "gzip") ||
     292                 :                                                 !strcasecmp(Z_STRVAL_P(c), "x-gzip") ||
     293                 :                                                 !strcasecmp(Z_STRVAL_P(c), "deflate")) {
     294              11 :                                         http_encoding_inflate(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len);
     295                 :                                 }
     296                 :                                 
     297              11 :                                 if (decoded) {
     298                 :                                         zval *len, **original_len;
     299                 :                                         char *tmp;
     300                 :                                         int tmp_len;
     301                 :                                         
     302              11 :                                         tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len);
     303              11 :                                         MAKE_STD_ZVAL(len);
     304              11 :                                         ZVAL_STRINGL(len, tmp, tmp_len, 0);
     305                 :                                         
     306              11 :                                         ZVAL_ADDREF(c);
     307              11 :                                         zend_hash_update(&msg->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), (void *) &c, sizeof(zval *), NULL);
     308              11 :                                         zend_hash_del(&msg->hdrs, "Content-Encoding", sizeof("Content-Encoding"));
     309              11 :                                         if (SUCCESS == zend_hash_find(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &original_len)) {
     310              11 :                                                 ZVAL_ADDREF(*original_len);
     311              11 :                                                 zend_hash_update(&msg->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) original_len, sizeof(zval *), NULL);
     312              11 :                                                 zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
     313                 :                                         } else {
     314               0 :                                                 zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL);
     315                 :                                         }
     316                 :                                         
     317              11 :                                         phpstr_dtor(PHPSTR(msg));
     318              11 :                                         PHPSTR(msg)->data = decoded;
     319              11 :                                         PHPSTR(msg)->used = decoded_len;
     320              11 :                                         PHPSTR(msg)->free = 1;
     321                 :                                 }
     322                 :                                 
     323              11 :                                 zval_ptr_dtor(&c);
     324                 :                         }
     325                 :                 }
     326                 : #endif /* HTTP_HAVE_ZLIB */
     327                 :         }
     328             117 : }
     329                 : 
     330                 : PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t message_length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC)
     331             121 : {
     332                 :         const char *continue_at;
     333             121 :         zend_bool free_msg = msg ? 0 : 1;
     334                 : 
     335             121 :         if ((!message) || (message_length < HTTP_MSG_MIN_SIZE)) {
     336               4 :                 http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Empty or too short HTTP message: '%s'", message);
     337               4 :                 return NULL;
     338                 :         }
     339                 : 
     340             117 :         msg = http_message_init_rel(msg, 0);
     341                 : 
     342             117 :         if (SUCCESS != http_parse_headers_cb(message, &msg->hdrs, 1, (http_info_callback) http_message_info_callback, (void *) &msg)) {
     343               0 :                 if (free_msg) {
     344               0 :                         http_message_free(&msg);
     345                 :                 }
     346               0 :                 http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse message headers");
     347               0 :                 return NULL;
     348                 :         }
     349                 :         
     350             117 :         http_message_body_parse(msg, message, message_length, &continue_at);
     351                 :         
     352                 :         /* check for following messages */
     353             117 :         if (continue_at && (continue_at < (message + message_length))) {
     354              38 :                 while (HTTP_IS_CTYPE(space, *continue_at)) ++continue_at;
     355              38 :                 if (continue_at < (message + message_length)) {
     356              10 :                         http_message *next = NULL, *most = NULL;
     357                 : 
     358                 :                         /* set current message to parent of most parent following messages and return deepest */
     359              10 :                         if ((most = next = http_message_parse_rel(NULL, continue_at, message + message_length - continue_at))) {
     360              10 :                                 while (most->parent) most = most->parent;
     361              10 :                                 most->parent = msg;
     362              10 :                                 msg = next;
     363                 :                         }
     364                 :                 }
     365                 :         }
     366                 : 
     367             117 :         return msg;
     368                 : }
     369                 : 
     370                 : PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length)
     371              50 : {
     372                 :         phpstr str;
     373              50 :         HashKey key = initHashKey(0);
     374                 :         zval **header;
     375                 :         char *data;
     376                 :         HashPosition pos1;
     377                 : 
     378              50 :         phpstr_init_ex(&str, 4096, 0);
     379                 : 
     380              50 :         switch (msg->type) {
     381                 :                 case HTTP_MSG_REQUEST:
     382              18 :                         phpstr_appendf(&str, HTTP_INFO_REQUEST_FMT_ARGS(&msg->http, HTTP_CRLF));
     383              18 :                         break;
     384                 : 
     385                 :                 case HTTP_MSG_RESPONSE:
     386              32 :                         phpstr_appendf(&str, HTTP_INFO_RESPONSE_FMT_ARGS(&msg->http, HTTP_CRLF));
     387                 :                         break;
     388                 : 
     389                 :                 case HTTP_MSG_NONE:
     390                 :                 default:
     391                 :                         break;
     392                 :         }
     393                 : 
     394             123 :         FOREACH_HASH_KEYVAL(pos1, &msg->hdrs, key, header) {
     395              73 :                 if (key.type == HASH_KEY_IS_STRING) {
     396                 :                         HashPosition pos2;
     397                 :                         zval **single_header;
     398                 : 
     399              73 :                         switch (Z_TYPE_PP(header)) {
     400                 :                                 case IS_STRING:
     401              73 :                                         phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(header));
     402              73 :                                         break;
     403                 : 
     404                 :                                 case IS_ARRAY:
     405               0 :                                         FOREACH_VAL(pos2, *header, single_header) {
     406               0 :                                                 phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(single_header));
     407                 :                                         }
     408                 :                                         break;
     409                 :                         }
     410                 :                 }
     411                 :         }
     412                 : 
     413              50 :         if (PHPSTR_LEN(msg)) {
     414              13 :                 phpstr_appends(&str, HTTP_CRLF);
     415              13 :                 phpstr_append(&str, PHPSTR_VAL(msg), PHPSTR_LEN(msg));
     416              13 :                 phpstr_appends(&str, HTTP_CRLF);
     417                 :         }
     418                 : 
     419              50 :         data = phpstr_data(&str, string, length);
     420              50 :         if (!string) {
     421               0 :                 efree(data);
     422                 :         }
     423                 : 
     424              50 :         phpstr_dtor(&str);
     425              50 : }
     426                 : 
     427                 : PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length)
     428              10 : {
     429                 :         char *buf;
     430                 :         size_t len;
     431                 :         phpstr str;
     432                 : 
     433              10 :         phpstr_init(&str);
     434                 : 
     435                 :         do {
     436              43 :                 http_message_tostring(message, &buf, &len);
     437              43 :                 phpstr_prepend(&str, buf, len);
     438              43 :                 efree(buf);
     439              43 :         } while ((message = message->parent));
     440                 : 
     441              10 :         buf = phpstr_data(&str, string, length);
     442              10 :         if (!string) {
     443               0 :                 efree(buf);
     444                 :         }
     445                 : 
     446              10 :         phpstr_dtor(&str);
     447              10 : }
     448                 : 
     449                 : PHP_HTTP_API http_message *_http_message_reverse(http_message *msg)
     450               0 : {
     451                 :         int i, c;
     452                 :         
     453               0 :         http_message_count(c, msg);
     454                 :         
     455               0 :         if (c > 1) {
     456               0 :                 http_message *tmp = msg, **arr = ecalloc(c, sizeof(http_message *));
     457                 :                 
     458               0 :                 for (i = 0; i < c; ++i) {
     459               0 :                         arr[i] = tmp;
     460               0 :                         tmp = tmp->parent;
     461                 :                 }
     462               0 :                 arr[0]->parent = NULL;
     463               0 :                 for (i = 0; i < c-1; ++i) {
     464               0 :                         arr[i+1]->parent = arr[i];
     465                 :                 }
     466                 :                 
     467               0 :                 msg = arr[c-1];
     468               0 :                 efree(arr);
     469                 :         }
     470                 :         
     471               0 :         return msg;
     472                 : }
     473                 : 
     474                 : PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2)
     475               3 : {
     476               6 :         if (m1 && m2) {
     477               3 :                 int i = 0, c1, c2;
     478               3 :                 http_message *t1 = m1, *t2 = m2, *p1, *p2;
     479                 :                 
     480               3 :                 http_message_count(c1, m1);
     481               3 :                 http_message_count(c2, m2);
     482                 :                 
     483               7 :                 while (i++ < (c1 - c2)) {
     484               1 :                         t1 = t1->parent;
     485                 :                 }
     486               9 :                 while (i++ <= c1) {
     487               3 :                         p1 = t1->parent;
     488               3 :                         p2 = t2->parent;
     489               3 :                         t1->parent = t2;
     490               3 :                         t2->parent = p1;
     491               3 :                         t1 = p1;
     492               3 :                         t2 = p2;
     493                 :                 }
     494               0 :         } else if (!m1 && m2) {
     495               0 :                 m1 = m2;
     496                 :         }
     497               3 :         return m1;
     498                 : }
     499                 : 
     500                 : PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *obj TSRMLS_DC)
     501              13 : {
     502                 :         zval strct;
     503                 :         zval *headers;
     504                 :         
     505              13 :         INIT_ZARR(strct, HASH_OF(obj));
     506                 :         
     507              13 :         add_assoc_long(&strct, "type", msg->type);
     508              13 :         add_assoc_double(&strct, "httpVersion", msg->http.version);
     509              13 :         switch (msg->type)
     510                 :         {
     511                 :                 case HTTP_MSG_RESPONSE:
     512              11 :                         add_assoc_long(&strct, "responseCode", msg->http.info.response.code);
     513              11 :                         add_assoc_string(&strct, "responseStatus", STR_PTR(msg->http.info.response.status), 1);
     514              11 :                 break;
     515                 :                 
     516                 :                 case HTTP_MSG_REQUEST:
     517               2 :                         add_assoc_string(&strct, "requestMethod", STR_PTR(msg->http.info.request.method), 1);
     518               2 :                         add_assoc_string(&strct, "requestUrl", STR_PTR(msg->http.info.request.url), 1);
     519                 :                 break;
     520                 :                 
     521                 :                 case HTTP_MSG_NONE:
     522                 :                         /* avoid compiler warning */
     523                 :                 break;
     524                 :         }
     525                 :         
     526              13 :         MAKE_STD_ZVAL(headers);
     527              13 :         array_init(headers);
     528              13 :         zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     529              13 :         add_assoc_zval(&strct, "headers", headers);
     530                 :         
     531              13 :         add_assoc_stringl(&strct, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg), 1);
     532                 :         
     533              13 :         if (msg->parent) {
     534                 :                 zval *parent;
     535                 :                 
     536               5 :                 MAKE_STD_ZVAL(parent);
     537               5 :                 if (Z_TYPE_P(obj) == IS_ARRAY) {
     538               0 :                         array_init(parent);
     539                 :                 } else {
     540               5 :                         object_init(parent);
     541                 :                 }
     542               5 :                 add_assoc_zval(&strct, "parentMessage", parent);
     543               5 :                 http_message_tostruct_recursive(msg->parent, parent);
     544                 :         } else {
     545               8 :                 add_assoc_null(&strct, "parentMessage");
     546                 :         }
     547              13 : }
     548                 : 
     549                 : PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC)
     550               0 : {
     551               0 :         STATUS rs = FAILURE;
     552                 : 
     553               0 :         switch (message->type) {
     554                 :                 case HTTP_MSG_RESPONSE:
     555                 :                 {
     556               0 :                         HashKey key = initHashKey(0);
     557                 :                         zval **val;
     558                 :                         HashPosition pos;
     559                 : 
     560               0 :                         FOREACH_HASH_KEYVAL(pos, &message->hdrs, key, val) {
     561               0 :                                 if (key.type == HASH_KEY_IS_STRING) {
     562               0 :                                         http_send_header_zval_ex(key.str, key.len-1, val, 1);
     563                 :                                 }
     564                 :                         }
     565               0 :                         rs =    SUCCESS == http_send_status(message->http.info.response.code) &&
     566                 :                                         SUCCESS == http_send_data(PHPSTR_VAL(message), PHPSTR_LEN(message)) ?
     567                 :                                         SUCCESS : FAILURE;
     568               0 :                         break;
     569                 :                 }
     570                 : 
     571                 :                 case HTTP_MSG_REQUEST:
     572                 :                 {
     573                 : #ifdef HTTP_HAVE_CURL
     574               0 :                         char *uri = NULL;
     575                 :                         http_request request;
     576                 :                         zval **zhost, options, headers;
     577                 : 
     578               0 :                         INIT_PZVAL(&options);
     579               0 :                         INIT_PZVAL(&headers);
     580               0 :                         array_init(&options);
     581               0 :                         array_init(&headers);
     582               0 :                         zend_hash_copy(Z_ARRVAL(headers), &message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     583               0 :                         add_assoc_zval(&options, "headers", &headers);
     584                 : 
     585                 :                         /* check host header */
     586               0 :                         if (SUCCESS == zend_hash_find(&message->hdrs, "Host", sizeof("Host"), (void *) &zhost)) {
     587               0 :                                 char *colon = NULL;
     588               0 :                                 php_url parts, *url = php_url_parse(message->http.info.request.url);
     589                 :                                 
     590               0 :                                 memset(&parts, 0, sizeof(php_url));
     591                 : 
     592                 :                                 /* check for port */
     593               0 :                                 if ((colon = strchr(Z_STRVAL_PP(zhost), ':'))) {
     594               0 :                                         parts.port = atoi(colon + 1);
     595               0 :                                         parts.host = estrndup(Z_STRVAL_PP(zhost), (Z_STRVAL_PP(zhost) - colon - 1));
     596                 :                                 } else {
     597               0 :                                         parts.host = estrndup(Z_STRVAL_PP(zhost), Z_STRLEN_PP(zhost));
     598                 :                                 }
     599                 :                                 
     600               0 :                                 http_build_url(HTTP_URL_REPLACE, url, &parts, NULL, &uri, NULL);
     601               0 :                                 php_url_free(url);
     602               0 :                                 efree(parts.host);
     603                 :                         } else {
     604               0 :                                 uri = http_absolute_url(message->http.info.request.url);
     605                 :                         }
     606                 : 
     607               0 :                         if ((request.meth = http_request_method_exists(1, 0, message->http.info.request.method))) {
     608                 :                                 http_request_body body;
     609                 :                                 
     610               0 :                                 http_request_init_ex(&request, NULL, request.meth, uri);
     611               0 :                                 request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, PHPSTR_VAL(message), PHPSTR_LEN(message), 0);
     612               0 :                                 if (SUCCESS == (rs = http_request_prepare(&request, NULL))) {
     613               0 :                                         http_request_exec(&request);
     614                 :                                 }
     615               0 :                                 http_request_dtor(&request);
     616                 :                         } else {
     617               0 :                                 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD,
     618                 :                                         "Cannot send HttpMessage. Request method %s not supported",
     619                 :                                         message->http.info.request.method);
     620                 :                         }
     621               0 :                         efree(uri);
     622                 : #else
     623                 :                         http_error(HE_WARNING, HTTP_E_RUNTIME, "HTTP requests not supported - ext/http was not linked against libcurl.");
     624                 : #endif
     625               0 :                 break;
     626                 :                 }
     627                 : 
     628                 :                 case HTTP_MSG_NONE:
     629                 :                 default:
     630               0 :                         http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HTTP_MSG_REQUEST nor HTTP_MSG_RESPONSE");
     631                 :                         break;
     632                 :         }
     633                 : 
     634               0 :         return rs;
     635                 : }
     636                 : 
     637                 : PHP_HTTP_API http_message *_http_message_dup(http_message *orig TSRMLS_DC)
     638               0 : {
     639               0 :         http_message *temp, *copy = NULL;
     640                 :         http_info info;
     641                 :         
     642               0 :         if (orig) {
     643               0 :                 info.type = orig->type;
     644               0 :                 info.http = orig->http;
     645                 :                 
     646               0 :                 copy = temp = http_message_new();
     647               0 :                 http_message_set_info(temp, &info);
     648               0 :                 zend_hash_copy(&temp->hdrs, &orig->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     649               0 :                 phpstr_append(&temp->body, orig->body.data, orig->body.used);
     650                 :         
     651               0 :                 while (orig->parent) {
     652               0 :                         info.type = orig->parent->type;
     653               0 :                         info.http = orig->parent->http;
     654                 :                 
     655               0 :                         temp->parent = http_message_new();
     656               0 :                         http_message_set_info(temp->parent, &info);
     657               0 :                         zend_hash_copy(&temp->parent->hdrs, &orig->parent->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     658               0 :                         phpstr_append(&temp->parent->body, orig->parent->body.data, orig->parent->body.used);
     659                 :                 
     660               0 :                         temp = temp->parent;
     661               0 :                         orig = orig->parent;
     662                 :                 }
     663                 :         }
     664                 :         
     665               0 :         return copy;
     666                 : }
     667                 : 
     668                 : PHP_HTTP_API void _http_message_dtor(http_message *message)
     669             165 : {
     670             165 :         if (message) {
     671             158 :                 zend_hash_destroy(&message->hdrs);
     672             158 :                 phpstr_dtor(PHPSTR(message));
     673                 :                 
     674             158 :                 switch (message->type) {
     675                 :                         case HTTP_MSG_REQUEST:
     676              21 :                                 STR_SET(message->http.info.request.method, NULL);
     677              21 :                                 STR_SET(message->http.info.request.url, NULL);
     678              21 :                                 break;
     679                 :                         
     680                 :                         case HTTP_MSG_RESPONSE:
     681             136 :                                 STR_SET(message->http.info.response.status, NULL);
     682                 :                                 break;
     683                 :                         
     684                 :                         default:
     685                 :                                 break;
     686                 :                 }
     687                 :         }
     688             165 : }
     689                 : 
     690                 : PHP_HTTP_API void _http_message_free(http_message **message)
     691              13 : {
     692              13 :         if (*message) {
     693              13 :                 if ((*message)->parent) {
     694               5 :                         http_message_free(&(*message)->parent);
     695                 :                 }
     696              13 :                 http_message_dtor(*message);
     697              13 :                 efree(*message);
     698              13 :                 *message = NULL;
     699                 :         }
     700              13 : }
     701                 : 
     702                 : /*
     703                 :  * Local variables:
     704                 :  * tab-width: 4
     705                 :  * c-basic-offset: 4
     706                 :  * End:
     707                 :  * vim600: noet sw=4 ts=4 fdm=marker
     708                 :  * vim<600: noet sw=4 ts=4
     709                 :  */
     710                 : 

Generated by: LTP GCOV extension version 1.5