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>