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: 223 761 29.3 %
Date: 2016-05-22 Functions: 7 9 77.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 22 May 2016 10:53:03 +0000 (3 days ago)

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