Annotation of embedaddon/php/ext/standard/php_fopen_wrapper.c, revision 1.1.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>