Annotation of embedaddon/php/ext/standard/php_fopen_wrapper.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:    | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
                     16:    |          Jim Winstead <jimw@php.net>                                 |
                     17:    |          Hartmut Holzgraefe <hholzgra@php.net>                       |
                     18:    +----------------------------------------------------------------------+
                     19:  */
1.1.1.2   misho      20: /* $Id$ */
1.1       misho      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: 
1.1.1.3   misho     266:                if (strcmp(sapi_module.name, "cli")) {
                    267:                        if (options & REPORT_ERRORS) {
                    268:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Direct access to file descriptors is only available from command-line PHP");
                    269:                        }
                    270:                        return NULL;
                    271:                }
                    272: 
                    273:                if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
                    274:                        if (options & REPORT_ERRORS) {
                    275:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
                    276:                        }
                    277:                        return NULL;
                    278:                }
                    279: 
1.1       misho     280:                start = &path[3];
                    281:                fildes_ori = strtol(start, &end, 10);
                    282:                if (end == start || *end != '\0') {
                    283:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
                    284:                                "php://fd/ stream must be specified in the form php://fd/<orig fd>");
                    285:                        return NULL;
                    286:                }
                    287: 
                    288: #if HAVE_UNISTD_H
                    289:                dtablesize = getdtablesize();
                    290: #else
                    291:                dtablesize = INT_MAX;
                    292: #endif
                    293: 
                    294:                if (fildes_ori < 0 || fildes_ori >= dtablesize) {
                    295:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
                    296:                                "The file descriptors must be non-negative numbers smaller than %d", dtablesize);
                    297:                        return NULL;
                    298:                }
                    299:                
                    300:                fd = dup(fildes_ori);
                    301:                if (fd == -1) {
                    302:                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
                    303:                                "Error duping file descriptor %ld; possibly it doesn't exist: "
                    304:                                "[%d]: %s", fildes_ori, errno, strerror(errno));
                    305:                        return NULL;
                    306:                }
                    307:        } else if (!strncasecmp(path, "filter/", 7)) {
                    308:                /* Save time/memory when chain isn't specified */
                    309:                if (strchr(mode, 'r') || strchr(mode, '+')) {
                    310:                        mode_rw |= PHP_STREAM_FILTER_READ;
                    311:                }
                    312:                if (strchr(mode, 'w') || strchr(mode, '+') || strchr(mode, 'a')) {
                    313:                        mode_rw |= PHP_STREAM_FILTER_WRITE;
                    314:                }
                    315:                pathdup = estrndup(path + 6, strlen(path + 6));
                    316:                p = strstr(pathdup, "/resource=");
                    317:                if (!p) {
                    318:                        php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "No URL resource specified");
                    319:                        efree(pathdup);
                    320:                        return NULL;
                    321:                }
                    322:                if (!(stream = php_stream_open_wrapper(p + 10, mode, options, opened_path))) {
                    323:                        efree(pathdup);
                    324:                        return NULL;
                    325:                }
                    326: 
                    327:                *p = '\0';
                    328: 
                    329:                p = php_strtok_r(pathdup + 1, "/", &token);
                    330:                while (p) {
                    331:                        if (!strncasecmp(p, "read=", 5)) {
                    332:                                php_stream_apply_filter_list(stream, p + 5, 1, 0 TSRMLS_CC);
                    333:                        } else if (!strncasecmp(p, "write=", 6)) {
                    334:                                php_stream_apply_filter_list(stream, p + 6, 0, 1 TSRMLS_CC);
                    335:                        } else {
                    336:                                php_stream_apply_filter_list(stream, p, mode_rw & PHP_STREAM_FILTER_READ, mode_rw & PHP_STREAM_FILTER_WRITE TSRMLS_CC);
                    337:                        }
                    338:                        p = php_strtok_r(NULL, "/", &token);
                    339:                }
                    340:                efree(pathdup);
                    341: 
                    342:                return stream;
                    343:        } else {
                    344:                /* invalid php://thingy */
                    345:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid php:// URL specified");
                    346:                return NULL;
                    347:        }
                    348: 
                    349:        /* must be stdin, stderr or stdout */
                    350:        if (fd == -1)   {
                    351:                /* failed to dup */
                    352:                return NULL;
                    353:        }
                    354: 
                    355: #if defined(S_IFSOCK) && !defined(WIN32) && !defined(__BEOS__)
                    356:        do {
                    357:                struct stat st;
                    358:                memset(&st, 0, sizeof(st));
                    359:                if (fstat(fd, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
                    360:                        stream = php_stream_sock_open_from_socket(fd, NULL);
                    361:                        if (stream) {
                    362:                                stream->ops = &php_stream_socket_ops;
                    363:                                return stream;
                    364:                        }
                    365:                }
                    366:        } while (0);
                    367: #endif
                    368: 
                    369:        if (file) {
                    370:                stream = php_stream_fopen_from_file(file, mode);
                    371:        } else {
                    372:                stream = php_stream_fopen_from_fd(fd, mode, NULL);
                    373:                if (stream == NULL) {
                    374:                        close(fd);
                    375:                }
                    376:        }
                    377: 
                    378:        return stream;
                    379: }
                    380: /* }}} */
                    381: 
                    382: static php_stream_wrapper_ops php_stdio_wops = {
                    383:        php_stream_url_wrap_php,
                    384:        NULL, /* close */
                    385:        NULL, /* fstat */
                    386:        NULL, /* stat */
                    387:        NULL, /* opendir */
                    388:        "PHP",
                    389:        NULL, /* unlink */
                    390:        NULL, /* rename */
                    391:        NULL, /* mkdir */
                    392:        NULL  /* rmdir */
                    393: };
                    394: 
                    395: php_stream_wrapper php_stream_php_wrapper =    {
                    396:        &php_stdio_wops,
                    397:        NULL,
                    398:        0, /* is_url */
                    399: };
                    400: 
                    401: 
                    402: /*
                    403:  * Local variables:
                    404:  * tab-width: 4
                    405:  * c-basic-offset: 4
                    406:  * End:
                    407:  * vim600: sw=4 ts=4 fdm=marker
                    408:  * vim<600: sw=4 ts=4
                    409:  */

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