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

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

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