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

LCOV - code coverage report
Current view: top level - ext/soap - php_http.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 230 893 25.8 %
Date: 2015-03-22 Functions: 7 9 77.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 22 Mar 2015 22:19:58 +0000 (4 days ago)

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