Annotation of embedaddon/php/ext/standard/http_fopen_wrapper.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
        !            16:    |          Jim Winstead <jimw@php.net>                                 |
        !            17:    |          Hartmut Holzgraefe <hholzgra@php.net>                       |
        !            18:    |          Wez Furlong <wez@thebrainroom.com>                          |
        !            19:    |          Sara Golemon <pollita@php.net>                              |
        !            20:    +----------------------------------------------------------------------+
        !            21:  */
        !            22: /* $Id: http_fopen_wrapper.c 321634 2012-01-01 13:15:04Z felipe $ */ 
        !            23: 
        !            24: #include "php.h"
        !            25: #include "php_globals.h"
        !            26: #include "php_streams.h"
        !            27: #include "php_network.h"
        !            28: #include "php_ini.h"
        !            29: #include "ext/standard/basic_functions.h"
        !            30: #include "ext/standard/php_smart_str.h"
        !            31: 
        !            32: #include <stdio.h>
        !            33: #include <stdlib.h>
        !            34: #include <errno.h>
        !            35: #include <sys/types.h>
        !            36: #include <sys/stat.h>
        !            37: #include <fcntl.h>
        !            38: 
        !            39: #ifdef PHP_WIN32
        !            40: #define O_RDONLY _O_RDONLY
        !            41: #include "win32/param.h"
        !            42: #else
        !            43: #include <sys/param.h>
        !            44: #endif
        !            45: 
        !            46: #include "php_standard.h"
        !            47: 
        !            48: #include <sys/types.h>
        !            49: #if HAVE_SYS_SOCKET_H
        !            50: #include <sys/socket.h>
        !            51: #endif
        !            52: 
        !            53: #ifdef PHP_WIN32
        !            54: #include <winsock2.h>
        !            55: #elif defined(NETWARE) && defined(USE_WINSOCK)
        !            56: #include <novsock2.h>
        !            57: #else
        !            58: #include <netinet/in.h>
        !            59: #include <netdb.h>
        !            60: #if HAVE_ARPA_INET_H
        !            61: #include <arpa/inet.h>
        !            62: #endif
        !            63: #endif
        !            64: 
        !            65: #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
        !            66: #undef AF_UNIX
        !            67: #endif
        !            68: 
        !            69: #if defined(AF_UNIX)
        !            70: #include <sys/un.h>
        !            71: #endif
        !            72: 
        !            73: #include "php_fopen_wrappers.h"
        !            74: 
        !            75: #define HTTP_HEADER_BLOCK_SIZE         1024
        !            76: #define PHP_URL_REDIRECT_MAX           20
        !            77: #define HTTP_HEADER_USER_AGENT         1
        !            78: #define HTTP_HEADER_HOST                       2
        !            79: #define HTTP_HEADER_AUTH                       4
        !            80: #define HTTP_HEADER_FROM                       8
        !            81: #define HTTP_HEADER_CONTENT_LENGTH     16
        !            82: #define HTTP_HEADER_TYPE                       32
        !            83: 
        !            84: #define HTTP_WRAPPER_HEADER_INIT    1
        !            85: #define HTTP_WRAPPER_REDIRECTED     2
        !            86: 
        !            87: php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context, int redirect_max, int flags STREAMS_DC TSRMLS_DC) /* {{{ */
        !            88: {
        !            89:        php_stream *stream = NULL;
        !            90:        php_url *resource = NULL;
        !            91:        int use_ssl;
        !            92:        int use_proxy = 0;
        !            93:        char *scratch = NULL;
        !            94:        char *tmp = NULL;
        !            95:        char *ua_str = NULL;
        !            96:        zval **ua_zval = NULL, **tmpzval = NULL;
        !            97:        int scratch_len = 0;
        !            98:        int body = 0;
        !            99:        char location[HTTP_HEADER_BLOCK_SIZE];
        !           100:        zval *response_header = NULL;
        !           101:        int reqok = 0;
        !           102:        char *http_header_line = NULL;
        !           103:        char tmp_line[128];
        !           104:        size_t chunk_size = 0, file_size = 0;
        !           105:        int eol_detect = 0;
        !           106:        char *transport_string, *errstr = NULL;
        !           107:        int transport_len, have_header = 0, request_fulluri = 0, ignore_errors = 0;
        !           108:        char *protocol_version = NULL;
        !           109:        int protocol_version_len = 3; /* Default: "1.0" */
        !           110:        struct timeval timeout;
        !           111:        char *user_headers = NULL;
        !           112:        int header_init = ((flags & HTTP_WRAPPER_HEADER_INIT) != 0);
        !           113:        int redirected = ((flags & HTTP_WRAPPER_REDIRECTED) != 0);
        !           114:        int follow_location = 1;
        !           115:        php_stream_filter *transfer_encoding = NULL;
        !           116: 
        !           117:        tmp_line[0] = '\0';
        !           118: 
        !           119:        if (redirect_max < 1) {
        !           120:                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Redirection limit reached, aborting");
        !           121:                return NULL;
        !           122:        }
        !           123: 
        !           124:        resource = php_url_parse(path);
        !           125:        if (resource == NULL) {
        !           126:                return NULL;
        !           127:        }
        !           128: 
        !           129:        if (strncasecmp(resource->scheme, "http", sizeof("http")) && strncasecmp(resource->scheme, "https", sizeof("https"))) {
        !           130:                if (!context || 
        !           131:                        php_stream_context_get_option(context, wrapper->wops->label, "proxy", &tmpzval) == FAILURE ||
        !           132:                        Z_TYPE_PP(tmpzval) != IS_STRING ||
        !           133:                        Z_STRLEN_PP(tmpzval) <= 0) {
        !           134:                        php_url_free(resource);
        !           135:                        return php_stream_open_wrapper_ex(path, mode, ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
        !           136:                }
        !           137:                /* Called from a non-http wrapper with http proxying requested (i.e. ftp) */
        !           138:                request_fulluri = 1;
        !           139:                use_ssl = 0;
        !           140:                use_proxy = 1;
        !           141: 
        !           142:                transport_len = Z_STRLEN_PP(tmpzval);
        !           143:                transport_string = estrndup(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
        !           144:        } else {
        !           145:                /* Normal http request (possibly with proxy) */
        !           146:        
        !           147:                if (strpbrk(mode, "awx+")) {
        !           148:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP wrapper does not support writeable connections");
        !           149:                        php_url_free(resource);
        !           150:                        return NULL;
        !           151:                }
        !           152: 
        !           153:                use_ssl = resource->scheme && (strlen(resource->scheme) > 4) && resource->scheme[4] == 's';
        !           154:                /* choose default ports */
        !           155:                if (use_ssl && resource->port == 0)
        !           156:                        resource->port = 443;
        !           157:                else if (resource->port == 0)
        !           158:                        resource->port = 80;
        !           159: 
        !           160:                if (context &&
        !           161:                        php_stream_context_get_option(context, wrapper->wops->label, "proxy", &tmpzval) == SUCCESS &&
        !           162:                        Z_TYPE_PP(tmpzval) == IS_STRING &&
        !           163:                        Z_STRLEN_PP(tmpzval) > 0) {
        !           164:                        use_proxy = 1;
        !           165:                        transport_len = Z_STRLEN_PP(tmpzval);
        !           166:                        transport_string = estrndup(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
        !           167:                } else {
        !           168:                        transport_len = spprintf(&transport_string, 0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", resource->host, resource->port);
        !           169:                }
        !           170:        }
        !           171: 
        !           172:        if (context && php_stream_context_get_option(context, wrapper->wops->label, "timeout", &tmpzval) == SUCCESS) {
        !           173:                SEPARATE_ZVAL(tmpzval);
        !           174:                convert_to_double_ex(tmpzval);
        !           175:                timeout.tv_sec = (time_t) Z_DVAL_PP(tmpzval);
        !           176:                timeout.tv_usec = (size_t) ((Z_DVAL_PP(tmpzval) - timeout.tv_sec) * 1000000);
        !           177:        } else {
        !           178:                timeout.tv_sec = FG(default_socket_timeout);
        !           179:                timeout.tv_usec = 0;
        !           180:        }
        !           181: 
        !           182:        stream = php_stream_xport_create(transport_string, transport_len, options,
        !           183:                        STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT,
        !           184:                        NULL, &timeout, context, &errstr, NULL);
        !           185:     
        !           186:        if (stream) {
        !           187:                php_stream_set_option(stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &timeout);
        !           188:        }
        !           189:                        
        !           190:        if (errstr) {
        !           191:                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "%s", errstr);
        !           192:                efree(errstr);
        !           193:                errstr = NULL;
        !           194:        }
        !           195: 
        !           196:        efree(transport_string);
        !           197: 
        !           198:        if (stream && use_proxy && use_ssl) {
        !           199:                smart_str header = {0};
        !           200: 
        !           201:                smart_str_appendl(&header, "CONNECT ", sizeof("CONNECT ")-1);
        !           202:                smart_str_appends(&header, resource->host);
        !           203:                smart_str_appendc(&header, ':');
        !           204:                smart_str_append_unsigned(&header, resource->port);
        !           205:                smart_str_appendl(&header, " HTTP/1.0\r\n", sizeof(" HTTP/1.0\r\n")-1);
        !           206: 
        !           207:            /* check if we have Proxy-Authorization header */
        !           208:                if (context && php_stream_context_get_option(context, "http", "header", &tmpzval) == SUCCESS) {
        !           209:                        char *s, *p;
        !           210: 
        !           211:                        if (Z_TYPE_PP(tmpzval) == IS_ARRAY) {
        !           212:                                HashPosition pos;
        !           213:                                zval **tmpheader = NULL;
        !           214: 
        !           215:                                for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(tmpzval), &pos);
        !           216:                                        SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(tmpzval), (void *)&tmpheader, &pos);
        !           217:                                        zend_hash_move_forward_ex(Z_ARRVAL_PP(tmpzval), &pos)) {
        !           218:                                        if (Z_TYPE_PP(tmpheader) == IS_STRING) {
        !           219:                                                s = Z_STRVAL_PP(tmpheader);
        !           220:                                                do {
        !           221:                                                        while (*s == ' ' || *s == '\t') s++;
        !           222:                                                        p = s;
        !           223:                                                        while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++;
        !           224:                                                        if (*p == ':') {
        !           225:                                                                p++;
        !           226:                                                                if (p - s == sizeof("Proxy-Authorization:") - 1 &&
        !           227:                                                                    zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1,
        !           228:                                                                        "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) {
        !           229:                                                                        while (*p != 0 && *p != '\r' && *p !='\n') p++;
        !           230:                                                                        smart_str_appendl(&header, s, p - s);
        !           231:                                                                        smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);
        !           232:                                                                        goto finish;
        !           233:                                                                } else {
        !           234:                                                                        while (*p != 0 && *p != '\r' && *p !='\n') p++;
        !           235:                                                                }
        !           236:                                                        }
        !           237:                                                        s = p;
        !           238:                                                        while (*s == '\r' || *s == '\n') s++;
        !           239:                                                } while (*s != 0);
        !           240:                                        }
        !           241:                                }
        !           242:                        } else if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval)) {
        !           243:                                s = Z_STRVAL_PP(tmpzval);
        !           244:                                do {
        !           245:                                        while (*s == ' ' || *s == '\t') s++;
        !           246:                                        p = s;
        !           247:                                        while (*p != 0 && *p != ':' && *p != '\r' && *p !='\n') p++;
        !           248:                                        if (*p == ':') {
        !           249:                                                p++;
        !           250:                                                if (p - s == sizeof("Proxy-Authorization:") - 1 &&
        !           251:                                                    zend_binary_strcasecmp(s, sizeof("Proxy-Authorization:") - 1,
        !           252:                                                        "Proxy-Authorization:", sizeof("Proxy-Authorization:") - 1) == 0) {
        !           253:                                                        while (*p != 0 && *p != '\r' && *p !='\n') p++;
        !           254:                                                        smart_str_appendl(&header, s, p - s);
        !           255:                                                        smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);
        !           256:                                                        goto finish;
        !           257:                                                } else {
        !           258:                                                        while (*p != 0 && *p != '\r' && *p !='\n') p++;
        !           259:                                                }
        !           260:                                        }
        !           261:                                        s = p;
        !           262:                                        while (*s == '\r' || *s == '\n') s++;
        !           263:                                } while (*s != 0);
        !           264:                        }
        !           265:                }
        !           266: finish:
        !           267:                smart_str_appendl(&header, "\r\n", sizeof("\r\n")-1);
        !           268: 
        !           269:                if (php_stream_write(stream, header.c, header.len) != header.len) {
        !           270:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Cannot connect to HTTPS server through proxy");
        !           271:                        php_stream_close(stream);
        !           272:                        stream = NULL;
        !           273:                }
        !           274:                smart_str_free(&header);
        !           275: 
        !           276:                if (stream) {
        !           277:                        char header_line[HTTP_HEADER_BLOCK_SIZE];
        !           278: 
        !           279:                        /* get response header */
        !           280:                        while (php_stream_gets(stream, header_line, HTTP_HEADER_BLOCK_SIZE-1) != NULL) {
        !           281:                                if (header_line[0] == '\n' ||
        !           282:                                    header_line[0] == '\r' ||
        !           283:                                    header_line[0] == '\0') {
        !           284:                                  break;
        !           285:                                }
        !           286:                        }
        !           287:                }
        !           288: 
        !           289:                /* enable SSL transport layer */
        !           290:                if (stream) {
        !           291:                        if (php_stream_xport_crypto_setup(stream, STREAM_CRYPTO_METHOD_SSLv23_CLIENT, NULL TSRMLS_CC) < 0 ||
        !           292:                            php_stream_xport_crypto_enable(stream, 1 TSRMLS_CC) < 0) {
        !           293:                                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Cannot connect to HTTPS server through proxy");
        !           294:                                php_stream_close(stream);
        !           295:                                stream = NULL;
        !           296:                        }
        !           297:                }
        !           298:        }
        !           299: 
        !           300:        if (stream == NULL)
        !           301:                goto out;
        !           302: 
        !           303:        /* avoid buffering issues while reading header */
        !           304:        if (options & STREAM_WILL_CAST)
        !           305:                chunk_size = php_stream_set_chunk_size(stream, 1);
        !           306:        
        !           307:        /* avoid problems with auto-detecting when reading the headers -> the headers
        !           308:         * are always in canonical \r\n format */
        !           309:        eol_detect = stream->flags & (PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC);
        !           310:        stream->flags &= ~(PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC);
        !           311: 
        !           312:        php_stream_context_set(stream, context);
        !           313: 
        !           314:        php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0);
        !           315: 
        !           316:        if (header_init && context && php_stream_context_get_option(context, "http", "max_redirects", &tmpzval) == SUCCESS) {
        !           317:                SEPARATE_ZVAL(tmpzval);
        !           318:                convert_to_long_ex(tmpzval);
        !           319:                redirect_max = Z_LVAL_PP(tmpzval);
        !           320:        }
        !           321: 
        !           322:        if (context && php_stream_context_get_option(context, "http", "method", &tmpzval) == SUCCESS) {
        !           323:                if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0) {
        !           324:                        /* As per the RFC, automatically redirected requests MUST NOT use other methods than
        !           325:                         * GET and HEAD unless it can be confirmed by the user */
        !           326:                        if (!redirected
        !           327:                                || (Z_STRLEN_PP(tmpzval) == 3 && memcmp("GET", Z_STRVAL_PP(tmpzval), 3) == 0)
        !           328:                                || (Z_STRLEN_PP(tmpzval) == 4 && memcmp("HEAD",Z_STRVAL_PP(tmpzval), 4) == 0)
        !           329:                        ) {
        !           330:                                scratch_len = strlen(path) + 29 + Z_STRLEN_PP(tmpzval);
        !           331:                                scratch = emalloc(scratch_len);
        !           332:                                strlcpy(scratch, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval) + 1);
        !           333:                                strncat(scratch, " ", 1);
        !           334:                        }
        !           335:                }
        !           336:        }
        !           337:  
        !           338:        if (context && php_stream_context_get_option(context, "http", "protocol_version", &tmpzval) == SUCCESS) {
        !           339:                SEPARATE_ZVAL(tmpzval);
        !           340:                convert_to_double_ex(tmpzval);
        !           341:                protocol_version_len = spprintf(&protocol_version, 0, "%.1F", Z_DVAL_PP(tmpzval));
        !           342:        }
        !           343: 
        !           344:        if (!scratch) {
        !           345:                scratch_len = strlen(path) + 29 + protocol_version_len;
        !           346:                scratch = emalloc(scratch_len);
        !           347:                strncpy(scratch, "GET ", scratch_len);
        !           348:        }
        !           349: 
        !           350:        /* Should we send the entire path in the request line, default to no. */
        !           351:        if (!request_fulluri &&
        !           352:                context &&
        !           353:                php_stream_context_get_option(context, "http", "request_fulluri", &tmpzval) == SUCCESS) {
        !           354:                zval ztmp = **tmpzval;
        !           355: 
        !           356:                zval_copy_ctor(&ztmp);
        !           357:                convert_to_boolean(&ztmp);
        !           358:                request_fulluri = Z_BVAL(ztmp) ? 1 : 0;
        !           359:                zval_dtor(&ztmp);
        !           360:        }
        !           361: 
        !           362:        if (request_fulluri) {
        !           363:                /* Ask for everything */
        !           364:                strcat(scratch, path);
        !           365:        } else {
        !           366:                /* Send the traditional /path/to/file?query_string */
        !           367: 
        !           368:                /* file */
        !           369:                if (resource->path && *resource->path) {
        !           370:                        strlcat(scratch, resource->path, scratch_len);
        !           371:                } else {
        !           372:                        strlcat(scratch, "/", scratch_len);
        !           373:                }
        !           374: 
        !           375:                /* query string */
        !           376:                if (resource->query) {
        !           377:                        strlcat(scratch, "?", scratch_len);
        !           378:                        strlcat(scratch, resource->query, scratch_len);
        !           379:                }
        !           380:        }
        !           381: 
        !           382:        /* protocol version we are speaking */
        !           383:        if (protocol_version) {
        !           384:                strlcat(scratch, " HTTP/", scratch_len);
        !           385:                strlcat(scratch, protocol_version, scratch_len);
        !           386:                strlcat(scratch, "\r\n", scratch_len);
        !           387:                efree(protocol_version);
        !           388:                protocol_version = NULL;
        !           389:        } else {
        !           390:                strlcat(scratch, " HTTP/1.0\r\n", scratch_len);
        !           391:        }
        !           392: 
        !           393:        /* send it */
        !           394:        php_stream_write(stream, scratch, strlen(scratch));
        !           395: 
        !           396:        if (context && php_stream_context_get_option(context, "http", "header", &tmpzval) == SUCCESS) {
        !           397:                tmp = NULL;
        !           398:                
        !           399:                if (Z_TYPE_PP(tmpzval) == IS_ARRAY) {
        !           400:                        HashPosition pos;
        !           401:                        zval **tmpheader = NULL;
        !           402:                        smart_str tmpstr = {0};
        !           403: 
        !           404:                        for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(tmpzval), &pos);
        !           405:                                SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(tmpzval), (void *)&tmpheader, &pos);
        !           406:                                zend_hash_move_forward_ex(Z_ARRVAL_PP(tmpzval), &pos)
        !           407:                        ) {
        !           408:                                if (Z_TYPE_PP(tmpheader) == IS_STRING) {
        !           409:                                        smart_str_appendl(&tmpstr, Z_STRVAL_PP(tmpheader), Z_STRLEN_PP(tmpheader));
        !           410:                                        smart_str_appendl(&tmpstr, "\r\n", sizeof("\r\n") - 1);
        !           411:                                }
        !           412:                        }
        !           413:                        smart_str_0(&tmpstr);
        !           414:                        /* Remove newlines and spaces from start and end. there's at least one extra \r\n at the end that needs to go. */
        !           415:                        if (tmpstr.c) {
        !           416:                                tmp = php_trim(tmpstr.c, strlen(tmpstr.c), NULL, 0, NULL, 3 TSRMLS_CC);
        !           417:                                smart_str_free(&tmpstr);
        !           418:                        }
        !           419:                }
        !           420:                if (Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval)) {
        !           421:                        /* Remove newlines and spaces from start and end php_trim will estrndup() */
        !           422:                        tmp = php_trim(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval), NULL, 0, NULL, 3 TSRMLS_CC);
        !           423:                }
        !           424:                if (tmp && strlen(tmp) > 0) {
        !           425:                        char *s;
        !           426: 
        !           427:                        if (!header_init) { /* Remove post headers for redirects */
        !           428:                                int l = strlen(tmp);
        !           429:                                char *s2, *tmp_c = estrdup(tmp);
        !           430:                                
        !           431:                                php_strtolower(tmp_c, l);
        !           432:                                if ((s = strstr(tmp_c, "content-length:"))) {
        !           433:                                        if ((s2 = memchr(s, '\n', tmp_c + l - s))) {
        !           434:                                                int b = tmp_c + l - 1 - s2;
        !           435:                                                memmove(tmp, tmp + (s2 + 1 - tmp_c), b);
        !           436:                                                memmove(tmp_c, s2 + 1, b);
        !           437:                                                
        !           438:                                        } else {
        !           439:                                                tmp[s - tmp_c] = *s = '\0';
        !           440:                                        }
        !           441:                                        l = strlen(tmp_c);
        !           442:                                }
        !           443:                                if ((s = strstr(tmp_c, "content-type:"))) {
        !           444:                                        if ((s2 = memchr(s, '\n', tmp_c + l - s))) {
        !           445:                                                memmove(tmp, tmp + (s2 + 1 - tmp_c), tmp_c + l - 1 - s2);
        !           446:                                        } else {
        !           447:                                                tmp[s - tmp_c] = '\0';
        !           448:                                        }
        !           449:                                }
        !           450: 
        !           451:                                efree(tmp_c);
        !           452:                                tmp_c = php_trim(tmp, strlen(tmp), NULL, 0, NULL, 3 TSRMLS_CC);
        !           453:                                efree(tmp);
        !           454:                                tmp = tmp_c;
        !           455:                        }
        !           456: 
        !           457:                        user_headers = estrdup(tmp);
        !           458: 
        !           459:                        /* Make lowercase for easy comparison against 'standard' headers */
        !           460:                        php_strtolower(tmp, strlen(tmp));
        !           461:                        if ((s = strstr(tmp, "user-agent:")) && 
        !           462:                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
        !           463:                                         *(s-1) == '\t' || *(s-1) == ' ')) {
        !           464:                                 have_header |= HTTP_HEADER_USER_AGENT;
        !           465:                        }
        !           466:                        if ((s = strstr(tmp, "host:")) &&
        !           467:                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
        !           468:                                         *(s-1) == '\t' || *(s-1) == ' ')) {
        !           469:                                 have_header |= HTTP_HEADER_HOST;
        !           470:                        }
        !           471:                        if ((s = strstr(tmp, "from:")) &&
        !           472:                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
        !           473:                                         *(s-1) == '\t' || *(s-1) == ' ')) {
        !           474:                                 have_header |= HTTP_HEADER_FROM;
        !           475:                                }
        !           476:                        if ((s = strstr(tmp, "authorization:")) &&
        !           477:                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
        !           478:                                         *(s-1) == '\t' || *(s-1) == ' ')) {
        !           479:                                 have_header |= HTTP_HEADER_AUTH;
        !           480:                        }
        !           481:                        if ((s = strstr(tmp, "content-length:")) &&
        !           482:                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
        !           483:                                         *(s-1) == '\t' || *(s-1) == ' ')) {
        !           484:                                 have_header |= HTTP_HEADER_CONTENT_LENGTH;
        !           485:                        }
        !           486:                        if ((s = strstr(tmp, "content-type:")) &&
        !           487:                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
        !           488:                                         *(s-1) == '\t' || *(s-1) == ' ')) {
        !           489:                                 have_header |= HTTP_HEADER_TYPE;
        !           490:                        }
        !           491:                        /* remove Proxy-Authorization header */
        !           492:                        if (use_proxy && use_ssl && (s = strstr(tmp, "proxy-authorization:")) &&
        !           493:                            (s == tmp || *(s-1) == '\r' || *(s-1) == '\n' || 
        !           494:                                         *(s-1) == '\t' || *(s-1) == ' ')) {
        !           495:                                char *p = s + sizeof("proxy-authorization:") - 1;
        !           496:                                
        !           497:                                while (s > tmp && (*(s-1) == ' ' || *(s-1) == '\t')) s--;
        !           498:                                while (*p != 0 && *p != '\r' && *p != '\n') p++;
        !           499:                                while (*p == '\r' || *p == '\n') p++;
        !           500:                                if (*p == 0) {
        !           501:                                        if (s == tmp) {
        !           502:                                                efree(user_headers);
        !           503:                                                user_headers = NULL;
        !           504:                                        } else {
        !           505:                                                while (s > tmp && (*(s-1) == '\r' || *(s-1) == '\n')) s--;
        !           506:                                                user_headers[s - tmp] = 0;
        !           507:                                        }
        !           508:                                } else {
        !           509:                                        memmove(user_headers + (s - tmp), user_headers + (p - tmp), strlen(p) + 1);
        !           510:                                }
        !           511:                        }
        !           512: 
        !           513:                }
        !           514:                if (tmp) {
        !           515:                        efree(tmp);
        !           516:                }
        !           517:        }
        !           518: 
        !           519:        /* auth header if it was specified */
        !           520:        if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user) {
        !           521:                /* decode the strings first */
        !           522:                php_url_decode(resource->user, strlen(resource->user));
        !           523: 
        !           524:                /* scratch is large enough, since it was made large enough for the whole URL */
        !           525:                strcpy(scratch, resource->user);
        !           526:                strcat(scratch, ":");
        !           527: 
        !           528:                /* Note: password is optional! */
        !           529:                if (resource->pass) {
        !           530:                        php_url_decode(resource->pass, strlen(resource->pass));
        !           531:                        strcat(scratch, resource->pass);
        !           532:                }
        !           533: 
        !           534:                tmp = (char*)php_base64_encode((unsigned char*)scratch, strlen(scratch), NULL);
        !           535:                
        !           536:                if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) {
        !           537:                        php_stream_write(stream, scratch, strlen(scratch));
        !           538:                        php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0);
        !           539:                }
        !           540: 
        !           541:                efree(tmp);
        !           542:                tmp = NULL;
        !           543:        }
        !           544: 
        !           545:        /* if the user has configured who they are, send a From: line */
        !           546:        {
        !           547:                char *from_address = php_ini_string("from", sizeof("from"), 0);
        !           548:                if (((have_header & HTTP_HEADER_FROM) == 0) && from_address && from_address[0] != '\0') {
        !           549:                        if (snprintf(scratch, scratch_len, "From: %s\r\n", from_address) > 0)
        !           550:                                php_stream_write(stream, scratch, strlen(scratch));
        !           551:                }
        !           552:        }
        !           553: 
        !           554:        /* Send Host: header so name-based virtual hosts work */
        !           555:        if ((have_header & HTTP_HEADER_HOST) == 0) {
        !           556:                if ((use_ssl && resource->port != 443 && resource->port != 0) || 
        !           557:                        (!use_ssl && resource->port != 80 && resource->port != 0)) {
        !           558:                        if (snprintf(scratch, scratch_len, "Host: %s:%i\r\n", resource->host, resource->port) > 0)
        !           559:                                php_stream_write(stream, scratch, strlen(scratch));
        !           560:                } else {
        !           561:                        if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0) {
        !           562:                                php_stream_write(stream, scratch, strlen(scratch));
        !           563:                        }
        !           564:                }
        !           565:        }
        !           566: 
        !           567:        if (context && 
        !           568:            php_stream_context_get_option(context, "http", "user_agent", &ua_zval) == SUCCESS &&
        !           569:                Z_TYPE_PP(ua_zval) == IS_STRING) {
        !           570:                ua_str = Z_STRVAL_PP(ua_zval);
        !           571:        } else if (FG(user_agent)) {
        !           572:                ua_str = FG(user_agent);
        !           573:        }
        !           574: 
        !           575:        if (((have_header & HTTP_HEADER_USER_AGENT) == 0) && ua_str) {
        !           576: #define _UA_HEADER "User-Agent: %s\r\n"
        !           577:                char *ua;
        !           578:                size_t ua_len;
        !           579:                
        !           580:                ua_len = sizeof(_UA_HEADER) + strlen(ua_str);
        !           581:                
        !           582:                /* ensure the header is only sent if user_agent is not blank */
        !           583:                if (ua_len > sizeof(_UA_HEADER)) {
        !           584:                        ua = emalloc(ua_len + 1);
        !           585:                        if ((ua_len = slprintf(ua, ua_len, _UA_HEADER, ua_str)) > 0) {
        !           586:                                ua[ua_len] = 0;
        !           587:                                php_stream_write(stream, ua, ua_len);
        !           588:                        } else {
        !           589:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot construct User-agent header");
        !           590:                        }
        !           591: 
        !           592:                        if (ua) {
        !           593:                                efree(ua);
        !           594:                        }
        !           595:                }       
        !           596:        }
        !           597: 
        !           598:        if (user_headers) {
        !           599:                /* A bit weird, but some servers require that Content-Length be sent prior to Content-Type for POST
        !           600:                 * see bug #44603 for details. Since Content-Type maybe part of user's headers we need to do this check first.
        !           601:                 */
        !           602:                if (
        !           603:                                header_init &&
        !           604:                                context &&
        !           605:                                !(have_header & HTTP_HEADER_CONTENT_LENGTH) &&
        !           606:                                php_stream_context_get_option(context, "http", "content", &tmpzval) == SUCCESS &&
        !           607:                                Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0
        !           608:                ) {
        !           609:                        scratch_len = slprintf(scratch, scratch_len, "Content-Length: %d\r\n", Z_STRLEN_PP(tmpzval));
        !           610:                        php_stream_write(stream, scratch, scratch_len);
        !           611:                        have_header |= HTTP_HEADER_CONTENT_LENGTH;
        !           612:                }
        !           613: 
        !           614:                php_stream_write(stream, user_headers, strlen(user_headers));
        !           615:                php_stream_write(stream, "\r\n", sizeof("\r\n")-1);
        !           616:                efree(user_headers);
        !           617:        }
        !           618: 
        !           619:        /* Request content, such as for POST requests */
        !           620:        if (header_init && context &&
        !           621:                php_stream_context_get_option(context, "http", "content", &tmpzval) == SUCCESS &&
        !           622:                Z_TYPE_PP(tmpzval) == IS_STRING && Z_STRLEN_PP(tmpzval) > 0) {
        !           623:                if (!(have_header & HTTP_HEADER_CONTENT_LENGTH)) {
        !           624:                        scratch_len = slprintf(scratch, scratch_len, "Content-Length: %d\r\n", Z_STRLEN_PP(tmpzval));
        !           625:                        php_stream_write(stream, scratch, scratch_len);
        !           626:                }
        !           627:                if (!(have_header & HTTP_HEADER_TYPE)) {
        !           628:                        php_stream_write(stream, "Content-Type: application/x-www-form-urlencoded\r\n",
        !           629:                                sizeof("Content-Type: application/x-www-form-urlencoded\r\n") - 1);
        !           630:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Content-type not specified assuming application/x-www-form-urlencoded");
        !           631:                }
        !           632:                php_stream_write(stream, "\r\n", sizeof("\r\n")-1);
        !           633:                php_stream_write(stream, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
        !           634:        } else {
        !           635:                php_stream_write(stream, "\r\n", sizeof("\r\n")-1);
        !           636:        }
        !           637: 
        !           638:        location[0] = '\0';
        !           639: 
        !           640:        if (!EG(active_symbol_table)) {
        !           641:                zend_rebuild_symbol_table(TSRMLS_C);
        !           642:        }
        !           643: 
        !           644:        if (header_init) {
        !           645:                zval *ztmp;
        !           646:                MAKE_STD_ZVAL(ztmp);
        !           647:                array_init(ztmp);
        !           648:                ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", ztmp);
        !           649:        }
        !           650: 
        !           651:        {
        !           652:                zval **rh;
        !           653:                zend_hash_find(EG(active_symbol_table), "http_response_header", sizeof("http_response_header"), (void **) &rh);
        !           654:                response_header = *rh;
        !           655:        }
        !           656: 
        !           657:        if (!php_stream_eof(stream)) {
        !           658:                size_t tmp_line_len;
        !           659:                /* get response header */
        !           660: 
        !           661:                if (php_stream_get_line(stream, tmp_line, sizeof(tmp_line) - 1, &tmp_line_len) != NULL) {
        !           662:                        zval *http_response;
        !           663:                        int response_code;
        !           664: 
        !           665:                        if (tmp_line_len > 9) {
        !           666:                                response_code = atoi(tmp_line + 9);
        !           667:                        } else {
        !           668:                                response_code = 0;
        !           669:                        }
        !           670:                        if (context && SUCCESS==php_stream_context_get_option(context, "http", "ignore_errors", &tmpzval)) {
        !           671:                                ignore_errors = zend_is_true(*tmpzval);
        !           672:                        }
        !           673:                        /* when we request only the header, don't fail even on error codes */
        !           674:                        if ((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) {
        !           675:                                reqok = 1;
        !           676:                        }
        !           677:                        /* all status codes in the 2xx range are defined by the specification as successful;
        !           678:                         * all status codes in the 3xx range are for redirection, and so also should never
        !           679:                         * fail */
        !           680:                        if (response_code >= 200 && response_code < 400) {
        !           681:                                reqok = 1;
        !           682:                        } else {
        !           683:                                switch(response_code) {
        !           684:                                        case 403:
        !           685:                                                php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT,
        !           686:                                                                tmp_line, response_code);
        !           687:                                                break;
        !           688:                                        default:
        !           689:                                                /* safety net in the event tmp_line == NULL */
        !           690:                                                if (!tmp_line_len) {
        !           691:                                                        tmp_line[0] = '\0';
        !           692:                                                }
        !           693:                                                php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE,
        !           694:                                                                tmp_line, response_code);
        !           695:                                }
        !           696:                        }
        !           697:                        if (tmp_line[tmp_line_len - 1] == '\n') {
        !           698:                                --tmp_line_len;
        !           699:                                if (tmp_line[tmp_line_len - 1] == '\r') {
        !           700:                                        --tmp_line_len;
        !           701:                                }
        !           702:                        }
        !           703:                        MAKE_STD_ZVAL(http_response);
        !           704:                        ZVAL_STRINGL(http_response, tmp_line, tmp_line_len, 1);
        !           705:                        zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response, sizeof(zval *), NULL);
        !           706:                }
        !           707:        } else {
        !           708:                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP request failed, unexpected end of socket!");
        !           709:                goto out;
        !           710:        }
        !           711:        
        !           712:        /* read past HTTP headers */
        !           713:        
        !           714:        http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE);
        !           715: 
        !           716:        while (!body && !php_stream_eof(stream)) {
        !           717:                size_t http_header_line_length;
        !           718:                if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) && *http_header_line != '\n' && *http_header_line != '\r') {
        !           719:                        char *e = http_header_line + http_header_line_length - 1;
        !           720:                        if (*e != '\n') {
        !           721:                                do { /* partial header */
        !           722:                                        if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) {
        !           723:                                                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Failed to read HTTP headers");
        !           724:                                                goto out;
        !           725:                                        }
        !           726:                                        e = http_header_line + http_header_line_length - 1;
        !           727:                                } while (*e != '\n');
        !           728:                                continue;
        !           729:                        }
        !           730:                        while (*e == '\n' || *e == '\r') {
        !           731:                                e--;
        !           732:                        }
        !           733:                        http_header_line_length = e - http_header_line + 1;
        !           734:                        http_header_line[http_header_line_length] = '\0';
        !           735: 
        !           736:                        if (!strncasecmp(http_header_line, "Location: ", 10)) {
        !           737:                                if (context && php_stream_context_get_option(context, "http", "follow_location", &tmpzval) == SUCCESS) {
        !           738:                                        SEPARATE_ZVAL(tmpzval);
        !           739:                                        convert_to_long_ex(tmpzval);
        !           740:                                        follow_location = Z_LVAL_PP(tmpzval);
        !           741:                                }
        !           742:                                strlcpy(location, http_header_line + 10, sizeof(location));
        !           743:                        } else if (!strncasecmp(http_header_line, "Content-Type: ", 14)) {
        !           744:                                php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + 14, 0);
        !           745:                        } else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) {
        !           746:                                file_size = atoi(http_header_line + 16);
        !           747:                                php_stream_notify_file_size(context, file_size, http_header_line, 0);
        !           748:                        } else if (!strncasecmp(http_header_line, "Transfer-Encoding: chunked", sizeof("Transfer-Encoding: chunked"))) {
        !           749: 
        !           750:                                /* create filter to decode response body */
        !           751:                                if (!(options & STREAM_ONLY_GET_HEADERS)) {
        !           752:                                        long decode = 1;
        !           753: 
        !           754:                                        if (context && php_stream_context_get_option(context, "http", "auto_decode", &tmpzval) == SUCCESS) {
        !           755:                                                SEPARATE_ZVAL(tmpzval);
        !           756:                                                convert_to_boolean(*tmpzval);
        !           757:                                                decode = Z_LVAL_PP(tmpzval);
        !           758:                                        }
        !           759:                                        if (decode) {
        !           760:                                                transfer_encoding = php_stream_filter_create("dechunk", NULL, php_stream_is_persistent(stream) TSRMLS_CC);
        !           761:                                                if (transfer_encoding) {
        !           762:                                                        /* don't store transfer-encodeing header */
        !           763:                                                        continue;
        !           764:                                                }
        !           765:                                        }
        !           766:                                }
        !           767:                        }
        !           768: 
        !           769:                        if (http_header_line[0] == '\0') {
        !           770:                                body = 1;
        !           771:                        } else {
        !           772:                                zval *http_header;
        !           773: 
        !           774:                                MAKE_STD_ZVAL(http_header);
        !           775: 
        !           776:                                ZVAL_STRINGL(http_header, http_header_line, http_header_line_length, 1);
        !           777:                                
        !           778:                                zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header, sizeof(zval *), NULL);
        !           779:                        }
        !           780:                } else {
        !           781:                        break;
        !           782:                }
        !           783:        }
        !           784: 
        !           785:        if (!reqok || (location[0] != '\0' && follow_location)) {
        !           786:                if (!follow_location || (((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) && redirect_max <= 1)) {
        !           787:                        goto out;
        !           788:                }
        !           789: 
        !           790:                if (location[0] != '\0')
        !           791:                        php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, location, 0);
        !           792: 
        !           793:                php_stream_close(stream);
        !           794:                stream = NULL;
        !           795: 
        !           796:                if (location[0] != '\0') {
        !           797: 
        !           798:                        char new_path[HTTP_HEADER_BLOCK_SIZE];
        !           799:                        char loc_path[HTTP_HEADER_BLOCK_SIZE];
        !           800: 
        !           801:                        *new_path='\0';
        !           802:                        if (strlen(location)<8 || (strncasecmp(location, "http://", sizeof("http://")-1) && 
        !           803:                                                        strncasecmp(location, "https://", sizeof("https://")-1) && 
        !           804:                                                        strncasecmp(location, "ftp://", sizeof("ftp://")-1) && 
        !           805:                                                        strncasecmp(location, "ftps://", sizeof("ftps://")-1))) 
        !           806:                        {
        !           807:                                if (*location != '/') {
        !           808:                                        if (*(location+1) != '\0' && resource->path) {
        !           809:                                                char *s = strrchr(resource->path, '/');
        !           810:                                                if (!s) {
        !           811:                                                        s = resource->path;
        !           812:                                                        if (!s[0]) {
        !           813:                                                                efree(s);
        !           814:                                                                s = resource->path = estrdup("/");
        !           815:                                                        } else {
        !           816:                                                                *s = '/';
        !           817:                                                        }
        !           818:                                                }
        !           819:                                                s[1] = '\0'; 
        !           820:                                                if (resource->path && *(resource->path) == '/' && *(resource->path + 1) == '\0') {
        !           821:                                                        snprintf(loc_path, sizeof(loc_path) - 1, "%s%s", resource->path, location);
        !           822:                                                } else {
        !           823:                                                        snprintf(loc_path, sizeof(loc_path) - 1, "%s/%s", resource->path, location);
        !           824:                                                }
        !           825:                                        } else {
        !           826:                                                snprintf(loc_path, sizeof(loc_path) - 1, "/%s", location);
        !           827:                                        }
        !           828:                                } else {
        !           829:                                        strlcpy(loc_path, location, sizeof(loc_path));
        !           830:                                }
        !           831:                                if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
        !           832:                                        snprintf(new_path, sizeof(new_path) - 1, "%s://%s:%d%s", resource->scheme, resource->host, resource->port, loc_path);
        !           833:                                } else {
        !           834:                                        snprintf(new_path, sizeof(new_path) - 1, "%s://%s%s", resource->scheme, resource->host, loc_path);
        !           835:                                }
        !           836:                        } else {
        !           837:                                strlcpy(new_path, location, sizeof(new_path));
        !           838:                        }
        !           839: 
        !           840:                        php_url_free(resource);
        !           841:                        /* check for invalid redirection URLs */
        !           842:                        if ((resource = php_url_parse(new_path)) == NULL) {
        !           843:                                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect URL! %s", new_path);
        !           844:                                goto out;
        !           845:                        }
        !           846: 
        !           847: #define CHECK_FOR_CNTRL_CHARS(val) { \
        !           848:        if (val) { \
        !           849:                unsigned char *s, *e; \
        !           850:                int l; \
        !           851:                l = php_url_decode(val, strlen(val)); \
        !           852:                s = (unsigned char*)val; e = s + l; \
        !           853:                while (s < e) { \
        !           854:                        if (iscntrl(*s)) { \
        !           855:                                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Invalid redirect URL! %s", new_path); \
        !           856:                                goto out; \
        !           857:                        } \
        !           858:                        s++; \
        !           859:                } \
        !           860:        } \
        !           861: }
        !           862:                        /* check for control characters in login, password & path */
        !           863:                        if (strncasecmp(new_path, "http://", sizeof("http://") - 1) || strncasecmp(new_path, "https://", sizeof("https://") - 1)) {
        !           864:                                CHECK_FOR_CNTRL_CHARS(resource->user)
        !           865:                                CHECK_FOR_CNTRL_CHARS(resource->pass)
        !           866:                                CHECK_FOR_CNTRL_CHARS(resource->path)
        !           867:                        }
        !           868:                        stream = php_stream_url_wrap_http_ex(wrapper, new_path, mode, options, opened_path, context, --redirect_max, HTTP_WRAPPER_REDIRECTED STREAMS_CC TSRMLS_CC);
        !           869:                } else {
        !           870:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "HTTP request failed! %s", tmp_line);
        !           871:                }
        !           872:        }
        !           873: out:
        !           874:        if (protocol_version) {
        !           875:                efree(protocol_version);
        !           876:        }
        !           877: 
        !           878:        if (http_header_line) {
        !           879:                efree(http_header_line);
        !           880:        }
        !           881: 
        !           882:        if (scratch) {
        !           883:                efree(scratch);
        !           884:        }
        !           885: 
        !           886:        if (resource) {
        !           887:                php_url_free(resource);
        !           888:        }
        !           889: 
        !           890:        if (stream) {
        !           891:                if (header_init) {
        !           892:                        zval_add_ref(&response_header);
        !           893:                        stream->wrapperdata = response_header;
        !           894:                }
        !           895:                php_stream_notify_progress_init(context, 0, file_size);
        !           896:                
        !           897:                /* Restore original chunk size now that we're done with headers */
        !           898:                if (options & STREAM_WILL_CAST)
        !           899:                        php_stream_set_chunk_size(stream, chunk_size);
        !           900: 
        !           901:                /* restore the users auto-detect-line-endings setting */
        !           902:                stream->flags |= eol_detect;
        !           903:                
        !           904:                /* as far as streams are concerned, we are now at the start of
        !           905:                 * the stream */
        !           906:                stream->position = 0;
        !           907: 
        !           908:                /* restore mode */
        !           909:                strlcpy(stream->mode, mode, sizeof(stream->mode));
        !           910: 
        !           911:                if (transfer_encoding) {
        !           912:                        php_stream_filter_append(&stream->readfilters, transfer_encoding);
        !           913:                }
        !           914:        } else if (transfer_encoding) {
        !           915:                php_stream_filter_free(transfer_encoding TSRMLS_CC);
        !           916:        }
        !           917: 
        !           918:        return stream;
        !           919: }
        !           920: /* }}} */
        !           921: 
        !           922: php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
        !           923: {
        !           924:        return php_stream_url_wrap_http_ex(wrapper, path, mode, options, opened_path, context, PHP_URL_REDIRECT_MAX, HTTP_WRAPPER_HEADER_INIT STREAMS_CC TSRMLS_CC);
        !           925: }
        !           926: /* }}} */
        !           927: 
        !           928: static int php_stream_http_stream_stat(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) /* {{{ */
        !           929: {
        !           930:        /* one day, we could fill in the details based on Date: and Content-Length:
        !           931:         * headers.  For now, we return with a failure code to prevent the underlying
        !           932:         * file's details from being used instead. */
        !           933:        return -1;
        !           934: }
        !           935: /* }}} */
        !           936: 
        !           937: static php_stream_wrapper_ops http_stream_wops = {
        !           938:        php_stream_url_wrap_http,
        !           939:        NULL, /* stream_close */
        !           940:        php_stream_http_stream_stat,
        !           941:        NULL, /* stat_url */
        !           942:        NULL, /* opendir */
        !           943:        "http",
        !           944:        NULL, /* unlink */
        !           945:        NULL, /* rename */
        !           946:        NULL, /* mkdir */
        !           947:        NULL  /* rmdir */
        !           948: };
        !           949: 
        !           950: PHPAPI php_stream_wrapper php_stream_http_wrapper = {
        !           951:        &http_stream_wops,
        !           952:        NULL,
        !           953:        1 /* is_url */
        !           954: };
        !           955: 
        !           956: /*
        !           957:  * Local variables:
        !           958:  * tab-width: 4
        !           959:  * c-basic-offset: 4
        !           960:  * End:
        !           961:  * vim600: sw=4 ts=4 fdm=marker
        !           962:  * vim<600: sw=4 ts=4
        !           963:  */

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