1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2007 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,v 1.45.2.4.2.6 2007/01/01 09:36:08 sebastian Exp $ */
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 32 : {
36 32 : PHPWRITE(buf, count);
37 32 : return count;
38 : }
39 :
40 : static size_t php_stream_output_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
41 0 : {
42 0 : stream->eof = 1;
43 0 : return 0;
44 : }
45 :
46 : static int php_stream_output_close(php_stream *stream, int close_handle TSRMLS_DC)
47 1 : {
48 1 : return 0;
49 : }
50 :
51 : static int php_stream_output_flush(php_stream *stream TSRMLS_DC)
52 16 : {
53 16 : sapi_flush(TSRMLS_C);
54 16 : return 0;
55 : }
56 :
57 : php_stream_ops php_stream_output_ops = {
58 : php_stream_output_write,
59 : php_stream_output_read,
60 : php_stream_output_close,
61 : php_stream_output_flush,
62 : "Output",
63 : NULL, /* seek */
64 : NULL, /* cast */
65 : NULL, /* stat */
66 : NULL /* set_option */
67 : };
68 :
69 : static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
70 0 : {
71 0 : return -1;
72 : }
73 :
74 : static size_t php_stream_input_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
75 0 : {
76 0 : off_t *position = (off_t*)stream->abstract;
77 0 : size_t read_bytes = 0;
78 :
79 0 : if(!stream->eof) {
80 0 : if(SG(request_info).raw_post_data) { /* data has already been read by a post handler */
81 0 : read_bytes = SG(request_info).raw_post_data_length - *position;
82 0 : if(read_bytes <= count) {
83 0 : stream->eof = 1;
84 : } else {
85 0 : read_bytes = count;
86 : }
87 0 : if(read_bytes) {
88 0 : memcpy(buf, SG(request_info).raw_post_data + *position, read_bytes);
89 : }
90 0 : } else if(sapi_module.read_post) {
91 0 : read_bytes = sapi_module.read_post(buf, count TSRMLS_CC);
92 0 : if(read_bytes <= 0){
93 0 : stream->eof = 1;
94 0 : read_bytes = 0;
95 : }
96 : } else {
97 0 : stream->eof = 1;
98 : }
99 : }
100 :
101 0 : *position += read_bytes;
102 0 : SG(read_post_bytes) += read_bytes;
103 0 : return read_bytes;
104 : }
105 :
106 : static int php_stream_input_close(php_stream *stream, int close_handle TSRMLS_DC)
107 0 : {
108 0 : efree(stream->abstract);
109 :
110 0 : return 0;
111 : }
112 :
113 : static int php_stream_input_flush(php_stream *stream TSRMLS_DC)
114 0 : {
115 0 : return -1;
116 : }
117 :
118 : php_stream_ops php_stream_input_ops = {
119 : php_stream_input_write,
120 : php_stream_input_read,
121 : php_stream_input_close,
122 : php_stream_input_flush,
123 : "Input",
124 : NULL, /* seek */
125 : NULL, /* cast */
126 : NULL, /* stat */
127 : NULL /* set_option */
128 : };
129 :
130 0 : static void php_stream_apply_filter_list(php_stream *stream, char *filterlist, int read_chain, int write_chain TSRMLS_DC) {
131 : char *p, *token;
132 : php_stream_filter *temp_filter;
133 :
134 0 : p = php_strtok_r(filterlist, "|", &token);
135 0 : while (p) {
136 0 : if (read_chain) {
137 0 : if ((temp_filter = php_stream_filter_create(p, NULL, php_stream_is_persistent(stream) TSRMLS_CC))) {
138 0 : php_stream_filter_append(&stream->readfilters, temp_filter);
139 : } else {
140 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create filter (%s)", p);
141 : }
142 : }
143 0 : if (write_chain) {
144 0 : if ((temp_filter = php_stream_filter_create(p, NULL, php_stream_is_persistent(stream) TSRMLS_CC))) {
145 0 : php_stream_filter_append(&stream->writefilters, temp_filter);
146 : } else {
147 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create filter (%s)", p);
148 : }
149 : }
150 0 : p = php_strtok_r(NULL, "|", &token);
151 : }
152 0 : }
153 :
154 :
155 : 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)
156 112 : {
157 112 : int fd = -1;
158 112 : int mode_rw = 0;
159 112 : php_stream * stream = NULL;
160 : char *p, *token, *pathdup;
161 : long max_memory;
162 :
163 112 : if (!strncasecmp(path, "php://", 6)) {
164 112 : path += 6;
165 : }
166 :
167 112 : if (!strncasecmp(path, "temp", 4)) {
168 0 : path += 4;
169 0 : max_memory = PHP_STREAM_MAX_MEM;
170 0 : if (!strncasecmp(path, "/maxmemory:", 11)) {
171 0 : path += 11;
172 0 : max_memory = strtol(path, NULL, 10);
173 0 : if (max_memory < 0) {
174 0 : php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Max memory must be >= 0");
175 0 : return NULL;
176 : }
177 : }
178 0 : return php_stream_temp_create(TEMP_STREAM_DEFAULT, max_memory);
179 : }
180 :
181 112 : if (!strcasecmp(path, "memory")) {
182 0 : return php_stream_memory_create(TEMP_STREAM_DEFAULT);
183 : }
184 :
185 112 : if (!strcasecmp(path, "output")) {
186 1 : return php_stream_alloc(&php_stream_output_ops, NULL, 0, "wb");
187 : }
188 :
189 111 : if (!strcasecmp(path, "input")) {
190 0 : if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
191 0 : if (options & REPORT_ERRORS) {
192 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
193 : }
194 0 : return NULL;
195 : }
196 0 : return php_stream_alloc(&php_stream_input_ops, ecalloc(1, sizeof(off_t)), 0, "rb");
197 : }
198 :
199 111 : if (!strcasecmp(path, "stdin")) {
200 1 : if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
201 0 : if (options & REPORT_ERRORS) {
202 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
203 : }
204 0 : return NULL;
205 : }
206 1 : if (!strcmp(sapi_module.name, "cli")) {
207 : static int cli_in = 0;
208 1 : fd = STDIN_FILENO;
209 1 : if (cli_in) {
210 0 : fd = dup(fd);
211 : } else {
212 1 : cli_in = 1;
213 : }
214 : } else {
215 0 : fd = dup(STDIN_FILENO);
216 : }
217 110 : } else if (!strcasecmp(path, "stdout")) {
218 109 : if (!strcmp(sapi_module.name, "cli")) {
219 : static int cli_out = 0;
220 1 : fd = STDOUT_FILENO;
221 1 : if (cli_out++) {
222 0 : fd = dup(fd);
223 : } else {
224 1 : cli_out = 1;
225 : }
226 : } else {
227 108 : fd = dup(STDOUT_FILENO);
228 : }
229 1 : } else if (!strcasecmp(path, "stderr")) {
230 1 : if (!strcmp(sapi_module.name, "cli")) {
231 : static int cli_err = 0;
232 1 : fd = STDERR_FILENO;
233 1 : if (cli_err++) {
234 0 : fd = dup(fd);
235 : } else {
236 1 : cli_err = 1;
237 : }
238 : } else {
239 0 : fd = dup(STDERR_FILENO);
240 : }
241 0 : } else if (!strncasecmp(path, "filter/", 7)) {
242 : /* Save time/memory when chain isn't specified */
243 0 : if (strchr(mode, 'r') || strchr(mode, '+')) {
244 0 : mode_rw |= PHP_STREAM_FILTER_READ;
245 : }
246 0 : if (strchr(mode, 'w') || strchr(mode, '+') || strchr(mode, 'a')) {
247 0 : mode_rw |= PHP_STREAM_FILTER_WRITE;
248 : }
249 0 : pathdup = estrndup(path + 6, strlen(path + 6));
250 0 : p = strstr(pathdup, "/resource=");
251 0 : if (!p) {
252 0 : php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "No URL resource specified.");
253 0 : efree(pathdup);
254 0 : return NULL;
255 : }
256 0 : if (!(stream = php_stream_open_wrapper(p + 10, mode, options, opened_path))) {
257 0 : efree(pathdup);
258 0 : return NULL;
259 : }
260 :
261 0 : *p = '\0';
262 :
263 0 : p = php_strtok_r(pathdup + 1, "/", &token);
264 0 : while (p) {
265 0 : if (!strncasecmp(p, "read=", 5)) {
266 0 : php_stream_apply_filter_list(stream, p + 5, 1, 0 TSRMLS_CC);
267 0 : } else if (!strncasecmp(p, "write=", 6)) {
268 0 : php_stream_apply_filter_list(stream, p + 6, 0, 1 TSRMLS_CC);
269 : } else {
270 0 : php_stream_apply_filter_list(stream, p, mode_rw & PHP_STREAM_FILTER_READ, mode_rw & PHP_STREAM_FILTER_WRITE TSRMLS_CC);
271 : }
272 0 : p = php_strtok_r(NULL, "/", &token);
273 : }
274 0 : efree(pathdup);
275 :
276 0 : return stream;
277 : } else {
278 : /* invalid php://thingy */
279 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid php:// URL specified");
280 0 : return NULL;
281 : }
282 :
283 : /* must be stdin, stderr or stdout */
284 111 : if (fd == -1) {
285 : /* failed to dup */
286 0 : return NULL;
287 : }
288 :
289 111 : stream = php_stream_fopen_from_fd(fd, mode, NULL);
290 111 : if (stream == NULL) {
291 0 : close(fd);
292 : }
293 :
294 111 : return stream;
295 : }
296 :
297 : static php_stream_wrapper_ops php_stdio_wops = {
298 : php_stream_url_wrap_php,
299 : NULL, /* close */
300 : NULL, /* fstat */
301 : NULL, /* stat */
302 : NULL, /* opendir */
303 : "PHP",
304 : NULL, /* unlink */
305 : NULL, /* rename */
306 : NULL, /* mkdir */
307 : NULL /* rmdir */
308 : };
309 :
310 : php_stream_wrapper php_stream_php_wrapper = {
311 : &php_stdio_wops,
312 : NULL,
313 : 0, /* is_url */
314 : };
315 :
316 :
317 : /*
318 : * Local variables:
319 : * tab-width: 4
320 : * c-basic-offset: 4
321 : * End:
322 : * vim600: sw=4 ts=4 fdm=marker
323 : * vim<600: sw=4 ts=4
324 : */
|