Annotation of embedaddon/php/ext/standard/php_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:    +----------------------------------------------------------------------+
        !            19:  */
        !            20: /* $Id: php_fopen_wrapper.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            21: 
        !            22: #include <stdio.h>
        !            23: #include <stdlib.h>
        !            24: #if HAVE_UNISTD_H
        !            25: #include <unistd.h>
        !            26: #endif
        !            27: 
        !            28: #include "php.h"
        !            29: #include "php_globals.h"
        !            30: #include "php_standard.h"
        !            31: #include "php_fopen_wrappers.h"
        !            32: #include "SAPI.h"
        !            33: 
        !            34: static size_t php_stream_output_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) /* {{{ */
        !            35: {
        !            36:        PHPWRITE(buf, count);
        !            37:        return count;
        !            38: }
        !            39: /* }}} */
        !            40: 
        !            41: static size_t php_stream_output_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
        !            42: {
        !            43:        stream->eof = 1;
        !            44:        return 0;
        !            45: }
        !            46: /* }}} */
        !            47: 
        !            48: static int php_stream_output_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
        !            49: {
        !            50:        return 0;
        !            51: }
        !            52: /* }}} */
        !            53: 
        !            54: php_stream_ops php_stream_output_ops = {
        !            55:        php_stream_output_write,
        !            56:        php_stream_output_read,
        !            57:        php_stream_output_close,
        !            58:        NULL, /* flush */
        !            59:        "Output",
        !            60:        NULL, /* seek */
        !            61:        NULL, /* cast */
        !            62:        NULL, /* stat */
        !            63:        NULL  /* set_option */
        !            64: };
        !            65: 
        !            66: static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) /* {{{ */
        !            67: {
        !            68:        return -1;
        !            69: }
        !            70: /* }}} */
        !            71: 
        !            72: static size_t php_stream_input_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
        !            73: {
        !            74:        off_t *position = (off_t*)stream->abstract;
        !            75:        size_t read_bytes = 0;
        !            76: 
        !            77:        if (!stream->eof) {
        !            78:                if (SG(request_info).raw_post_data) { /* data has already been read by a post handler */
        !            79:                        read_bytes = SG(request_info).raw_post_data_length - *position;
        !            80:                        if (read_bytes <= count) {
        !            81:                                stream->eof = 1;
        !            82:                        } else {
        !            83:                                read_bytes = count;
        !            84:                        }
        !            85:                        if (read_bytes) {
        !            86:                                memcpy(buf, SG(request_info).raw_post_data + *position, read_bytes);
        !            87:                        }
        !            88:                } else if (sapi_module.read_post) {
        !            89:                        read_bytes = sapi_module.read_post(buf, count TSRMLS_CC);
        !            90:                        if (read_bytes <= 0) {
        !            91:                                stream->eof = 1;
        !            92:                                read_bytes = 0;
        !            93:                        }
        !            94:                        /* Increment SG(read_post_bytes) only when something was actually read. */
        !            95:                        SG(read_post_bytes) += read_bytes;
        !            96:                } else {
        !            97:                        stream->eof = 1;
        !            98:                }
        !            99:        }
        !           100: 
        !           101:        *position += read_bytes;
        !           102: 
        !           103:        return read_bytes;
        !           104: }
        !           105: /* }}} */
        !           106: 
        !           107: static int php_stream_input_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
        !           108: {
        !           109:        efree(stream->abstract);
        !           110: 
        !           111:        return 0;
        !           112: }
        !           113: /* }}} */
        !           114: 
        !           115: static int php_stream_input_flush(php_stream *stream TSRMLS_DC) /* {{{ */
        !           116: {
        !           117:        return -1;
        !           118: }
        !           119: /* }}} */
        !           120: 
        !           121: php_stream_ops php_stream_input_ops = {
        !           122:        php_stream_input_write,
        !           123:        php_stream_input_read,
        !           124:        php_stream_input_close,
        !           125:        php_stream_input_flush,
        !           126:        "Input",
        !           127:        NULL, /* seek */
        !           128:        NULL, /* cast */
        !           129:        NULL, /* stat */
        !           130:        NULL  /* set_option */
        !           131: };
        !           132: 
        !           133: static void php_stream_apply_filter_list(php_stream *stream, char *filterlist, int read_chain, int write_chain TSRMLS_DC) /* {{{ */
        !           134: {
        !           135:        char *p, *token;
        !           136:        php_stream_filter *temp_filter;
        !           137: 
        !           138:        p = php_strtok_r(filterlist, "|", &token);
        !           139:        while (p) {
        !           140:                php_url_decode(p, strlen(p));
        !           141:                if (read_chain) {
        !           142:                        if ((temp_filter = php_stream_filter_create(p, NULL, php_stream_is_persistent(stream) TSRMLS_CC))) {
        !           143:                                php_stream_filter_append(&stream->readfilters, temp_filter);
        !           144:                        } else {
        !           145:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create filter (%s)", p);
        !           146:                        }
        !           147:                }
        !           148:                if (write_chain) {
        !           149:                        if ((temp_filter = php_stream_filter_create(p, NULL, php_stream_is_persistent(stream) TSRMLS_CC))) {
        !           150:                                php_stream_filter_append(&stream->writefilters, temp_filter);
        !           151:                        } else {
        !           152:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create filter (%s)", p);
        !           153:                        }
        !           154:                }
        !           155:                p = php_strtok_r(NULL, "|", &token);
        !           156:        }
        !           157: }
        !           158: /* }}} */
        !           159: 
        !           160: php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
        !           161: {
        !           162:        int fd = -1;
        !           163:        int mode_rw = 0;
        !           164:        php_stream * stream = NULL;
        !           165:        char *p, *token, *pathdup;
        !           166:        long max_memory;
        !           167:        FILE *file = NULL;
        !           168: 
        !           169:        if (!strncasecmp(path, "php://", 6)) {
        !           170:                path += 6;
        !           171:        }
        !           172: 
        !           173:        if (!strncasecmp(path, "temp", 4)) {
        !           174:                path += 4;
        !           175:                max_memory = PHP_STREAM_MAX_MEM;
        !           176:                if (!strncasecmp(path, "/maxmemory:", 11)) {
        !           177:                        path += 11;
        !           178:                        max_memory = strtol(path, NULL, 10);
        !           179:                        if (max_memory < 0) {
        !           180:                                php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Max memory must be >= 0");
        !           181:                                return NULL;
        !           182:                        }
        !           183:                }
        !           184:                if (strpbrk(mode, "wa+")) {
        !           185:                        mode_rw = TEMP_STREAM_DEFAULT;
        !           186:                } else {
        !           187:                        mode_rw = TEMP_STREAM_READONLY;
        !           188:                }
        !           189:                return php_stream_temp_create(mode_rw, max_memory);
        !           190:        }
        !           191: 
        !           192:        if (!strcasecmp(path, "memory")) {
        !           193:                if (strpbrk(mode, "wa+")) {
        !           194:                        mode_rw = TEMP_STREAM_DEFAULT;
        !           195:                } else {
        !           196:                        mode_rw = TEMP_STREAM_READONLY;
        !           197:                }
        !           198:                return php_stream_memory_create(mode_rw);
        !           199:        }
        !           200: 
        !           201:        if (!strcasecmp(path, "output")) {
        !           202:                return php_stream_alloc(&php_stream_output_ops, NULL, 0, "wb");
        !           203:        }
        !           204: 
        !           205:        if (!strcasecmp(path, "input")) {
        !           206:                if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
        !           207:                        if (options & REPORT_ERRORS) {
        !           208:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
        !           209:                        }
        !           210:                        return NULL;
        !           211:                }
        !           212:                return php_stream_alloc(&php_stream_input_ops, ecalloc(1, sizeof(off_t)), 0, "rb");
        !           213:        }
        !           214: 
        !           215:        if (!strcasecmp(path, "stdin")) {
        !           216:                if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
        !           217:                        if (options & REPORT_ERRORS) {
        !           218:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
        !           219:                        }
        !           220:                        return NULL;
        !           221:                }
        !           222:                if (!strcmp(sapi_module.name, "cli")) {
        !           223:                        static int cli_in = 0;
        !           224:                        fd = STDIN_FILENO;
        !           225:                        if (cli_in) {
        !           226:                                fd = dup(fd);
        !           227:                        } else {
        !           228:                                cli_in = 1;
        !           229:                                file = stdin;
        !           230:                        }
        !           231:                } else {
        !           232:                        fd = dup(STDIN_FILENO);
        !           233:                }
        !           234:        } else if (!strcasecmp(path, "stdout")) {
        !           235:                if (!strcmp(sapi_module.name, "cli")) {
        !           236:                        static int cli_out = 0;
        !           237:                        fd = STDOUT_FILENO;
        !           238:                        if (cli_out++) {
        !           239:                                fd = dup(fd);
        !           240:                        } else {
        !           241:                                cli_out = 1;
        !           242:                                file = stdout;
        !           243:                        }
        !           244:                } else {
        !           245:                        fd = dup(STDOUT_FILENO);
        !           246:                }
        !           247:        } else if (!strcasecmp(path, "stderr")) {
        !           248:                if (!strcmp(sapi_module.name, "cli")) {
        !           249:                        static int cli_err = 0;
        !           250:                        fd = STDERR_FILENO;
        !           251:                        if (cli_err++) {
        !           252:                                fd = dup(fd);
        !           253:                        } else {
        !           254:                                cli_err = 1;
        !           255:                                file = stderr;
        !           256:                        }
        !           257:                } else {
        !           258:                        fd = dup(STDERR_FILENO);
        !           259:                }
        !           260:        } else if (!strncasecmp(path, "fd/", 3)) {
        !           261:                char       *start,
        !           262:                                   *end;
        !           263:                long       fildes_ori;
        !           264:                int                dtablesize;
        !           265: 
        !           266:                start = &path[3];
        !           267:                fildes_ori = strtol(start, &end, 10);
        !           268:                if (end == start || *end != '\0') {
        !           269:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
        !           270:                                "php://fd/ stream must be specified in the form php://fd/<orig fd>");
        !           271:                        return NULL;
        !           272:                }
        !           273: 
        !           274: #if HAVE_UNISTD_H
        !           275:                dtablesize = getdtablesize();
        !           276: #else
        !           277:                dtablesize = INT_MAX;
        !           278: #endif
        !           279: 
        !           280:                if (fildes_ori < 0 || fildes_ori >= dtablesize) {
        !           281:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
        !           282:                                "The file descriptors must be non-negative numbers smaller than %d", dtablesize);
        !           283:                        return NULL;
        !           284:                }
        !           285:                
        !           286:                fd = dup(fildes_ori);
        !           287:                if (fd == -1) {
        !           288:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
        !           289:                                "Error duping file descriptor %ld; possibly it doesn't exist: "
        !           290:                                "[%d]: %s", fildes_ori, errno, strerror(errno));
        !           291:                        return NULL;
        !           292:                }
        !           293:        } else if (!strncasecmp(path, "filter/", 7)) {
        !           294:                /* Save time/memory when chain isn't specified */
        !           295:                if (strchr(mode, 'r') || strchr(mode, '+')) {
        !           296:                        mode_rw |= PHP_STREAM_FILTER_READ;
        !           297:                }
        !           298:                if (strchr(mode, 'w') || strchr(mode, '+') || strchr(mode, 'a')) {
        !           299:                        mode_rw |= PHP_STREAM_FILTER_WRITE;
        !           300:                }
        !           301:                pathdup = estrndup(path + 6, strlen(path + 6));
        !           302:                p = strstr(pathdup, "/resource=");
        !           303:                if (!p) {
        !           304:                        php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "No URL resource specified");
        !           305:                        efree(pathdup);
        !           306:                        return NULL;
        !           307:                }
        !           308:                if (!(stream = php_stream_open_wrapper(p + 10, mode, options, opened_path))) {
        !           309:                        efree(pathdup);
        !           310:                        return NULL;
        !           311:                }
        !           312: 
        !           313:                *p = '\0';
        !           314: 
        !           315:                p = php_strtok_r(pathdup + 1, "/", &token);
        !           316:                while (p) {
        !           317:                        if (!strncasecmp(p, "read=", 5)) {
        !           318:                                php_stream_apply_filter_list(stream, p + 5, 1, 0 TSRMLS_CC);
        !           319:                        } else if (!strncasecmp(p, "write=", 6)) {
        !           320:                                php_stream_apply_filter_list(stream, p + 6, 0, 1 TSRMLS_CC);
        !           321:                        } else {
        !           322:                                php_stream_apply_filter_list(stream, p, mode_rw & PHP_STREAM_FILTER_READ, mode_rw & PHP_STREAM_FILTER_WRITE TSRMLS_CC);
        !           323:                        }
        !           324:                        p = php_strtok_r(NULL, "/", &token);
        !           325:                }
        !           326:                efree(pathdup);
        !           327: 
        !           328:                return stream;
        !           329:        } else {
        !           330:                /* invalid php://thingy */
        !           331:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid php:// URL specified");
        !           332:                return NULL;
        !           333:        }
        !           334: 
        !           335:        /* must be stdin, stderr or stdout */
        !           336:        if (fd == -1)   {
        !           337:                /* failed to dup */
        !           338:                return NULL;
        !           339:        }
        !           340: 
        !           341: #if defined(S_IFSOCK) && !defined(WIN32) && !defined(__BEOS__)
        !           342:        do {
        !           343:                struct stat st;
        !           344:                memset(&st, 0, sizeof(st));
        !           345:                if (fstat(fd, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
        !           346:                        stream = php_stream_sock_open_from_socket(fd, NULL);
        !           347:                        if (stream) {
        !           348:                                stream->ops = &php_stream_socket_ops;
        !           349:                                return stream;
        !           350:                        }
        !           351:                }
        !           352:        } while (0);
        !           353: #endif
        !           354: 
        !           355:        if (file) {
        !           356:                stream = php_stream_fopen_from_file(file, mode);
        !           357:        } else {
        !           358:                stream = php_stream_fopen_from_fd(fd, mode, NULL);
        !           359:                if (stream == NULL) {
        !           360:                        close(fd);
        !           361:                }
        !           362:        }
        !           363: 
        !           364:        return stream;
        !           365: }
        !           366: /* }}} */
        !           367: 
        !           368: static php_stream_wrapper_ops php_stdio_wops = {
        !           369:        php_stream_url_wrap_php,
        !           370:        NULL, /* close */
        !           371:        NULL, /* fstat */
        !           372:        NULL, /* stat */
        !           373:        NULL, /* opendir */
        !           374:        "PHP",
        !           375:        NULL, /* unlink */
        !           376:        NULL, /* rename */
        !           377:        NULL, /* mkdir */
        !           378:        NULL  /* rmdir */
        !           379: };
        !           380: 
        !           381: php_stream_wrapper php_stream_php_wrapper =    {
        !           382:        &php_stdio_wops,
        !           383:        NULL,
        !           384:        0, /* is_url */
        !           385: };
        !           386: 
        !           387: 
        !           388: /*
        !           389:  * Local variables:
        !           390:  * tab-width: 4
        !           391:  * c-basic-offset: 4
        !           392:  * End:
        !           393:  * vim600: sw=4 ts=4 fdm=marker
        !           394:  * vim<600: sw=4 ts=4
        !           395:  */

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