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

LTP GCOV extension - code coverage report
Current view: directory - soap - php_http.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 787
Code covered: 27.4 % Executed lines: 216
Legend: not executed executed

       1                 : /*
       2                 :   +----------------------------------------------------------------------+
       3                 :   | PHP Version 5                                                        |
       4                 :   +----------------------------------------------------------------------+
       5                 :   | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :   +----------------------------------------------------------------------+
       7                 :   | This source file is subject to version 3.01 of the PHP license,      |
       8                 :   | that is bundled with this package in the file LICENSE, and is        |
       9                 :   | available through the world-wide-web at the following url:           |
      10                 :   | http://www.php.net/license/3_01.txt                                  |
      11                 :   | If you did not receive a copy of the PHP license and are unable to   |
      12                 :   | obtain it through the world-wide-web, please send a note to          |
      13                 :   | license@php.net so we can mail you a copy immediately.               |
      14                 :   +----------------------------------------------------------------------+
      15                 :   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
      16                 :   |          Shane Caraveo <shane@caraveo.com>                           |
      17                 :   |          Dmitry Stogov <dmitry@zend.com>                             |
      18                 :   +----------------------------------------------------------------------+
      19                 : */
      20                 : /* $Id: php_http.c 281589 2009-06-03 12:39:50Z iliaa $ */
      21                 : 
      22                 : #include "php_soap.h"
      23                 : #include "ext/standard/base64.h"
      24                 : #include "ext/standard/md5.h"
      25                 : #include "ext/standard/php_rand.h"
      26                 : 
      27                 : static char *get_http_header_value(char *headers, char *type);
      28                 : static int get_http_body(php_stream *socketd, int close, char *headers,  char **response, int *out_size TSRMLS_DC);
      29                 : static int get_http_headers(php_stream *socketd,char **response, int *out_size TSRMLS_DC);
      30                 : 
      31                 : #define smart_str_append_const(str, const) \
      32                 :         smart_str_appendl(str,const,sizeof(const)-1)
      33                 : 
      34                 : /* Proxy HTTP Authentication */
      35                 : void proxy_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_DC)
      36               0 : {
      37                 :         zval **login, **password;
      38                 : 
      39               0 :         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_login", sizeof("_proxy_login"), (void **)&login) == SUCCESS) {
      40                 :                 unsigned char* buf;
      41                 :                 int len;
      42               0 :                 smart_str auth = {0};
      43                 : 
      44               0 :                 smart_str_appendl(&auth, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
      45               0 :                 smart_str_appendc(&auth, ':');
      46               0 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_password", sizeof("_proxy_password"), (void **)&password) == SUCCESS) {
      47               0 :                         smart_str_appendl(&auth, Z_STRVAL_PP(password), Z_STRLEN_PP(password));
      48                 :                 }
      49               0 :                 smart_str_0(&auth);
      50               0 :                 buf = php_base64_encode((unsigned char*)auth.c, auth.len, &len);
      51               0 :                 smart_str_append_const(soap_headers, "Proxy-Authorization: Basic ");
      52               0 :                 smart_str_appendl(soap_headers, (char*)buf, len);
      53               0 :                 smart_str_append_const(soap_headers, "\r\n");
      54               0 :                 efree(buf);
      55               0 :                 smart_str_free(&auth);
      56                 :         }
      57               0 : }
      58                 : 
      59                 : /* HTTP Authentication */
      60                 : void basic_authentication(zval* this_ptr, smart_str* soap_headers TSRMLS_DC)
      61             697 : {
      62                 :         zval **login, **password;
      63                 : 
      64             697 :         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", sizeof("_login"), (void **)&login) == SUCCESS &&
      65                 :                         !zend_hash_exists(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest"))) {
      66                 :                 unsigned char* buf;
      67                 :                 int len;
      68               0 :                 smart_str auth = {0};
      69                 : 
      70               0 :                 smart_str_appendl(&auth, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
      71               0 :                 smart_str_appendc(&auth, ':');
      72               0 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS) {
      73               0 :                         smart_str_appendl(&auth, Z_STRVAL_PP(password), Z_STRLEN_PP(password));
      74                 :                 }
      75               0 :                 smart_str_0(&auth);
      76               0 :                 buf = php_base64_encode((unsigned char*)auth.c, auth.len, &len);
      77               0 :                 smart_str_append_const(soap_headers, "Authorization: Basic ");
      78               0 :                 smart_str_appendl(soap_headers, (char*)buf, len);
      79               0 :                 smart_str_append_const(soap_headers, "\r\n");
      80               0 :                 efree(buf);
      81               0 :                 smart_str_free(&auth);
      82                 :         }
      83             697 : }
      84                 : 
      85                 : static php_stream* http_connect(zval* this_ptr, php_url *phpurl, int use_ssl, php_stream_context *context, int *use_proxy TSRMLS_DC)
      86               1 : {
      87                 :         php_stream *stream;
      88                 :         zval **proxy_host, **proxy_port, **tmp;
      89                 :         char *host;
      90                 :         char *name;
      91                 :         long namelen;
      92                 :         int port;
      93                 :         int old_error_reporting;
      94                 :         struct timeval tv;
      95               1 :         struct timeval *timeout = NULL;
      96                 : 
      97               1 :         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_host", sizeof("_proxy_host"), (void **) &proxy_host) == SUCCESS &&
      98                 :             Z_TYPE_PP(proxy_host) == IS_STRING &&
      99                 :             zend_hash_find(Z_OBJPROP_P(this_ptr), "_proxy_port", sizeof("_proxy_port"), (void **) &proxy_port) == SUCCESS &&
     100                 :             Z_TYPE_PP(proxy_port) == IS_LONG) {
     101               0 :                 host = Z_STRVAL_PP(proxy_host);
     102               0 :                 port = Z_LVAL_PP(proxy_port);
     103               0 :                 *use_proxy = 1;
     104                 :         } else {
     105               1 :                 host = phpurl->host;
     106               1 :                 port = phpurl->port;
     107                 :         }
     108               1 :         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_connection_timeout", sizeof("_connection_timeout"), (void **) &tmp) == SUCCESS &&
     109                 :             Z_TYPE_PP(tmp) == IS_LONG && Z_LVAL_PP(tmp) > 0) {
     110               0 :           tv.tv_sec = Z_LVAL_PP(tmp);
     111               0 :           tv.tv_usec = 0;
     112               0 :                 timeout = &tv;
     113                 :         }
     114                 : 
     115               1 :         old_error_reporting = EG(error_reporting);
     116               1 :         EG(error_reporting) &= ~(E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE);
     117                 : 
     118               1 :         namelen = spprintf(&name, 0, "%s://%s:%d", (use_ssl && !*use_proxy)? "ssl" : "tcp", host, port);
     119                 : 
     120               1 :         stream = php_stream_xport_create(name, namelen,
     121                 :                 ENFORCE_SAFE_MODE | REPORT_ERRORS,
     122                 :                 STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
     123                 :                 NULL /*persistent_id*/,
     124                 :                 timeout,
     125                 :                 context,
     126                 :                 NULL, NULL);
     127               1 :         efree(name);
     128                 : 
     129                 :         /* SSL & proxy */
     130               1 :         if (stream && *use_proxy && use_ssl) {
     131               0 :                 smart_str soap_headers = {0};
     132                 :                 char *http_headers;
     133                 :                 int http_header_size;
     134                 : 
     135               0 :                 smart_str_append_const(&soap_headers, "CONNECT ");
     136               0 :                 smart_str_appends(&soap_headers, phpurl->host);
     137               0 :                 smart_str_appendc(&soap_headers, ':');
     138               0 :                 smart_str_append_unsigned(&soap_headers, phpurl->port);
     139               0 :                 smart_str_append_const(&soap_headers, " HTTP/1.1\r\n");
     140               0 :                 proxy_authentication(this_ptr, &soap_headers TSRMLS_CC);
     141               0 :                 smart_str_append_const(&soap_headers, "\r\n");
     142               0 :                 if (php_stream_write(stream, soap_headers.c, soap_headers.len) != soap_headers.len) {
     143               0 :                         php_stream_close(stream);
     144               0 :                         stream = NULL;
     145                 :                 }
     146               0 :                 smart_str_free(&soap_headers);
     147                 : 
     148               0 :                 if (stream) {
     149               0 :                         if (!get_http_headers(stream, &http_headers, &http_header_size TSRMLS_CC) || http_headers == NULL) {
     150               0 :                                 php_stream_close(stream);
     151               0 :                                 stream = NULL;
     152                 :                         }
     153               0 :                         if (http_headers) {
     154               0 :                                 efree(http_headers);
     155                 :                         }
     156                 :                 }
     157                 :                 /* enable SSL transport layer */
     158               0 :                 if (stream) {
     159               0 :                         if (php_stream_xport_crypto_setup(stream, STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 ||
     160                 :                             php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) {
     161               0 :                                 php_stream_close(stream);
     162               0 :                                 stream = NULL;
     163                 :                         }
     164                 :                 }
     165                 :         }
     166                 : 
     167               1 :         EG(error_reporting) = old_error_reporting;
     168               1 :         return stream;
     169                 : }
     170                 : 
     171                 : static int in_domain(const char *host, const char *domain)
     172               0 : {
     173               0 :   if (domain[0] == '.') {
     174               0 :     int l1 = strlen(host);
     175               0 :     int l2 = strlen(domain);
     176               0 :     if (l1 > l2) {
     177               0 :         return strcmp(host+l1-l2,domain) == 0;
     178                 :     } else {
     179               0 :       return 0;
     180                 :     }
     181                 :   } else {
     182               0 :     return strcmp(host,domain) == 0;
     183                 :   }
     184                 : }
     185                 : 
     186                 : int make_http_soap_request(zval  *this_ptr,
     187                 :                            char  *buf,
     188                 :                            int    buf_size,
     189                 :                            char  *location,
     190                 :                            char  *soapaction,
     191                 :                            int    soap_version,
     192                 :                            char **buffer,
     193                 :                            int   *buffer_len TSRMLS_DC)
     194             316 : {
     195                 :         char *request;
     196             316 :         smart_str soap_headers = {0};
     197             316 :         smart_str soap_headers_z = {0};
     198                 :         int request_size, err;
     199             316 :         php_url *phpurl = NULL;
     200                 :         php_stream *stream;
     201                 :         zval **trace, **tmp;
     202             316 :         int use_proxy = 0;
     203                 :         int use_ssl;
     204                 :         char *http_headers, *http_body, *content_type, *http_version, *cookie_itt;
     205                 :         int http_header_size, http_body_size, http_close;
     206                 :         char *connection;
     207                 :         int http_1_1;
     208                 :         int http_status;
     209             316 :         int content_type_xml = 0;
     210                 :         char *content_encoding;
     211             316 :         char *http_msg = NULL;
     212                 :         zend_bool old_allow_url_fopen;
     213             316 :         php_stream_context *context = NULL;
     214                 : 
     215             316 :         if (this_ptr == NULL || Z_TYPE_P(this_ptr) != IS_OBJECT) {
     216               0 :                 return FALSE;
     217                 :         }
     218                 : 
     219             316 :   request = buf;
     220             316 :   request_size = buf_size;
     221                 :         /* Compress request */
     222             316 :         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "compression", sizeof("compression"), (void **)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_LONG) {
     223               0 :                 int level = Z_LVAL_PP(tmp) & 0x0f;
     224               0 :                 int kind  = Z_LVAL_PP(tmp) & SOAP_COMPRESSION_DEFLATE;
     225                 : 
     226               0 :                 if (level > 9) {level = 9;}
     227                 :                 
     228               0 :           if ((Z_LVAL_PP(tmp) & SOAP_COMPRESSION_ACCEPT) != 0) {
     229               0 :                         smart_str_append_const(&soap_headers_z,"Accept-Encoding: gzip, deflate\r\n");
     230                 :           }
     231               0 :           if (level > 0) {
     232                 :                         zval func;
     233                 :                         zval retval;
     234                 :                         zval param1, param2, param3;
     235                 :                         zval *params[3];
     236                 :                         int n;
     237                 : 
     238               0 :                         params[0] = &param1;
     239               0 :                         INIT_PZVAL(params[0]);
     240               0 :                         params[1] = &param2;
     241               0 :                         INIT_PZVAL(params[1]);
     242               0 :                         params[2] = &param3;
     243               0 :                         INIT_PZVAL(params[2]);
     244               0 :                         ZVAL_STRINGL(params[0], buf, buf_size, 0);
     245               0 :                         ZVAL_LONG(params[1], level);
     246               0 :             if (kind == SOAP_COMPRESSION_DEFLATE) {
     247               0 :                 n = 2;
     248               0 :                                 ZVAL_STRING(&func, "gzcompress", 0);
     249               0 :                                 smart_str_append_const(&soap_headers_z,"Content-Encoding: deflate\r\n");
     250                 :             } else {
     251               0 :               n = 3;
     252               0 :                                 ZVAL_STRING(&func, "gzencode", 0);
     253               0 :                                 smart_str_append_const(&soap_headers_z,"Content-Encoding: gzip\r\n");
     254               0 :                                 ZVAL_LONG(params[2], 1);
     255                 :             }
     256               0 :                         if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, n, params TSRMLS_CC) == SUCCESS &&
     257                 :                             Z_TYPE(retval) == IS_STRING) {
     258               0 :                                 request = Z_STRVAL(retval);
     259               0 :                                 request_size = Z_STRLEN(retval);
     260                 :                         } else {
     261               0 :                                 if (request != buf) {efree(request);}
     262               0 :                                 smart_str_free(&soap_headers_z);
     263               0 :                                 return FALSE;
     264                 :                         }
     265                 :           }
     266                 :         }
     267                 : 
     268             316 :         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"), (void **)&tmp) == SUCCESS) {
     269               0 :                 php_stream_from_zval_no_verify(stream,tmp);
     270               0 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"), (void **)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_LONG) {
     271               0 :                         use_proxy = Z_LVAL_PP(tmp);
     272                 :                 }
     273                 :         } else {
     274             316 :                 stream = NULL;
     275                 :         }
     276                 : 
     277             316 :         if (location != NULL && location[0] != '\000') {
     278             316 :                 phpurl = php_url_parse(location);
     279                 :         }
     280                 : 
     281             316 :         if (SUCCESS == zend_hash_find(Z_OBJPROP_P(this_ptr),
     282                 :                         "_stream_context", sizeof("_stream_context"), (void**)&tmp)) {
     283               1 :                 context = php_stream_context_from_zval(*tmp, 0);
     284                 :         }
     285                 : 
     286             316 : try_again:
     287             316 :         if (phpurl == NULL || phpurl->host == NULL) {
     288             315 :           if (phpurl != NULL) {php_url_free(phpurl);}
     289             315 :                 if (request != buf) {efree(request);}
     290             315 :                 add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL TSRMLS_CC);
     291             315 :                 smart_str_free(&soap_headers_z);
     292             315 :                 return FALSE;
     293                 :         }
     294                 : 
     295               1 :         use_ssl = 0;
     296               1 :         if (phpurl->scheme != NULL && strcmp(phpurl->scheme, "https") == 0) {
     297               0 :                 use_ssl = 1;
     298               1 :         } else if (phpurl->scheme == NULL || strcmp(phpurl->scheme, "http") != 0) {
     299               0 :                 php_url_free(phpurl);
     300               0 :                 if (request != buf) {efree(request);}
     301               0 :                 add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL TSRMLS_CC);
     302               0 :                 smart_str_free(&soap_headers_z);
     303               0 :                 return FALSE;
     304                 :         }
     305                 : 
     306               1 :         old_allow_url_fopen = PG(allow_url_fopen);
     307               1 :         PG(allow_url_fopen) = 1;
     308               1 :         if (use_ssl && php_stream_locate_url_wrapper("https://", NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) == NULL) {
     309               0 :                 php_url_free(phpurl);
     310               0 :                 if (request != buf) {efree(request);}
     311               0 :                 add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL TSRMLS_CC);
     312               0 :                 PG(allow_url_fopen) = old_allow_url_fopen;
     313               0 :                 smart_str_free(&soap_headers_z);
     314               0 :                 return FALSE;
     315                 :         }
     316                 : 
     317               1 :         if (phpurl->port == 0) {
     318               1 :                 phpurl->port = use_ssl ? 443 : 80;
     319                 :         }
     320                 : 
     321                 :         /* Check if request to the same host */
     322               1 :         if (stream != NULL) {
     323                 :           php_url *orig;
     324               0 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl"), (void **)&tmp) == SUCCESS &&
     325                 :                     (orig = (php_url *) zend_fetch_resource(tmp TSRMLS_CC, -1, "httpurl", NULL, 1, le_url)) != NULL &&
     326                 :                     ((use_proxy && !use_ssl) ||
     327                 :                      (((use_ssl && orig->scheme != NULL && strcmp(orig->scheme, "https") == 0) ||
     328                 :                       (!use_ssl && orig->scheme == NULL) ||
     329                 :                       (!use_ssl && strcmp(orig->scheme, "https") != 0)) &&
     330                 :                      strcmp(orig->host, phpurl->host) == 0 &&
     331                 :                      orig->port == phpurl->port))) {
     332                 :     } else {
     333               0 :                         php_stream_close(stream);
     334               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl"));
     335               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
     336               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
     337               0 :                         stream = NULL;
     338               0 :                         use_proxy = 0;
     339                 :     }
     340                 :         }
     341                 : 
     342                 :         /* Check if keep-alive connection is still opened */
     343               1 :         if (stream != NULL && php_stream_eof(stream)) {
     344               0 :                 php_stream_close(stream);
     345               0 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl"));
     346               0 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
     347               0 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
     348               0 :                 stream = NULL;
     349               0 :                 use_proxy = 0;
     350                 :         }
     351                 : 
     352               1 :         if (!stream) {
     353               1 :                 stream = http_connect(this_ptr, phpurl, use_ssl, context, &use_proxy TSRMLS_CC);
     354               1 :                 if (stream) {
     355                 :                         php_stream_auto_cleanup(stream);
     356               1 :                         add_property_resource(this_ptr, "httpsocket", php_stream_get_resource_id(stream));
     357               1 :                         add_property_long(this_ptr, "_use_proxy", use_proxy);
     358                 :                 } else {
     359               0 :                         php_url_free(phpurl);
     360               0 :                         if (request != buf) {efree(request);}
     361               0 :                         add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL TSRMLS_CC);
     362               0 :                         PG(allow_url_fopen) = old_allow_url_fopen;
     363               0 :                         smart_str_free(&soap_headers_z);
     364               0 :                         return FALSE;
     365                 :                 }
     366                 :         }
     367               1 :         PG(allow_url_fopen) = old_allow_url_fopen;
     368                 : 
     369               1 :         if (stream) {
     370                 :                 zval **cookies, **login, **password;
     371               1 :           int ret = zend_list_insert(phpurl, le_url);
     372                 : 
     373               1 :                 add_property_resource(this_ptr, "httpurl", ret);
     374                 :                 /*zend_list_addref(ret);*/
     375                 : 
     376               1 :                 if (context && 
     377                 :                     php_stream_context_get_option(context, "http", "protocol_version", &tmp) == SUCCESS &&
     378                 :                     Z_TYPE_PP(tmp) == IS_DOUBLE &&
     379                 :                     Z_DVAL_PP(tmp) == 1.0) {
     380               0 :                         http_1_1 = 0;
     381                 :                 } else {
     382               1 :                         http_1_1 = 1;
     383                 :                 }
     384                 : 
     385               1 :                 smart_str_append_const(&soap_headers, "POST ");
     386               1 :                 if (use_proxy && !use_ssl) {
     387               0 :                         smart_str_appends(&soap_headers, phpurl->scheme);
     388               0 :                         smart_str_append_const(&soap_headers, "://");
     389               0 :                         smart_str_appends(&soap_headers, phpurl->host);
     390               0 :                         smart_str_appendc(&soap_headers, ':');
     391               0 :                         smart_str_append_unsigned(&soap_headers, phpurl->port);
     392                 :                 }
     393               1 :                 if (phpurl->path) {
     394               0 :                         smart_str_appends(&soap_headers, phpurl->path);
     395                 :                 } else {
     396               1 :                         smart_str_appendc(&soap_headers, '/');
     397                 :                 }
     398               1 :                 if (phpurl->query) {
     399               0 :                         smart_str_appendc(&soap_headers, '?');
     400               0 :                         smart_str_appends(&soap_headers, phpurl->query);
     401                 :                 }
     402               1 :                 if (phpurl->fragment) {
     403               0 :                         smart_str_appendc(&soap_headers, '#');
     404               0 :                         smart_str_appends(&soap_headers, phpurl->fragment);
     405                 :                 }
     406               1 :                 if (http_1_1) {
     407               1 :                         smart_str_append_const(&soap_headers, " HTTP/1.1\r\n");
     408                 :                 } else {
     409               0 :                         smart_str_append_const(&soap_headers, " HTTP/1.0\r\n");
     410                 :                 }
     411               1 :                 smart_str_append_const(&soap_headers, "Host: ");
     412               1 :                 smart_str_appends(&soap_headers, phpurl->host);
     413               1 :                 if (phpurl->port != (use_ssl?443:80)) {
     414               0 :                         smart_str_appendc(&soap_headers, ':');
     415               0 :                         smart_str_append_unsigned(&soap_headers, phpurl->port);
     416                 :                 }
     417               1 :                 if (http_1_1) {
     418               1 :                         smart_str_append_const(&soap_headers, "\r\n"
     419                 :                                 "Connection: Keep-Alive\r\n");
     420                 :                 } else {
     421               0 :                         smart_str_append_const(&soap_headers, "\r\n"
     422                 :                                 "Connection: close\r\n");
     423                 :                 }
     424               1 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_user_agent", sizeof("_user_agent"), (void **)&tmp) == SUCCESS &&
     425                 :                     Z_TYPE_PP(tmp) == IS_STRING) {
     426               0 :                         if (Z_STRLEN_PP(tmp) > 0) {
     427               0 :                                 smart_str_append_const(&soap_headers, "User-Agent: ");
     428               0 :                                 smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     429               0 :                                 smart_str_append_const(&soap_headers, "\r\n");
     430                 :                         }
     431               1 :                 } else if (context && 
     432                 :                            php_stream_context_get_option(context, "http", "user_agent", &tmp) == SUCCESS &&
     433                 :                            Z_TYPE_PP(tmp) == IS_STRING) {
     434               0 :                         if (Z_STRLEN_PP(tmp) > 0) {
     435               0 :                                 smart_str_append_const(&soap_headers, "User-Agent: ");
     436               0 :                                 smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     437               0 :                                 smart_str_append_const(&soap_headers, "\r\n");
     438                 :                         }
     439               1 :                 } else if (FG(user_agent)) {
     440               0 :                         smart_str_append_const(&soap_headers, "User-Agent: ");
     441               0 :                         smart_str_appends(&soap_headers, FG(user_agent));
     442               0 :                         smart_str_append_const(&soap_headers, "\r\n");
     443                 :                 } else {
     444               1 :                         smart_str_append_const(&soap_headers, "User-Agent: PHP-SOAP/"PHP_VERSION"\r\n");
     445                 :                 }
     446                 : 
     447               1 :                 smart_str_append(&soap_headers, &soap_headers_z);
     448                 : 
     449               1 :                 if (soap_version == SOAP_1_2) {
     450               0 :                         smart_str_append_const(&soap_headers,"Content-Type: application/soap+xml; charset=utf-8");
     451               0 :                         if (soapaction) {
     452               0 :                                 smart_str_append_const(&soap_headers,"; action=\"");
     453               0 :                                 smart_str_appends(&soap_headers, soapaction);
     454               0 :                                 smart_str_append_const(&soap_headers,"\"");
     455                 :                         }
     456               0 :                         smart_str_append_const(&soap_headers,"\r\n");
     457                 :                 } else {
     458               1 :                         smart_str_append_const(&soap_headers,"Content-Type: text/xml; charset=utf-8\r\n");
     459               1 :                         if (soapaction) {
     460               1 :                                 smart_str_append_const(&soap_headers, "SOAPAction: \"");
     461               1 :                                 smart_str_appends(&soap_headers, soapaction);
     462               1 :                                 smart_str_append_const(&soap_headers, "\"\r\n");
     463                 :                         }
     464                 :                 }
     465               1 :                 smart_str_append_const(&soap_headers,"Content-Length: ");
     466               1 :                 smart_str_append_long(&soap_headers, request_size);
     467               1 :                 smart_str_append_const(&soap_headers, "\r\n");
     468                 : 
     469                 :                 /* HTTP Authentication */
     470               1 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", sizeof("_login"), (void **)&login) == SUCCESS &&
     471                 :                     Z_TYPE_PP(login) == IS_STRING) {
     472                 :                         zval **digest;
     473                 : 
     474               0 :                         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest"), (void **)&digest) == SUCCESS) {
     475               0 :                                 if (Z_TYPE_PP(digest) == IS_ARRAY) {
     476                 :                                         char          HA1[33], HA2[33], response[33], cnonce[33], nc[9];
     477                 :                                         PHP_MD5_CTX   md5ctx;
     478                 :                                         unsigned char hash[16];
     479                 : 
     480               0 :                                         PHP_MD5Init(&md5ctx);
     481               0 :                                         snprintf(cnonce, sizeof(cnonce), "%ld", php_rand(TSRMLS_C));
     482               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)cnonce, strlen(cnonce));
     483               0 :                                         PHP_MD5Final(hash, &md5ctx);
     484               0 :                                         make_digest(cnonce, hash);
     485                 : 
     486               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "nc", sizeof("nc"), (void **)&tmp) == SUCCESS &&
     487                 :                                             Z_TYPE_PP(tmp) == IS_LONG) {
     488               0 :                                                 Z_LVAL_PP(tmp)++;
     489               0 :                                                 snprintf(nc, sizeof(nc), "%08ld", Z_LVAL_PP(tmp));
     490                 :                                         } else {
     491               0 :                                                 add_assoc_long(*digest, "nc", 1);
     492               0 :                                                 strcpy(nc, "00000001");
     493                 :                                         }
     494                 : 
     495               0 :                                         PHP_MD5Init(&md5ctx);
     496               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)Z_STRVAL_PP(login), Z_STRLEN_PP(login));
     497               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     498               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "realm", sizeof("realm"), (void **)&tmp) == SUCCESS &&
     499                 :                                             Z_TYPE_PP(tmp) == IS_STRING) {
     500               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     501                 :                                         }
     502               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     503               0 :                                         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS &&
     504                 :                                             Z_TYPE_PP(password) == IS_STRING) {
     505               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)Z_STRVAL_PP(password), Z_STRLEN_PP(password));
     506                 :                                         }
     507               0 :                                         PHP_MD5Final(hash, &md5ctx);
     508               0 :                                         make_digest(HA1, hash);
     509               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "algorithm", sizeof("algorithm"), (void **)&tmp) == SUCCESS &&
     510                 :                                             Z_TYPE_PP(tmp) == IS_STRING &&
     511                 :                                             Z_STRLEN_PP(tmp) == sizeof("md5-sess")-1 &&
     512                 :                                             stricmp(Z_STRVAL_PP(tmp), "md5-sess") == 0) {
     513               0 :                                                 PHP_MD5Init(&md5ctx);
     514               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)HA1, 32);
     515               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     516               0 :                                                 if (zend_hash_find(Z_ARRVAL_PP(digest), "nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
     517                 :                                                     Z_TYPE_PP(tmp) == IS_STRING) {
     518               0 :                                                         PHP_MD5Update(&md5ctx, (unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     519                 :                                                 }
     520               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     521               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)cnonce, 8);
     522               0 :                                                 PHP_MD5Final(hash, &md5ctx);
     523               0 :                                                 make_digest(HA1, hash);
     524                 :                                         }
     525                 : 
     526               0 :                                         PHP_MD5Init(&md5ctx);
     527               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)"POST:", sizeof("POST:")-1);
     528               0 :                                         if (phpurl->path) {
     529               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)phpurl->path, strlen(phpurl->path));
     530                 :                                         } else {
     531               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)"/", 1);
     532                 :                                         }
     533               0 :                                         if (phpurl->query) {
     534               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)"?", 1);
     535               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)phpurl->query, strlen(phpurl->query));
     536                 :                                         }
     537                 : 
     538                 :                                         /* TODO: Support for qop="auth-int" */
     539                 : /*
     540                 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
     541                 :                                             Z_TYPE_PP(tmp) == IS_STRING &&
     542                 :                                             Z_STRLEN_PP(tmp) == sizeof("auth-int")-1 &&
     543                 :                                             stricmp(Z_STRVAL_PP(tmp), "auth-int") == 0) {
     544                 :                                                 PHP_MD5Update(&md5ctx, ":", 1);
     545                 :                                                 PHP_MD5Update(&md5ctx, HEntity, HASHHEXLEN);
     546                 :                                         }
     547                 : */
     548               0 :                                         PHP_MD5Final(hash, &md5ctx);
     549               0 :                                         make_digest(HA2, hash);
     550                 : 
     551               0 :                                         PHP_MD5Init(&md5ctx);
     552               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)HA1, 32);
     553               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     554               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
     555                 :                                             Z_TYPE_PP(tmp) == IS_STRING) {
     556               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     557                 :                                         }
     558               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     559               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
     560                 :                                             Z_TYPE_PP(tmp) == IS_STRING) {
     561               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)nc, 8);
     562               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     563               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)cnonce, 8);
     564               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     565                 :                                                 /* TODO: Support for qop="auth-int" */
     566               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)"auth", sizeof("auth")-1);
     567               0 :                                                 PHP_MD5Update(&md5ctx, (unsigned char*)":", 1);
     568                 :                                         }
     569               0 :                                         PHP_MD5Update(&md5ctx, (unsigned char*)HA2, 32);
     570               0 :                                         PHP_MD5Final(hash, &md5ctx);
     571               0 :                                         make_digest(response, hash);
     572                 :         
     573               0 :                                         smart_str_append_const(&soap_headers, "Authorization: Digest username=\"");
     574               0 :                                         smart_str_appendl(&soap_headers, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
     575               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "realm", sizeof("realm"), (void **)&tmp) == SUCCESS &&
     576                 :                                             Z_TYPE_PP(tmp) == IS_STRING) {
     577               0 :                                                 smart_str_append_const(&soap_headers, "\", realm=\"");
     578               0 :                                                 smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     579                 :                                         }
     580               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "nonce", sizeof("nonce"), (void **)&tmp) == SUCCESS &&
     581                 :                                             Z_TYPE_PP(tmp) == IS_STRING) {
     582               0 :                                                 smart_str_append_const(&soap_headers, "\", nonce=\"");
     583               0 :                                                 smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     584                 :                                         }
     585               0 :                                         smart_str_append_const(&soap_headers, "\", uri=\"");
     586               0 :                                         if (phpurl->path) {
     587               0 :                                                 smart_str_appends(&soap_headers, phpurl->path);
     588                 :                                         } else {
     589               0 :                                                 smart_str_appendc(&soap_headers, '/');
     590                 :                                         } 
     591               0 :                                         if (phpurl->query) {
     592               0 :                                                 smart_str_appendc(&soap_headers, '?');
     593               0 :                                                 smart_str_appends(&soap_headers, phpurl->query);
     594                 :                                         }
     595               0 :                                         if (phpurl->fragment) {
     596               0 :                                                 smart_str_appendc(&soap_headers, '#');
     597               0 :                                                 smart_str_appends(&soap_headers, phpurl->fragment);
     598                 :                                         }
     599               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "qop", sizeof("qop"), (void **)&tmp) == SUCCESS &&
     600                 :                                             Z_TYPE_PP(tmp) == IS_STRING) {
     601                 :                                         /* TODO: Support for qop="auth-int" */
     602               0 :                                                 smart_str_append_const(&soap_headers, "\", qop=\"auth");
     603               0 :                                                 smart_str_append_const(&soap_headers, "\", nc=\"");
     604               0 :                                                 smart_str_appendl(&soap_headers, nc, 8);
     605               0 :                                                 smart_str_append_const(&soap_headers, "\", cnonce=\"");
     606               0 :                                                 smart_str_appendl(&soap_headers, cnonce, 8);
     607                 :                                         }
     608               0 :                                         smart_str_append_const(&soap_headers, "\", response=\"");
     609               0 :                                         smart_str_appendl(&soap_headers, response, 32);
     610               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "opaque", sizeof("opaque"), (void **)&tmp) == SUCCESS &&
     611                 :                                             Z_TYPE_PP(tmp) == IS_STRING) {
     612               0 :                                                 smart_str_append_const(&soap_headers, "\", opaque=\"");
     613               0 :                                                 smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     614                 :                                         }
     615               0 :                                         if (zend_hash_find(Z_ARRVAL_PP(digest), "algorithm", sizeof("algorithm"), (void **)&tmp) == SUCCESS &&
     616                 :                                                 Z_TYPE_PP(tmp) == IS_STRING) {
     617               0 :                                                 smart_str_append_const(&soap_headers, "\", algorithm=\"");
     618               0 :                                                 smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     619                 :                                         }
     620               0 :                                         smart_str_append_const(&soap_headers, "\"\r\n");
     621                 :                                 }
     622                 :                         } else {
     623                 :                                 unsigned char* buf;
     624                 :                                 int len;
     625                 : 
     626               0 :                                 smart_str auth = {0};
     627               0 :                                 smart_str_appendl(&auth, Z_STRVAL_PP(login), Z_STRLEN_PP(login));
     628               0 :                                 smart_str_appendc(&auth, ':');
     629               0 :                                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS &&
     630                 :                                     Z_TYPE_PP(password) == IS_STRING) {
     631               0 :                                         smart_str_appendl(&auth, Z_STRVAL_PP(password), Z_STRLEN_PP(password));
     632                 :                                 }
     633               0 :                                 smart_str_0(&auth);
     634               0 :                                 buf = php_base64_encode((unsigned char*)auth.c, auth.len, &len);
     635               0 :                                 smart_str_append_const(&soap_headers, "Authorization: Basic ");
     636               0 :                                 smart_str_appendl(&soap_headers, (char*)buf, len);
     637               0 :                                 smart_str_append_const(&soap_headers, "\r\n");
     638               0 :                                 efree(buf);
     639               0 :                                 smart_str_free(&auth);
     640                 :                         }
     641                 :                 }
     642                 : 
     643                 :                 /* Proxy HTTP Authentication */
     644               1 :                 if (use_proxy && !use_ssl) {
     645               0 :                         proxy_authentication(this_ptr, &soap_headers TSRMLS_CC);
     646                 :                 }
     647                 : 
     648                 :                 /* Send cookies along with request */
     649               1 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == SUCCESS) {
     650                 :                         zval **data;
     651                 :                         char *key;
     652                 :                         int i, n;
     653                 : 
     654               0 :                         n = zend_hash_num_elements(Z_ARRVAL_PP(cookies));
     655               0 :                         if (n > 0) {
     656               0 :                                 zend_hash_internal_pointer_reset(Z_ARRVAL_PP(cookies));
     657               0 :                                 smart_str_append_const(&soap_headers, "Cookie: ");
     658               0 :                                 for (i = 0; i < n; i++) {
     659               0 :                                         zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data);
     660               0 :                                         zend_hash_get_current_key(Z_ARRVAL_PP(cookies), &key, NULL, FALSE);
     661                 : 
     662               0 :                                         if (Z_TYPE_PP(data) == IS_ARRAY) {
     663                 :                                           zval** value;
     664                 : 
     665               0 :                                                 if (zend_hash_index_find(Z_ARRVAL_PP(data), 0, (void**)&value) == SUCCESS &&
     666                 :                                                     Z_TYPE_PP(value) == IS_STRING) {
     667                 :                                                   zval **tmp;
     668               0 :                                                   if ((zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == FAILURE ||
     669                 :                                                        strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0) &&
     670                 :                                                       (zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE ||
     671                 :                                                        in_domain(phpurl->host,Z_STRVAL_PP(tmp))) &&
     672                 :                                                       (use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) {
     673               0 :                                                                 smart_str_appendl(&soap_headers, key, strlen(key));
     674               0 :                                                                 smart_str_appendc(&soap_headers, '=');
     675               0 :                                                                 smart_str_appendl(&soap_headers, Z_STRVAL_PP(value), Z_STRLEN_PP(value));
     676               0 :                                                                 smart_str_appendc(&soap_headers, ';');
     677                 :                                                         }
     678                 :                                                 }
     679                 :                                         }
     680               0 :                                         zend_hash_move_forward(Z_ARRVAL_PP(cookies));
     681                 :                                 }
     682               0 :                                 smart_str_append_const(&soap_headers, "\r\n");
     683                 :                         }
     684                 :                 }
     685                 : 
     686               1 :                 if (context &&
     687                 :                         php_stream_context_get_option(context, "http", "header", &tmp) == SUCCESS &&
     688                 :                         Z_TYPE_PP(tmp) == IS_STRING && Z_STRLEN_PP(tmp)) {
     689               0 :                         char *s = Z_STRVAL_PP(tmp);
     690                 :                         char *p;
     691                 :                         int name_len;
     692                 : 
     693               0 :                         while (*s) {
     694                 :                                 /* skip leading newlines and spaces */
     695               0 :                                 while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') {
     696               0 :                                         s++;
     697                 :                                 }
     698                 :                                 /* extract header name */
     699               0 :                                 p = s;
     700               0 :                                 name_len = -1;
     701               0 :                                 while (*p) {
     702               0 :                                         if (*p == ':') {
     703               0 :                                                 if (name_len < 0) name_len = p - s;
     704               0 :                                                 break;
     705               0 :                                         } else if (*p == ' ' || *p == '\t') {
     706               0 :                                                 if (name_len < 0) name_len = p - s;
     707               0 :                                         } else if (*p == '\r' || *p == '\n') {
     708                 :                                                 break;
     709                 :                                         }
     710               0 :                                         p++;
     711                 :                                 }
     712               0 :                                 if (*p == ':') {
     713                 :                                         /* extract header value */
     714               0 :                                         while (*p && *p != '\r' && *p != '\n') {
     715               0 :                                                 p++;
     716                 :                                         }
     717                 :                                         /* skip some predefined headers */
     718               0 :                                         if ((name_len != sizeof("host")-1 ||
     719                 :                                              strncasecmp(s, "host", sizeof("host")-1) != 0) &&
     720                 :                                             (name_len != sizeof("connection")-1 ||
     721                 :                                              strncasecmp(s, "connection", sizeof("connection")-1) != 0) &&
     722                 :                                             (name_len != sizeof("user-agent")-1 ||
     723                 :                                              strncasecmp(s, "user-agent", sizeof("user-agent")-1) != 0) &&
     724                 :                                             (name_len != sizeof("content-length")-1 ||
     725                 :                                              strncasecmp(s, "content-length", sizeof("content-length")-1) != 0) &&
     726                 :                                             (name_len != sizeof("content-type")-1 ||
     727                 :                                              strncasecmp(s, "content-type", sizeof("content-type")-1) != 0) &&
     728                 :                                             (name_len != sizeof("cookie")-1 ||
     729                 :                                              strncasecmp(s, "cookie", sizeof("cookie")-1) != 0) &&
     730                 :                                             (name_len != sizeof("authorization")-1 ||
     731                 :                                              strncasecmp(s, "authorization", sizeof("authorization")-1) != 0) &&
     732                 :                                             (name_len != sizeof("proxy-authorization")-1 ||
     733                 :                                              strncasecmp(s, "proxy-authorization", sizeof("proxy-authorization")-1) != 0)) {
     734                 :                                             /* add header */
     735               0 :                                                 smart_str_appendl(&soap_headers, s, p-s);
     736               0 :                                                 smart_str_append_const(&soap_headers, "\r\n");
     737                 :                                         }
     738                 :                                 }
     739               0 :                                 s = (*p) ? (p + 1) : p;
     740                 :                         }
     741                 :                 }
     742                 : 
     743               1 :                 smart_str_append_const(&soap_headers, "\r\n");
     744               1 :                 smart_str_0(&soap_headers);
     745               1 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
     746                 :                     Z_LVAL_PP(trace) > 0) {
     747               1 :                         add_property_stringl(this_ptr, "__last_request_headers", soap_headers.c, soap_headers.len, 1);
     748                 :                 }
     749               1 :                 smart_str_appendl(&soap_headers, request, request_size);
     750               1 :                 smart_str_0(&soap_headers);
     751                 : 
     752               1 :                 err = php_stream_write(stream, soap_headers.c, soap_headers.len);
     753               1 :                 if (err != soap_headers.len) {
     754               0 :                         if (request != buf) {efree(request);}
     755               0 :                         smart_str_free(&soap_headers);
     756               0 :                         php_stream_close(stream);
     757               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "httpurl", sizeof("httpurl"));
     758               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
     759               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
     760               0 :                         add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL TSRMLS_CC);
     761               0 :                         return FALSE;
     762                 :                 }
     763               1 :                 smart_str_free(&soap_headers);
     764                 : 
     765                 :         } else {
     766               0 :                 add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL TSRMLS_CC);
     767               0 :                 smart_str_free(&soap_headers_z);
     768               0 :                 return FALSE;
     769                 :         }
     770                 : 
     771               1 :         if (!buffer) {
     772               0 :                 php_stream_close(stream);
     773               0 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
     774               0 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
     775               0 :                 smart_str_free(&soap_headers_z);
     776               0 :                 return TRUE;
     777                 :         }
     778                 : 
     779                 :         do {
     780               1 :                 if (!get_http_headers(stream, &http_headers, &http_header_size TSRMLS_CC)) {
     781               0 :                         if (http_headers) {efree(http_headers);}
     782               0 :                         if (request != buf) {efree(request);}
     783               0 :                         php_stream_close(stream);
     784               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
     785               0 :                         zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
     786               0 :                         add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL TSRMLS_CC);
     787               0 :                         smart_str_free(&soap_headers_z);
     788               0 :                         return FALSE;
     789                 :                 }
     790                 : 
     791               1 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
     792                 :                     Z_LVAL_PP(trace) > 0) {
     793               1 :                         add_property_stringl(this_ptr, "__last_response_headers", http_headers, http_header_size, 1);
     794                 :                 }
     795                 : 
     796                 :                 /* Check to see what HTTP status was sent */
     797               1 :                 http_1_1 = 0;
     798               1 :                 http_status = 0;
     799               1 :                 http_version = get_http_header_value(http_headers,"HTTP/");
     800               1 :                 if (http_version) {
     801                 :                         char *tmp;
     802                 : 
     803               1 :                         if (!strncmp(http_version,"1.1", 3)) {
     804               1 :                                 http_1_1 = 1;
     805                 :                         }
     806                 : 
     807               1 :                         tmp = strstr(http_version," ");
     808               1 :                         if (tmp != NULL) {
     809               1 :                                 tmp++;
     810               1 :                                 http_status = atoi(tmp);
     811                 :                         }
     812               1 :                         tmp = strstr(tmp," ");
     813               1 :                         if (tmp != NULL) {
     814               1 :                                 tmp++;
     815               1 :                                 if (http_msg) {
     816               0 :                                         efree(http_msg);
     817                 :                                 }
     818               1 :                                 http_msg = estrdup(tmp);
     819                 :                         }
     820               1 :                         efree(http_version);
     821                 : 
     822                 :                         /* Try and get headers again */
     823               1 :                         if (http_status == 100) {
     824               0 :                                 efree(http_headers);
     825                 :                         }
     826                 :                 }
     827               1 :         } while (http_status == 100);
     828                 : 
     829                 :         /* Grab and send back every cookie */
     830                 : 
     831                 :         /* Not going to worry about Path: because
     832                 :            we shouldn't be changing urls so path dont
     833                 :            matter too much
     834                 :         */
     835               1 :         cookie_itt = strstr(http_headers,"Set-Cookie: ");
     836               2 :         while (cookie_itt) {
     837                 :                 char *end_pos, *cookie;
     838                 :                 char *eqpos, *sempos;
     839                 :                 zval **cookies;
     840                 : 
     841               0 :                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == FAILURE) {
     842                 :                         zval *tmp_cookies;
     843               0 :                         MAKE_STD_ZVAL(tmp_cookies);
     844               0 :                         array_init(tmp_cookies);
     845               0 :                         zend_hash_update(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), &tmp_cookies, sizeof(zval *), (void **)&cookies);
     846                 :                 }
     847                 : 
     848               0 :                 end_pos = strstr(cookie_itt,"\r\n");
     849               0 :                 cookie = get_http_header_value(cookie_itt,"Set-Cookie: ");
     850                 : 
     851               0 :                 eqpos = strstr(cookie, "=");
     852               0 :                 sempos = strstr(cookie, ";");
     853               0 :                 if (eqpos != NULL && (sempos == NULL || sempos > eqpos)) {
     854               0 :                         smart_str name = {0};
     855                 :                         int cookie_len;
     856                 :                         zval *zcookie;
     857                 : 
     858               0 :                         if (sempos != NULL) {
     859               0 :                                 cookie_len = sempos-(eqpos+1);
     860                 :                         } else {
     861               0 :                                 cookie_len = strlen(cookie)-(eqpos-cookie)-1;
     862                 :                         }
     863                 : 
     864               0 :                         smart_str_appendl(&name, cookie, eqpos - cookie);
     865               0 :                         smart_str_0(&name);
     866                 : 
     867               0 :                         ALLOC_INIT_ZVAL(zcookie);
     868               0 :                         array_init(zcookie);
     869               0 :                         add_index_stringl(zcookie, 0, eqpos + 1, cookie_len, 1);
     870                 : 
     871               0 :                         if (sempos != NULL) {
     872               0 :                                 char *options = cookie + cookie_len+1;
     873               0 :                                 while (*options) {
     874               0 :                                         while (*options == ' ') {options++;}
     875               0 :                                         sempos = strstr(options, ";");
     876               0 :                                         if (strstr(options,"path=") == options) {
     877               0 :                                                 eqpos = options + sizeof("path=")-1;
     878               0 :                                                 add_index_stringl(zcookie, 1, eqpos, sempos?(sempos-eqpos):strlen(eqpos), 1);
     879               0 :                                         } else if (strstr(options,"domain=") == options) {
     880               0 :                                                 eqpos = options + sizeof("domain=")-1;
     881               0 :                                                 add_index_stringl(zcookie, 2, eqpos, sempos?(sempos-eqpos):strlen(eqpos), 1);
     882               0 :                                         } else if (strstr(options,"secure") == options) {
     883               0 :                                                 add_index_bool(zcookie, 3, 1);
     884                 :                                         }
     885               0 :                                         if (sempos != NULL) {
     886               0 :                                                 options = sempos+1;
     887                 :                                         } else {
     888               0 :                                           break;
     889                 :                                         }
     890                 :                                 }
     891                 :                         }
     892               0 :                         if (!zend_hash_index_exists(Z_ARRVAL_P(zcookie), 1)) {
     893               0 :                                 char *t = phpurl->path?phpurl->path:"/";
     894               0 :                                 char *c = strrchr(t, '/');
     895               0 :                                 if (c) {
     896               0 :                                         add_index_stringl(zcookie, 1, t, c-t, 1);
     897                 :                                 }
     898                 :                         }
     899               0 :                         if (!zend_hash_index_exists(Z_ARRVAL_P(zcookie), 2)) {
     900               0 :                                 add_index_string(zcookie, 2, phpurl->host, 1);
     901                 :                         }
     902                 : 
     903               0 :                         add_assoc_zval_ex(*cookies, name.c, name.len+1, zcookie);
     904               0 :                         smart_str_free(&name);
     905                 :                 }
     906                 : 
     907               0 :                 cookie_itt = strstr(cookie_itt + sizeof("Set-Cookie: "), "Set-Cookie: ");
     908               0 :                 efree(cookie);
     909                 :         }
     910                 : 
     911                 :         /* See if the server requested a close */
     912               1 :         if (http_1_1) {
     913               1 :                 http_close = FALSE;
     914               1 :                 if (use_proxy && !use_ssl) {
     915               0 :                         connection = get_http_header_value(http_headers,"Proxy-Connection: ");
     916               0 :                         if (connection) {
     917               0 :                                 if (strncasecmp(connection, "close", sizeof("close")-1) == 0) {
     918               0 :                                         http_close = TRUE;
     919                 :                                 }
     920               0 :                                 efree(connection);
     921                 :                         }
     922                 :                 }
     923               1 :                 if (http_close == FALSE) {
     924               1 :                         connection = get_http_header_value(http_headers,"Connection: ");
     925               1 :                         if (connection) {
     926               1 :                                 if (strncasecmp(connection, "close", sizeof("close")-1) == 0) {
     927               1 :                                         http_close = TRUE;
     928                 :                                 }
     929               1 :                                 efree(connection);
     930                 :                         }
     931                 :                 }
     932                 :         } else {
     933               0 :                 http_close = TRUE;
     934               0 :                 if (use_proxy && !use_ssl) {
     935               0 :                         connection = get_http_header_value(http_headers,"Proxy-Connection: ");
     936               0 :                         if (connection) {
     937               0 :                                 if (strncasecmp(connection, "Keep-Alive", sizeof("Keep-Alive")-1) == 0) {
     938               0 :                                         http_close = FALSE;
     939                 :                                 }
     940               0 :                                 efree(connection);
     941                 :                         }
     942                 :                 }
     943               0 :                 if (http_close == TRUE) {
     944               0 :                         connection = get_http_header_value(http_headers,"Connection: ");
     945               0 :                         if (connection) {
     946               0 :                                 if (strncasecmp(connection, "Keep-Alive", sizeof("Keep-Alive")-1) == 0) {
     947               0 :                                         http_close = FALSE;
     948                 :                                 }
     949               0 :                                 efree(connection);
     950                 :                         }
     951                 :                 }
     952                 :         }       
     953                 : 
     954               1 :         if (!get_http_body(stream, http_close, http_headers, &http_body, &http_body_size TSRMLS_CC)) {
     955               0 :                 if (request != buf) {efree(request);}
     956               0 :                 php_stream_close(stream);
     957               0 :                 efree(http_headers);
     958               0 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
     959               0 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
     960               0 :                 add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL TSRMLS_CC);
     961               0 :                 if (http_msg) {
     962               0 :                         efree(http_msg);
     963                 :                 }
     964               0 :                 smart_str_free(&soap_headers_z);
     965               0 :                 return FALSE;
     966                 :         }
     967                 : 
     968               1 :         if (request != buf) {efree(request);}
     969                 : 
     970               1 :         if (http_close) {
     971               1 :                 php_stream_close(stream);
     972               1 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "httpsocket", sizeof("httpsocket"));
     973               1 :                 zend_hash_del(Z_OBJPROP_P(this_ptr), "_use_proxy", sizeof("_use_proxy"));
     974               1 :                 stream = NULL;
     975                 :         }
     976                 : 
     977                 :         /* Process HTTP status codes */
     978               1 :         if (http_status >= 300 && http_status < 400) {
     979                 :                 char *loc;
     980                 : 
     981               0 :                 if ((loc = get_http_header_value(http_headers,"Location: ")) != NULL) {
     982               0 :                         php_url *new_url  = php_url_parse(loc);
     983                 : 
     984               0 :                         if (new_url != NULL) {
     985               0 :                                 efree(http_headers);
     986               0 :                                 efree(http_body);
     987               0 :                                 efree(loc);
     988               0 :                                 if (new_url->scheme == NULL && new_url->path != NULL) {
     989               0 :                                         new_url->scheme = phpurl->scheme ? estrdup(phpurl->scheme) : NULL;
     990               0 :                                         new_url->host = phpurl->host ? estrdup(phpurl->host) : NULL;
     991               0 :                                         new_url->port = phpurl->port;
     992               0 :                                         if (new_url->path && new_url->path[0] != '/') {
     993               0 :                                                 char *t = phpurl->path;
     994               0 :                                                 char *p = strrchr(t, '/');
     995               0 :                                                 if (p) {
     996               0 :                                                         char *s = emalloc((p - t) + strlen(new_url->path) + 2);
     997               0 :                                                         strncpy(s, t, (p - t) + 1);
     998               0 :                                                         s[(p - t) + 1] = 0;
     999               0 :                                                         strcat(s, new_url->path);
    1000               0 :                                                         efree(new_url->path);
    1001               0 :                                                         new_url->path = s;
    1002                 :                                                 }
    1003                 :                                         }
    1004                 :                                 }
    1005               0 :                                 phpurl = new_url;
    1006                 : 
    1007               0 :                                 goto try_again;
    1008                 :                         }
    1009                 :                 }
    1010               1 :         } else if (http_status == 401) {
    1011                 :                 /* Digest authentication */
    1012                 :                 zval **digest, **login, **password;
    1013               0 :                 char *auth = get_http_header_value(http_headers, "WWW-Authenticate: ");
    1014                 : 
    1015               0 :                 if (auth &&
    1016                 :                                 strstr(auth, "Digest") == auth &&
    1017                 :                     (zend_hash_find(Z_OBJPROP_P(this_ptr), "_digest", sizeof("_digest"), (void **)&digest) == FAILURE ||
    1018                 :                      Z_TYPE_PP(digest) != IS_ARRAY) &&
    1019                 :                     zend_hash_find(Z_OBJPROP_P(this_ptr), "_login", sizeof("_login"), (void **)&login) == SUCCESS &&
    1020                 :                     Z_TYPE_PP(login) == IS_STRING &&
    1021                 :                     zend_hash_find(Z_OBJPROP_P(this_ptr), "_password", sizeof("_password"), (void **)&password) == SUCCESS &&
    1022                 :                     Z_TYPE_PP(password) == IS_STRING) {
    1023                 :                         char *s;
    1024               0 :                         zval *digest = NULL;
    1025                 : 
    1026               0 :                         s = auth + sizeof("Digest")-1;
    1027               0 :                         while (*s != '\0') {
    1028                 :                                 char *name, *val;
    1029               0 :                                 while (*s == ' ') ++s;
    1030               0 :                                 name = s;
    1031               0 :                                 while (*s != '\0' && *s != '=') ++s;
    1032               0 :                                 if (*s == '=') {
    1033               0 :                                         *s = '\0';
    1034               0 :                                         ++s;
    1035               0 :                                         if (*s == '"') {
    1036               0 :                                                 ++s;
    1037               0 :                                                 val = s;
    1038               0 :                                                 while (*s != '\0' && *s != '"') ++s;
    1039                 :                                         } else {
    1040               0 :                                                 val = s;
    1041               0 :                                                 while (*s != '\0' && *s != ' ' && *s != ',') ++s;
    1042                 :                                         }
    1043               0 :                                         if (*s != '\0') {
    1044               0 :                                                 if (*s != ',') {
    1045               0 :                                                         *s = '\0';
    1046               0 :                                                         ++s;
    1047               0 :                                                         while (*s != '\0' && *s != ',') ++s;
    1048               0 :                                                         if (*s != '\0') ++s;
    1049                 :                                                 } else {
    1050               0 :                                                         *s = '\0';
    1051               0 :                                                         ++s;
    1052                 :                                                 }
    1053                 :                                         }
    1054               0 :                                         if (digest == NULL) {
    1055               0 :                                                 ALLOC_INIT_ZVAL(digest);
    1056               0 :                                                 array_init(digest);
    1057                 :                                         }
    1058               0 :                                         add_assoc_string(digest, name, val ,1);
    1059                 :                                 }
    1060                 :                         }
    1061                 : 
    1062               0 :                         if (digest != NULL) {
    1063               0 :                                 php_url *new_url  = emalloc(sizeof(php_url));
    1064                 : 
    1065               0 :                                 Z_DELREF_P(digest);
    1066               0 :                                 add_property_zval_ex(this_ptr, "_digest", sizeof("_digest"), digest TSRMLS_CC);
    1067                 : 
    1068               0 :                                 *new_url = *phpurl;
    1069               0 :                                 if (phpurl->scheme) phpurl->scheme = estrdup(phpurl->scheme);
    1070               0 :                                 if (phpurl->user) phpurl->user = estrdup(phpurl->user);
    1071               0 :                                 if (phpurl->pass) phpurl->pass = estrdup(phpurl->pass);
    1072               0 :                                 if (phpurl->host) phpurl->host = estrdup(phpurl->host);
    1073               0 :                                 if (phpurl->path) phpurl->path = estrdup(phpurl->path);
    1074               0 :                                 if (phpurl->query) phpurl->query = estrdup(phpurl->query);
    1075               0 :                                 if (phpurl->fragment) phpurl->fragment = estrdup(phpurl->fragment);
    1076               0 :                                 phpurl = new_url;
    1077                 : 
    1078               0 :                                 efree(auth);
    1079               0 :                                 efree(http_headers);
    1080               0 :                                 efree(http_body);
    1081                 : 
    1082               0 :                                 goto try_again;
    1083                 :                         }
    1084                 :                 }
    1085               0 :                 if (auth) efree(auth);
    1086                 :         }
    1087               1 :         smart_str_free(&soap_headers_z);
    1088                 : 
    1089                 :         /* Check and see if the server even sent a xml document */
    1090               1 :         content_type = get_http_header_value(http_headers,"Content-Type: ");
    1091               1 :         if (content_type) {
    1092               1 :                 char *pos = NULL;
    1093                 :                 int cmplen;
    1094               1 :                 pos = strstr(content_type,";");
    1095               1 :                 if (pos != NULL) {
    1096               1 :                         cmplen = pos - content_type;
    1097                 :                 } else {
    1098               0 :                         cmplen = strlen(content_type);
    1099                 :                 }
    1100               1 :                 if (strncmp(content_type, "text/xml", cmplen) == 0 ||
    1101                 :                     strncmp(content_type, "application/soap+xml", cmplen) == 0) {
    1102               0 :                         content_type_xml = 1;
    1103                 : /*
    1104                 :                         if (strncmp(http_body, "<?xml", 5)) {
    1105                 :                                 zval *err;
    1106                 :                                 MAKE_STD_ZVAL(err);
    1107                 :                                 ZVAL_STRINGL(err, http_body, http_body_size, 1);
    1108                 :                                 add_soap_fault(this_ptr, "HTTP", "Didn't recieve an xml document", NULL, err TSRMLS_CC);
    1109                 :                                 efree(content_type);
    1110                 :                                 efree(http_headers);
    1111                 :                                 efree(http_body);
    1112                 :                                 return FALSE;
    1113                 :                         }
    1114                 : */
    1115                 :                 }
    1116               1 :                 efree(content_type);
    1117                 :         }
    1118                 : 
    1119                 :         /* Decompress response */
    1120               1 :         content_encoding = get_http_header_value(http_headers,"Content-Encoding: ");
    1121               1 :         if (content_encoding) {
    1122                 :                 zval func;
    1123                 :                 zval retval;
    1124                 :           zval param;
    1125                 :                 zval *params[1];
    1126                 : 
    1127               0 :                 if ((strcmp(content_encoding,"gzip") == 0 ||
    1128                 :                      strcmp(content_encoding,"x-gzip") == 0) &&
    1129                 :                      zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate"))) {
    1130               0 :                         ZVAL_STRING(&func, "gzinflate", 0);
    1131               0 :                         params[0] = &param;
    1132               0 :                         ZVAL_STRINGL(params[0], http_body+10, http_body_size-10, 0);
    1133               0 :                         INIT_PZVAL(params[0]);
    1134               0 :                 } else if (strcmp(content_encoding,"deflate") == 0 &&
    1135                 :                            zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) {
    1136               0 :                         ZVAL_STRING(&func, "gzuncompress", 0);
    1137               0 :                         params[0] = &param;
    1138               0 :                         ZVAL_STRINGL(params[0], http_body, http_body_size, 0);
    1139               0 :                         INIT_PZVAL(params[0]);
    1140                 :                 } else {
    1141               0 :                         efree(content_encoding);
    1142               0 :                         efree(http_headers);
    1143               0 :                         efree(http_body);
    1144               0 :                         if (http_msg) {
    1145               0 :                                 efree(http_msg);
    1146                 :                         }
    1147               0 :                         add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL TSRMLS_CC);
    1148               0 :                         return FALSE;
    1149                 :                 }
    1150               0 :                 if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS &&
    1151                 :                     Z_TYPE(retval) == IS_STRING) {
    1152               0 :                         efree(http_body);
    1153               0 :                         *buffer = Z_STRVAL(retval);
    1154               0 :                         *buffer_len = Z_STRLEN(retval);
    1155                 :                 } else {
    1156               0 :                         efree(content_encoding);
    1157               0 :                         efree(http_headers);
    1158               0 :                         efree(http_body);
    1159               0 :                         add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL TSRMLS_CC);
    1160               0 :                         if (http_msg) {
    1161               0 :                                 efree(http_msg);
    1162                 :                         }
    1163               0 :                         return FALSE;
    1164                 :                 }
    1165               0 :                 efree(content_encoding);
    1166                 :         } else {
    1167               1 :                 *buffer = http_body;
    1168               1 :                 *buffer_len = http_body_size;
    1169                 :         }
    1170                 : 
    1171               1 :         efree(http_headers);
    1172                 : 
    1173               1 :         if (http_status >= 400) {
    1174               0 :                 int error = 0;
    1175                 : 
    1176               0 :                 if (*buffer_len == 0) {
    1177               0 :                         error = 1;
    1178               0 :                 } else if (*buffer_len > 0) {
    1179               0 :                         if (!content_type_xml) {
    1180               0 :                                 char *s = *buffer;
    1181                 : 
    1182               0 :                                 while (*s != '\0' && *s < ' ') {
    1183               0 :                                         s++;
    1184                 :                                 }
    1185               0 :                                 if (strncmp(s, "<?xml", 5)) {
    1186               0 :                                         error = 1;
    1187                 :                                 }
    1188                 :                         }
    1189                 :                 }
    1190                 : 
    1191               0 :                 if (error) {
    1192               0 :                         efree(*buffer);
    1193               0 :                         add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL TSRMLS_CC);
    1194               0 :                         efree(http_msg);
    1195               0 :                         return FALSE;
    1196                 :                 }
    1197                 :         }
    1198                 : 
    1199               1 :         if (http_msg) {
    1200               1 :                 efree(http_msg);
    1201                 :         }
    1202                 : 
    1203               1 :         return TRUE;
    1204                 : }
    1205                 : 
    1206                 : static char *get_http_header_value(char *headers, char *type)
    1207               6 : {
    1208               6 :         char *pos, *tmp = NULL;
    1209                 :         int typelen, headerslen;
    1210                 : 
    1211               6 :         typelen = strlen(type);
    1212               6 :         headerslen = strlen(headers);
    1213                 : 
    1214                 :         /* header `titles' can be lower case, or any case combination, according
    1215                 :          * to the various RFC's. */
    1216               6 :         pos = headers;
    1217                 :         do {
    1218                 :                 /* start of buffer or start of line */
    1219              35 :                 if (strncasecmp(pos, type, typelen) == 0) {
    1220                 :                         char *eol;
    1221                 : 
    1222                 :                         /* match */
    1223               4 :                         tmp = pos + typelen;
    1224               4 :                         eol = strchr(tmp, '\n');
    1225               4 :                         if (eol == NULL) {
    1226               0 :                                 eol = headers + headerslen;
    1227               4 :                         } else if (eol > tmp && *(eol-1) == '\r') {
    1228               4 :                                 eol--;
    1229                 :                         }
    1230               4 :                         return estrndup(tmp, eol - tmp);
    1231                 :                 }
    1232                 : 
    1233                 :                 /* find next line */
    1234              31 :                 pos = strchr(pos, '\n');
    1235              31 :                 if (pos) {
    1236              29 :                         pos++;
    1237                 :                 }
    1238                 : 
    1239              31 :         } while (pos);
    1240                 : 
    1241               2 :         return NULL;
    1242                 : }
    1243                 : 
    1244                 : static int get_http_body(php_stream *stream, int close, char *headers,  char **response, int *out_size TSRMLS_DC)
    1245               1 : {
    1246               1 :         char *header, *http_buf = NULL;
    1247               1 :         int header_close = close, header_chunked = 0, header_length = 0, http_buf_size = 0;
    1248                 : 
    1249               1 :         if (!close) {
    1250               0 :                 header = get_http_header_value(headers, "Connection: ");
    1251               0 :                 if (header) {
    1252               0 :                         if(!strncasecmp(header, "close", sizeof("close")-1)) header_close = 1;
    1253               0 :                         efree(header);
    1254                 :                 }
    1255                 :         }
    1256               1 :         header = get_http_header_value(headers, "Transfer-Encoding: ");
    1257               1 :         if (header) {
    1258               0 :                 if(!strncasecmp(header, "chunked", sizeof("chunked")-1)) header_chunked = 1;
    1259               0 :                 efree(header);
    1260                 :         }
    1261               1 :         header = get_http_header_value(headers, "Content-Length: ");
    1262               1 :         if (header) {
    1263               1 :                 header_length = atoi(header);
    1264               1 :                 efree(header);
    1265               1 :                 if (!header_length && !header_chunked) {
    1266                 :                         /* Empty response */
    1267               0 :                         http_buf = emalloc(1);
    1268               0 :                         http_buf[0] = '\0';
    1269               0 :                         (*response) = http_buf;
    1270               0 :                         (*out_size) = 0;
    1271               0 :                         return TRUE;
    1272                 :                 }
    1273                 :         }
    1274                 : 
    1275               1 :         if (header_chunked) {
    1276                 :                 char ch, done, chunk_size[10], headerbuf[8192];
    1277                 : 
    1278               0 :                 done = FALSE;
    1279                 : 
    1280               0 :                 while (!done) {
    1281               0 :                         int buf_size = 0;
    1282                 : 
    1283               0 :                         php_stream_gets(stream, chunk_size, sizeof(chunk_size));
    1284               0 :                         if (sscanf(chunk_size, "%x", &buf_size) > 0 ) {
    1285               0 :                                 if (buf_size > 0) {
    1286               0 :                                         int len_size = 0;
    1287                 : 
    1288               0 :                                         if (http_buf_size + buf_size + 1 < 0) {
    1289               0 :                                                 efree(http_buf);
    1290               0 :                                                 return FALSE;
    1291                 :                                         }
    1292               0 :                                         http_buf = erealloc(http_buf, http_buf_size + buf_size + 1);
    1293                 : 
    1294               0 :                                         while (len_size < buf_size) {
    1295               0 :                                                 int len_read = php_stream_read(stream, http_buf + http_buf_size, buf_size - len_size);
    1296               0 :                                                 if (len_read <= 0) {
    1297                 :                                                         /* Error or EOF */
    1298               0 :                                                         done = TRUE;
    1299               0 :                                                   break;
    1300                 :                                                 }
    1301               0 :                                                 len_size += len_read;
    1302               0 :                                                 http_buf_size += len_read;
    1303                 :                                         }
    1304                 : 
    1305                 :                                         /* Eat up '\r' '\n' */
    1306               0 :                                         ch = php_stream_getc(stream);
    1307               0 :                                         if (ch == '\r') {
    1308               0 :                                                 ch = php_stream_getc(stream);
    1309                 :                                         }
    1310               0 :                                         if (ch != '\n') {
    1311                 :                                                 /* Somthing wrong in chunked encoding */
    1312               0 :                                                 if (http_buf) {
    1313               0 :                                                         efree(http_buf);
    1314                 :                                                 }
    1315               0 :                                                 return FALSE;
    1316                 :                                         }
    1317                 :                                 }
    1318                 :                         } else {
    1319                 :                                 /* Somthing wrong in chunked encoding */
    1320               0 :                                 if (http_buf) {
    1321               0 :                                         efree(http_buf);
    1322                 :                                 }
    1323               0 :                                 return FALSE;
    1324                 :                         }
    1325               0 :                         if (buf_size == 0) {
    1326               0 :                                 done = TRUE;
    1327                 :                         }
    1328                 :                 }
    1329                 : 
    1330                 :                 /* Ignore trailer headers */
    1331                 :                 while (1) {
    1332               0 :                         if (!php_stream_gets(stream, headerbuf, sizeof(headerbuf))) {
    1333               0 :                                 break;
    1334                 :                         }
    1335                 : 
    1336               0 :                         if ((headerbuf[0] == '\r' && headerbuf[1] == '\n') ||
    1337                 :                             (headerbuf[0] == '\n')) {
    1338                 :                                 /* empty line marks end of headers */
    1339                 :                                 break;
    1340                 :                         }
    1341               0 :                 }
    1342                 : 
    1343               0 :                 if (http_buf == NULL) {
    1344               0 :                         http_buf = emalloc(1);
    1345                 :                 }
    1346                 : 
    1347               1 :         } else if (header_length) {
    1348               1 :                 if (header_length < 0) {
    1349               0 :                         return FALSE;
    1350                 :                 }
    1351               1 :                 http_buf = emalloc(header_length + 1);
    1352               3 :                 while (http_buf_size < header_length) {
    1353               1 :                         int len_read = php_stream_read(stream, http_buf + http_buf_size, header_length - http_buf_size);
    1354               1 :                         if (len_read <= 0) {
    1355               0 :                                 break;
    1356                 :                         }
    1357               1 :                         http_buf_size += len_read;
    1358                 :                 }
    1359               0 :         } else if (header_close) {
    1360                 :                 do {
    1361                 :                         int len_read;
    1362               0 :                         http_buf = erealloc(http_buf, http_buf_size + 4096 + 1);
    1363               0 :                         len_read = php_stream_read(stream, http_buf + http_buf_size, 4096);
    1364               0 :                         if (len_read > 0) {
    1365               0 :                                 http_buf_size += len_read;
    1366                 :                         }
    1367               0 :                 } while(!php_stream_eof(stream));
    1368                 :         } else {
    1369               0 :                 return FALSE;
    1370                 :         }
    1371                 : 
    1372               1 :         http_buf[http_buf_size] = '\0';
    1373               1 :         (*response) = http_buf;
    1374               1 :         (*out_size) = http_buf_size;
    1375               1 :         return TRUE;
    1376                 : }
    1377                 : 
    1378                 : static int get_http_headers(php_stream *stream, char **response, int *out_size TSRMLS_DC)
    1379               1 : {
    1380               1 :         int done = FALSE;
    1381               1 :         smart_str tmp_response = {0};
    1382                 :         char headerbuf[8192];
    1383                 : 
    1384               9 :         while (!done) {
    1385               8 :                 if (!php_stream_gets(stream, headerbuf, sizeof(headerbuf))) {
    1386               0 :                         break;
    1387                 :                 }
    1388                 : 
    1389               8 :                 if ((headerbuf[0] == '\r' && headerbuf[1] == '\n') ||
    1390                 :                     (headerbuf[0] == '\n')) {
    1391                 :                         /* empty line marks end of headers */
    1392               1 :                         done = TRUE;
    1393               1 :                         break;
    1394                 :                 }
    1395                 : 
    1396                 :                 /* add header to collection */
    1397               7 :                 smart_str_appends(&tmp_response, headerbuf);
    1398                 :         }
    1399               1 :         smart_str_0(&tmp_response);
    1400               1 :         (*response) = tmp_response.c;
    1401               1 :         (*out_size) = tmp_response.len;
    1402               1 :         return done;
    1403                 : }
    1404                 : /*
    1405                 :  * Local variables:
    1406                 :  * tab-width: 4
    1407                 :  * c-basic-offset: 4
    1408                 :  * End:
    1409                 :  * vim600: sw=4 ts=4 fdm=marker
    1410                 :  * vim<600: sw=4 ts=4
    1411                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:08 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.