root/ext/soap/php_http.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. proxy_authentication
  2. basic_authentication
  3. http_context_headers
  4. http_connect
  5. in_domain
  6. make_http_soap_request
  7. get_http_header_value
  8. get_http_body
  9. get_http_headers

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

/* [<][>][^][v][top][bottom][index][help] */