Annotation of embedaddon/php/ext/soap/php_http.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>