xref: /PHP-5.4/ext/standard/file.c (revision be9b2a95)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2014 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    |          Stig Bakken <ssb@php.net>                                   |
17    |          Andi Gutmans <andi@zend.com>                                |
18    |          Zeev Suraski <zeev@zend.com>                                |
19    | PHP 4.0 patches by Thies C. Arntzen (thies@thieso.net)               |
20    | PHP streams by Wez Furlong (wez@thebrainroom.com)                    |
21    +----------------------------------------------------------------------+
22 */
23 
24 /* $Id$ */
25 
26 /* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */
27 
28 /* {{{ includes */
29 
30 #include "php.h"
31 #include "php_globals.h"
32 #include "ext/standard/flock_compat.h"
33 #include "ext/standard/exec.h"
34 #include "ext/standard/php_filestat.h"
35 #include "php_open_temporary_file.h"
36 #include "ext/standard/basic_functions.h"
37 #include "php_ini.h"
38 #include "php_smart_str.h"
39 
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 
47 #ifdef PHP_WIN32
48 # include <io.h>
49 # define O_RDONLY _O_RDONLY
50 # include "win32/param.h"
51 # include "win32/winutil.h"
52 # include "win32/fnmatch.h"
53 #else
54 # if HAVE_SYS_PARAM_H
55 #  include <sys/param.h>
56 # endif
57 # if HAVE_SYS_SELECT_H
58 #  include <sys/select.h>
59 # endif
60 # if defined(NETWARE) && defined(USE_WINSOCK)
61 #  include <novsock2.h>
62 # else
63 #  include <sys/socket.h>
64 #  include <netinet/in.h>
65 #  include <netdb.h>
66 # endif
67 # if HAVE_ARPA_INET_H
68 #  include <arpa/inet.h>
69 # endif
70 #endif
71 
72 #include "ext/standard/head.h"
73 #include "php_string.h"
74 #include "file.h"
75 
76 #if HAVE_PWD_H
77 # ifdef PHP_WIN32
78 #  include "win32/pwd.h"
79 # else
80 #  include <pwd.h>
81 # endif
82 #endif
83 
84 #ifdef HAVE_SYS_TIME_H
85 # include <sys/time.h>
86 #endif
87 
88 #include "fsock.h"
89 #include "fopen_wrappers.h"
90 #include "streamsfuncs.h"
91 #include "php_globals.h"
92 
93 #ifdef HAVE_SYS_FILE_H
94 # include <sys/file.h>
95 #endif
96 
97 #if MISSING_FCLOSE_DECL
98 extern int fclose(FILE *);
99 #endif
100 
101 #ifdef HAVE_SYS_MMAN_H
102 # include <sys/mman.h>
103 #endif
104 
105 #include "scanf.h"
106 #include "zend_API.h"
107 
108 #ifdef ZTS
109 int file_globals_id;
110 #else
111 php_file_globals file_globals;
112 #endif
113 
114 #if defined(HAVE_FNMATCH) && !defined(PHP_WIN32)
115 # ifndef _GNU_SOURCE
116 #  define _GNU_SOURCE
117 # endif
118 # include <fnmatch.h>
119 #endif
120 
121 #ifdef HAVE_WCHAR_H
122 # include <wchar.h>
123 #endif
124 
125 #ifndef S_ISDIR
126 # define S_ISDIR(mode)	(((mode)&S_IFMT) == S_IFDIR)
127 #endif
128 /* }}} */
129 
130 #define PHP_STREAM_TO_ZVAL(stream, arg) \
131 	php_stream_from_zval_no_verify(stream, arg); \
132 	if (stream == NULL) {	\
133 		RETURN_FALSE;	\
134 	}
135 
136 /* {{{ ZTS-stuff / Globals / Prototypes */
137 
138 /* sharing globals is *evil* */
139 static int le_stream_context = FAILURE;
140 
php_le_stream_context(TSRMLS_D)141 PHPAPI int php_le_stream_context(TSRMLS_D)
142 {
143 	return le_stream_context;
144 }
145 /* }}} */
146 
147 /* {{{ Module-Stuff
148 */
ZEND_RSRC_DTOR_FUNC(file_context_dtor)149 static ZEND_RSRC_DTOR_FUNC(file_context_dtor)
150 {
151 	php_stream_context *context = (php_stream_context*)rsrc->ptr;
152 	if (context->options) {
153 		zval_ptr_dtor(&context->options);
154 		context->options = NULL;
155 	}
156 	php_stream_context_free(context);
157 }
158 
file_globals_ctor(php_file_globals * file_globals_p TSRMLS_DC)159 static void file_globals_ctor(php_file_globals *file_globals_p TSRMLS_DC)
160 {
161 	FG(pclose_ret) = 0;
162 	FG(user_stream_current_filename) = NULL;
163 	FG(def_chunk_size) = PHP_SOCK_CHUNK_SIZE;
164 	FG(wrapper_errors) = NULL;
165 }
166 
file_globals_dtor(php_file_globals * file_globals_p TSRMLS_DC)167 static void file_globals_dtor(php_file_globals *file_globals_p TSRMLS_DC)
168 {
169 }
170 
171 PHP_INI_BEGIN()
172 	STD_PHP_INI_ENTRY("user_agent", NULL, PHP_INI_ALL, OnUpdateString, user_agent, php_file_globals, file_globals)
173 	STD_PHP_INI_ENTRY("from", NULL, PHP_INI_ALL, OnUpdateString, from_address, php_file_globals, file_globals)
174 	STD_PHP_INI_ENTRY("default_socket_timeout", "60", PHP_INI_ALL, OnUpdateLong, default_socket_timeout, php_file_globals, file_globals)
175 	STD_PHP_INI_ENTRY("auto_detect_line_endings", "0", PHP_INI_ALL, OnUpdateLong, auto_detect_line_endings, php_file_globals, file_globals)
PHP_INI_END()176 PHP_INI_END()
177 
178 PHP_MINIT_FUNCTION(file)
179 {
180 	le_stream_context = zend_register_list_destructors_ex(file_context_dtor, NULL, "stream-context", module_number);
181 
182 #ifdef ZTS
183 	ts_allocate_id(&file_globals_id, sizeof(php_file_globals), (ts_allocate_ctor) file_globals_ctor, (ts_allocate_dtor) file_globals_dtor);
184 #else
185 	file_globals_ctor(&file_globals TSRMLS_CC);
186 #endif
187 
188 	REGISTER_INI_ENTRIES();
189 
190 	REGISTER_LONG_CONSTANT("SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
191 	REGISTER_LONG_CONSTANT("SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
192 	REGISTER_LONG_CONSTANT("SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
193 	REGISTER_LONG_CONSTANT("LOCK_SH", PHP_LOCK_SH, CONST_CS | CONST_PERSISTENT);
194 	REGISTER_LONG_CONSTANT("LOCK_EX", PHP_LOCK_EX, CONST_CS | CONST_PERSISTENT);
195 	REGISTER_LONG_CONSTANT("LOCK_UN", PHP_LOCK_UN, CONST_CS | CONST_PERSISTENT);
196 	REGISTER_LONG_CONSTANT("LOCK_NB", PHP_LOCK_NB, CONST_CS | CONST_PERSISTENT);
197 
198 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_CONNECT",			PHP_STREAM_NOTIFY_CONNECT,			CONST_CS | CONST_PERSISTENT);
199 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_REQUIRED",	PHP_STREAM_NOTIFY_AUTH_REQUIRED,	CONST_CS | CONST_PERSISTENT);
200 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_RESULT",		PHP_STREAM_NOTIFY_AUTH_RESULT,		CONST_CS | CONST_PERSISTENT);
201 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_MIME_TYPE_IS",	PHP_STREAM_NOTIFY_MIME_TYPE_IS,		CONST_CS | CONST_PERSISTENT);
202 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FILE_SIZE_IS",	PHP_STREAM_NOTIFY_FILE_SIZE_IS,		CONST_CS | CONST_PERSISTENT);
203 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_REDIRECTED",		PHP_STREAM_NOTIFY_REDIRECTED,		CONST_CS | CONST_PERSISTENT);
204 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_PROGRESS",		PHP_STREAM_NOTIFY_PROGRESS,			CONST_CS | CONST_PERSISTENT);
205 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FAILURE",			PHP_STREAM_NOTIFY_FAILURE,			CONST_CS | CONST_PERSISTENT);
206 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_COMPLETED",		PHP_STREAM_NOTIFY_COMPLETED,		CONST_CS | CONST_PERSISTENT);
207 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_RESOLVE",			PHP_STREAM_NOTIFY_RESOLVE,			CONST_CS | CONST_PERSISTENT);
208 
209 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_INFO",	PHP_STREAM_NOTIFY_SEVERITY_INFO,	CONST_CS | CONST_PERSISTENT);
210 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_WARN",	PHP_STREAM_NOTIFY_SEVERITY_WARN,	CONST_CS | CONST_PERSISTENT);
211 	REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_ERR",	PHP_STREAM_NOTIFY_SEVERITY_ERR,		CONST_CS | CONST_PERSISTENT);
212 
213 	REGISTER_LONG_CONSTANT("STREAM_FILTER_READ",			PHP_STREAM_FILTER_READ,				CONST_CS | CONST_PERSISTENT);
214 	REGISTER_LONG_CONSTANT("STREAM_FILTER_WRITE",			PHP_STREAM_FILTER_WRITE,			CONST_CS | CONST_PERSISTENT);
215 	REGISTER_LONG_CONSTANT("STREAM_FILTER_ALL",				PHP_STREAM_FILTER_ALL,				CONST_CS | CONST_PERSISTENT);
216 
217 	REGISTER_LONG_CONSTANT("STREAM_CLIENT_PERSISTENT",		PHP_STREAM_CLIENT_PERSISTENT,		CONST_CS | CONST_PERSISTENT);
218 	REGISTER_LONG_CONSTANT("STREAM_CLIENT_ASYNC_CONNECT",	PHP_STREAM_CLIENT_ASYNC_CONNECT,	CONST_CS | CONST_PERSISTENT);
219 	REGISTER_LONG_CONSTANT("STREAM_CLIENT_CONNECT",			PHP_STREAM_CLIENT_CONNECT,	CONST_CS | CONST_PERSISTENT);
220 
221 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_CLIENT",		STREAM_CRYPTO_METHOD_SSLv2_CLIENT,	CONST_CS|CONST_PERSISTENT);
222 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_CLIENT",		STREAM_CRYPTO_METHOD_SSLv3_CLIENT,	CONST_CS|CONST_PERSISTENT);
223 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_CLIENT",	STREAM_CRYPTO_METHOD_SSLv23_CLIENT,	CONST_CS|CONST_PERSISTENT);
224 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_CLIENT",		STREAM_CRYPTO_METHOD_TLS_CLIENT,	CONST_CS|CONST_PERSISTENT);
225 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER",		STREAM_CRYPTO_METHOD_SSLv2_SERVER,	CONST_CS|CONST_PERSISTENT);
226 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER",		STREAM_CRYPTO_METHOD_SSLv3_SERVER,	CONST_CS|CONST_PERSISTENT);
227 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_SERVER",	STREAM_CRYPTO_METHOD_SSLv23_SERVER,	CONST_CS|CONST_PERSISTENT);
228 	REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_SERVER",		STREAM_CRYPTO_METHOD_TLS_SERVER,	CONST_CS|CONST_PERSISTENT);
229 
230 	REGISTER_LONG_CONSTANT("STREAM_SHUT_RD",	STREAM_SHUT_RD,		CONST_CS|CONST_PERSISTENT);
231 	REGISTER_LONG_CONSTANT("STREAM_SHUT_WR",	STREAM_SHUT_WR,		CONST_CS|CONST_PERSISTENT);
232 	REGISTER_LONG_CONSTANT("STREAM_SHUT_RDWR",	STREAM_SHUT_RDWR,	CONST_CS|CONST_PERSISTENT);
233 
234 #ifdef PF_INET
235 	REGISTER_LONG_CONSTANT("STREAM_PF_INET", PF_INET, CONST_CS|CONST_PERSISTENT);
236 #elif defined(AF_INET)
237 	REGISTER_LONG_CONSTANT("STREAM_PF_INET", AF_INET, CONST_CS|CONST_PERSISTENT);
238 #endif
239 
240 #if HAVE_IPV6
241 # ifdef PF_INET6
242 	REGISTER_LONG_CONSTANT("STREAM_PF_INET6", PF_INET6, CONST_CS|CONST_PERSISTENT);
243 # elif defined(AF_INET6)
244 	REGISTER_LONG_CONSTANT("STREAM_PF_INET6", AF_INET6, CONST_CS|CONST_PERSISTENT);
245 # endif
246 #endif
247 
248 #ifdef PF_UNIX
249 	REGISTER_LONG_CONSTANT("STREAM_PF_UNIX", PF_UNIX, CONST_CS|CONST_PERSISTENT);
250 #elif defined(AF_UNIX)
251 	REGISTER_LONG_CONSTANT("STREAM_PF_UNIX", AF_UNIX, CONST_CS|CONST_PERSISTENT);
252 #endif
253 
254 #ifdef IPPROTO_IP
255 	/* most people will use this one when calling socket() or socketpair() */
256 	REGISTER_LONG_CONSTANT("STREAM_IPPROTO_IP", IPPROTO_IP, CONST_CS|CONST_PERSISTENT);
257 #endif
258 
259 #ifdef IPPROTO_TCP
260 	REGISTER_LONG_CONSTANT("STREAM_IPPROTO_TCP", IPPROTO_TCP, CONST_CS|CONST_PERSISTENT);
261 #endif
262 
263 #ifdef IPPROTO_UDP
264 	REGISTER_LONG_CONSTANT("STREAM_IPPROTO_UDP", IPPROTO_UDP, CONST_CS|CONST_PERSISTENT);
265 #endif
266 
267 #ifdef IPPROTO_ICMP
268 	REGISTER_LONG_CONSTANT("STREAM_IPPROTO_ICMP", IPPROTO_ICMP, CONST_CS|CONST_PERSISTENT);
269 #endif
270 
271 #ifdef IPPROTO_RAW
272 	REGISTER_LONG_CONSTANT("STREAM_IPPROTO_RAW", IPPROTO_RAW, CONST_CS|CONST_PERSISTENT);
273 #endif
274 
275 	REGISTER_LONG_CONSTANT("STREAM_SOCK_STREAM", SOCK_STREAM, CONST_CS|CONST_PERSISTENT);
276 	REGISTER_LONG_CONSTANT("STREAM_SOCK_DGRAM", SOCK_DGRAM, CONST_CS|CONST_PERSISTENT);
277 
278 #ifdef SOCK_RAW
279 	REGISTER_LONG_CONSTANT("STREAM_SOCK_RAW", SOCK_RAW, CONST_CS|CONST_PERSISTENT);
280 #endif
281 
282 #ifdef SOCK_SEQPACKET
283 	REGISTER_LONG_CONSTANT("STREAM_SOCK_SEQPACKET", SOCK_SEQPACKET, CONST_CS|CONST_PERSISTENT);
284 #endif
285 
286 #ifdef SOCK_RDM
287 	REGISTER_LONG_CONSTANT("STREAM_SOCK_RDM", SOCK_RDM, CONST_CS|CONST_PERSISTENT);
288 #endif
289 
290 	REGISTER_LONG_CONSTANT("STREAM_PEEK", STREAM_PEEK, CONST_CS | CONST_PERSISTENT);
291 	REGISTER_LONG_CONSTANT("STREAM_OOB",  STREAM_OOB, CONST_CS | CONST_PERSISTENT);
292 
293 	REGISTER_LONG_CONSTANT("STREAM_SERVER_BIND",			STREAM_XPORT_BIND,					CONST_CS | CONST_PERSISTENT);
294 	REGISTER_LONG_CONSTANT("STREAM_SERVER_LISTEN",			STREAM_XPORT_LISTEN,				CONST_CS | CONST_PERSISTENT);
295 
296 	REGISTER_LONG_CONSTANT("FILE_USE_INCLUDE_PATH",			PHP_FILE_USE_INCLUDE_PATH,			CONST_CS | CONST_PERSISTENT);
297 	REGISTER_LONG_CONSTANT("FILE_IGNORE_NEW_LINES",			PHP_FILE_IGNORE_NEW_LINES,			CONST_CS | CONST_PERSISTENT);
298 	REGISTER_LONG_CONSTANT("FILE_SKIP_EMPTY_LINES",			PHP_FILE_SKIP_EMPTY_LINES,			CONST_CS | CONST_PERSISTENT);
299 	REGISTER_LONG_CONSTANT("FILE_APPEND",					PHP_FILE_APPEND,					CONST_CS | CONST_PERSISTENT);
300 	REGISTER_LONG_CONSTANT("FILE_NO_DEFAULT_CONTEXT",		PHP_FILE_NO_DEFAULT_CONTEXT,		CONST_CS | CONST_PERSISTENT);
301 
302 	REGISTER_LONG_CONSTANT("FILE_TEXT",						0,									CONST_CS | CONST_PERSISTENT);
303 	REGISTER_LONG_CONSTANT("FILE_BINARY",					0,									CONST_CS | CONST_PERSISTENT);
304 
305 #ifdef HAVE_FNMATCH
306 	REGISTER_LONG_CONSTANT("FNM_NOESCAPE", FNM_NOESCAPE, CONST_CS | CONST_PERSISTENT);
307 	REGISTER_LONG_CONSTANT("FNM_PATHNAME", FNM_PATHNAME, CONST_CS | CONST_PERSISTENT);
308 	REGISTER_LONG_CONSTANT("FNM_PERIOD",   FNM_PERIOD,   CONST_CS | CONST_PERSISTENT);
309 # ifdef FNM_CASEFOLD /* a GNU extension */ /* TODO emulate if not available */
310 	REGISTER_LONG_CONSTANT("FNM_CASEFOLD", FNM_CASEFOLD, CONST_CS | CONST_PERSISTENT);
311 # endif
312 #endif
313 
314 	return SUCCESS;
315 }
316 /* }}} */
317 
PHP_MSHUTDOWN_FUNCTION(file)318 PHP_MSHUTDOWN_FUNCTION(file) /* {{{ */
319 {
320 #ifndef ZTS
321 	file_globals_dtor(&file_globals TSRMLS_CC);
322 #endif
323 	return SUCCESS;
324 }
325 /* }}} */
326 
327 static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN };
328 
329 /* {{{ proto bool flock(resource fp, int operation [, int &wouldblock])
330    Portable file locking */
PHP_FUNCTION(flock)331 PHP_FUNCTION(flock)
332 {
333 	zval *arg1, *arg3 = NULL;
334 	int act;
335 	php_stream *stream;
336 	long operation = 0;
337 
338 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &arg1, &operation, &arg3) == FAILURE) {
339 		return;
340 	}
341 
342 	PHP_STREAM_TO_ZVAL(stream, &arg1);
343 
344 	act = operation & 3;
345 	if (act < 1 || act > 3) {
346 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal operation argument");
347 		RETURN_FALSE;
348 	}
349 
350 	if (arg3 && PZVAL_IS_REF(arg3)) {
351 		convert_to_long_ex(&arg3);
352 		Z_LVAL_P(arg3) = 0;
353 	}
354 
355 	/* flock_values contains all possible actions if (operation & 4) we won't block on the lock */
356 	act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0);
357 	if (php_stream_lock(stream, act)) {
358 		if (operation && errno == EWOULDBLOCK && arg3 && PZVAL_IS_REF(arg3)) {
359 			Z_LVAL_P(arg3) = 1;
360 		}
361 		RETURN_FALSE;
362 	}
363 	RETURN_TRUE;
364 }
365 /* }}} */
366 
367 #define PHP_META_UNSAFE ".\\+*?[^]$() "
368 
369 /* {{{ proto array get_meta_tags(string filename [, bool use_include_path])
370    Extracts all meta tag content attributes from a file and returns an array */
PHP_FUNCTION(get_meta_tags)371 PHP_FUNCTION(get_meta_tags)
372 {
373 	char *filename;
374 	int filename_len;
375 	zend_bool use_include_path = 0;
376 	int in_tag = 0, done = 0;
377 	int looking_for_val = 0, have_name = 0, have_content = 0;
378 	int saw_name = 0, saw_content = 0;
379 	char *name = NULL, *value = NULL, *temp = NULL;
380 	php_meta_tags_token tok, tok_last;
381 	php_meta_tags_data md;
382 
383 	/* Initiailize our structure */
384 	memset(&md, 0, sizeof(md));
385 
386 	/* Parse arguments */
387 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &filename, &filename_len, &use_include_path) == FAILURE) {
388 		return;
389 	}
390 
391 	md.stream = php_stream_open_wrapper(filename, "rb",
392 			(use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
393 			NULL);
394 	if (!md.stream)	{
395 		RETURN_FALSE;
396 	}
397 
398 	array_init(return_value);
399 
400 	tok_last = TOK_EOF;
401 
402 	while (!done && (tok = php_next_meta_token(&md TSRMLS_CC)) != TOK_EOF) {
403 		if (tok == TOK_ID) {
404 			if (tok_last == TOK_OPENTAG) {
405 				md.in_meta = !strcasecmp("meta", md.token_data);
406 			} else if (tok_last == TOK_SLASH && in_tag) {
407 				if (strcasecmp("head", md.token_data) == 0) {
408 					/* We are done here! */
409 					done = 1;
410 				}
411 			} else if (tok_last == TOK_EQUAL && looking_for_val) {
412 				if (saw_name) {
413 					STR_FREE(name);
414 					/* Get the NAME attr (Single word attr, non-quoted) */
415 					temp = name = estrndup(md.token_data, md.token_len);
416 
417 					while (temp && *temp) {
418 						if (strchr(PHP_META_UNSAFE, *temp)) {
419 							*temp = '_';
420 						}
421 						temp++;
422 					}
423 
424 					have_name = 1;
425 				} else if (saw_content) {
426 					STR_FREE(value);
427 					value = estrndup(md.token_data, md.token_len);
428 					have_content = 1;
429 				}
430 
431 				looking_for_val = 0;
432 			} else {
433 				if (md.in_meta) {
434 					if (strcasecmp("name", md.token_data) == 0) {
435 						saw_name = 1;
436 						saw_content = 0;
437 						looking_for_val = 1;
438 					} else if (strcasecmp("content", md.token_data) == 0) {
439 						saw_name = 0;
440 						saw_content = 1;
441 						looking_for_val = 1;
442 					}
443 				}
444 			}
445 		} else if (tok == TOK_STRING && tok_last == TOK_EQUAL && looking_for_val) {
446 			if (saw_name) {
447 				STR_FREE(name);
448 				/* Get the NAME attr (Quoted single/double) */
449 				temp = name = estrndup(md.token_data, md.token_len);
450 
451 				while (temp && *temp) {
452 					if (strchr(PHP_META_UNSAFE, *temp)) {
453 						*temp = '_';
454 					}
455 					temp++;
456 				}
457 
458 				have_name = 1;
459 			} else if (saw_content) {
460 				STR_FREE(value);
461 				value = estrndup(md.token_data, md.token_len);
462 				have_content = 1;
463 			}
464 
465 			looking_for_val = 0;
466 		} else if (tok == TOK_OPENTAG) {
467 			if (looking_for_val) {
468 				looking_for_val = 0;
469 				have_name = saw_name = 0;
470 				have_content = saw_content = 0;
471 			}
472 			in_tag = 1;
473 		} else if (tok == TOK_CLOSETAG) {
474 			if (have_name) {
475 				/* For BC */
476 				php_strtolower(name, strlen(name));
477 				if (have_content) {
478 					add_assoc_string(return_value, name, value, 1);
479 				} else {
480 					add_assoc_string(return_value, name, "", 1);
481 				}
482 
483 				efree(name);
484 				STR_FREE(value);
485 			} else if (have_content) {
486 				efree(value);
487 			}
488 
489 			name = value = NULL;
490 
491 			/* Reset all of our flags */
492 			in_tag = looking_for_val = 0;
493 			have_name = saw_name = 0;
494 			have_content = saw_content = 0;
495 			md.in_meta = 0;
496 		}
497 
498 		tok_last = tok;
499 
500 		if (md.token_data)
501 			efree(md.token_data);
502 
503 		md.token_data = NULL;
504 	}
505 
506 	STR_FREE(value);
507 	STR_FREE(name);
508 	php_stream_close(md.stream);
509 }
510 /* }}} */
511 
512 /* {{{ proto string file_get_contents(string filename [, bool use_include_path [, resource context [, long offset [, long maxlen]]]])
513    Read the entire file into a string */
PHP_FUNCTION(file_get_contents)514 PHP_FUNCTION(file_get_contents)
515 {
516 	char *filename;
517 	int filename_len;
518 	char *contents;
519 	zend_bool use_include_path = 0;
520 	php_stream *stream;
521 	long len;
522 	long offset = -1;
523 	long maxlen = PHP_STREAM_COPY_ALL;
524 	zval *zcontext = NULL;
525 	php_stream_context *context = NULL;
526 
527 	/* Parse arguments */
528 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
529 		return;
530 	}
531 
532 	if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
533 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero");
534 		RETURN_FALSE;
535 	}
536 
537 	context = php_stream_context_from_zval(zcontext, 0);
538 
539 	stream = php_stream_open_wrapper_ex(filename, "rb",
540 				(use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
541 				NULL, context);
542 	if (!stream) {
543 		RETURN_FALSE;
544 	}
545 
546 	if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
547 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek to position %ld in the stream", offset);
548 		php_stream_close(stream);
549 		RETURN_FALSE;
550 	}
551 
552 	if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) {
553 		if (len > INT_MAX) {
554 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "content truncated from %ld to %d bytes", len, INT_MAX);
555 			len = INT_MAX;
556 		}
557 		RETVAL_STRINGL(contents, len, 0);
558 	} else if (len == 0) {
559 		RETVAL_EMPTY_STRING();
560 	} else {
561 		RETVAL_FALSE;
562 	}
563 
564 	php_stream_close(stream);
565 }
566 /* }}} */
567 
568 /* {{{ proto int file_put_contents(string file, mixed data [, int flags [, resource context]])
569    Write/Create a file with contents data and return the number of bytes written */
PHP_FUNCTION(file_put_contents)570 PHP_FUNCTION(file_put_contents)
571 {
572 	php_stream *stream;
573 	char *filename;
574 	int filename_len;
575 	zval *data;
576 	long numbytes = 0;
577 	long flags = 0;
578 	zval *zcontext = NULL;
579 	php_stream_context *context = NULL;
580 	php_stream *srcstream = NULL;
581 	char mode[3] = "wb";
582 
583 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/|lr!", &filename, &filename_len, &data, &flags, &zcontext) == FAILURE) {
584 		return;
585 	}
586 
587 	if (Z_TYPE_P(data) == IS_RESOURCE) {
588 		php_stream_from_zval(srcstream, &data);
589 	}
590 
591 	context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
592 
593 	if (flags & PHP_FILE_APPEND) {
594 		mode[0] = 'a';
595 	} else if (flags & LOCK_EX) {
596 		/* check to make sure we are dealing with a regular file */
597 		if (php_memnstr(filename, "://", sizeof("://") - 1, filename + filename_len)) {
598 			if (strncasecmp(filename, "file://", sizeof("file://") - 1)) {
599 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Exclusive locks may only be set for regular files");
600 				RETURN_FALSE;
601 			}
602 		}
603 		mode[0] = 'c';
604 	}
605 	mode[2] = '\0';
606 
607 	stream = php_stream_open_wrapper_ex(filename, mode, ((flags & PHP_FILE_USE_INCLUDE_PATH) ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
608 	if (stream == NULL) {
609 		RETURN_FALSE;
610 	}
611 
612 	if (flags & LOCK_EX && (!php_stream_supports_lock(stream) || php_stream_lock(stream, LOCK_EX))) {
613 		php_stream_close(stream);
614 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Exclusive locks are not supported for this stream");
615 		RETURN_FALSE;
616 	}
617 
618 	if (mode[0] == 'c') {
619 		php_stream_truncate_set_size(stream, 0);
620 	}
621 
622 	switch (Z_TYPE_P(data)) {
623 		case IS_RESOURCE: {
624 			size_t len;
625 			if (php_stream_copy_to_stream_ex(srcstream, stream, PHP_STREAM_COPY_ALL, &len) != SUCCESS) {
626 				numbytes = -1;
627 			} else {
628 				if (len > LONG_MAX) {
629 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "content truncated from %lu to %ld bytes", (unsigned long) len, LONG_MAX);
630 					len = LONG_MAX;
631 				}
632 				numbytes = len;
633 			}
634 			break;
635 		}
636 		case IS_NULL:
637 		case IS_LONG:
638 		case IS_DOUBLE:
639 		case IS_BOOL:
640 		case IS_CONSTANT:
641 			convert_to_string_ex(&data);
642 
643 		case IS_STRING:
644 			if (Z_STRLEN_P(data)) {
645 				numbytes = php_stream_write(stream, Z_STRVAL_P(data), Z_STRLEN_P(data));
646 				if (numbytes != Z_STRLEN_P(data)) {
647 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %ld of %d bytes written, possibly out of free disk space", numbytes, Z_STRLEN_P(data));
648 					numbytes = -1;
649 				}
650 			}
651 			break;
652 
653 		case IS_ARRAY:
654 			if (zend_hash_num_elements(Z_ARRVAL_P(data))) {
655 				int bytes_written;
656 				zval **tmp;
657 				HashPosition pos;
658 
659 				zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(data), &pos);
660 				while (zend_hash_get_current_data_ex(Z_ARRVAL_P(data), (void **) &tmp, &pos) == SUCCESS) {
661 					if (Z_TYPE_PP(tmp) != IS_STRING) {
662 						SEPARATE_ZVAL(tmp);
663 						convert_to_string(*tmp);
664 					}
665 					if (Z_STRLEN_PP(tmp)) {
666 						numbytes += Z_STRLEN_PP(tmp);
667 						bytes_written = php_stream_write(stream, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
668 						if (bytes_written < 0 || bytes_written != Z_STRLEN_PP(tmp)) {
669 							if (bytes_written < 0) {
670 								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write %d bytes to %s", Z_STRLEN_PP(tmp), filename);
671 							} else {
672 								php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", bytes_written, Z_STRLEN_PP(tmp));
673 							}
674 							numbytes = -1;
675 							break;
676 						}
677 					}
678 					zend_hash_move_forward_ex(Z_ARRVAL_P(data), &pos);
679 				}
680 			}
681 			break;
682 
683 		case IS_OBJECT:
684 			if (Z_OBJ_HT_P(data) != NULL) {
685 				zval out;
686 
687 				if (zend_std_cast_object_tostring(data, &out, IS_STRING TSRMLS_CC) == SUCCESS) {
688 					numbytes = php_stream_write(stream, Z_STRVAL(out), Z_STRLEN(out));
689 					if (numbytes != Z_STRLEN(out)) {
690 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %ld of %d bytes written, possibly out of free disk space", numbytes, Z_STRLEN(out));
691 						numbytes = -1;
692 					}
693 					zval_dtor(&out);
694 					break;
695 				}
696 			}
697 		default:
698 			numbytes = -1;
699 			break;
700 	}
701 	php_stream_close(stream);
702 
703 	if (numbytes < 0) {
704 		RETURN_FALSE;
705 	}
706 
707 	RETURN_LONG(numbytes);
708 }
709 /* }}} */
710 
711 #define PHP_FILE_BUF_SIZE	80
712 
713 /* {{{ proto array file(string filename [, int flags[, resource context]])
714    Read entire file into an array */
PHP_FUNCTION(file)715 PHP_FUNCTION(file)
716 {
717 	char *filename;
718 	int filename_len;
719 	char *target_buf=NULL, *p, *s, *e;
720 	register int i = 0;
721 	int target_len;
722 	char eol_marker = '\n';
723 	long flags = 0;
724 	zend_bool use_include_path;
725 	zend_bool include_new_line;
726 	zend_bool skip_blank_lines;
727 	php_stream *stream;
728 	zval *zcontext = NULL;
729 	php_stream_context *context = NULL;
730 
731 	/* Parse arguments */
732 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lr!", &filename, &filename_len, &flags, &zcontext) == FAILURE) {
733 		return;
734 	}
735 	if (flags < 0 || flags > (PHP_FILE_USE_INCLUDE_PATH | PHP_FILE_IGNORE_NEW_LINES | PHP_FILE_SKIP_EMPTY_LINES | PHP_FILE_NO_DEFAULT_CONTEXT)) {
736 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%ld' flag is not supported", flags);
737 		RETURN_FALSE;
738 	}
739 
740 	use_include_path = flags & PHP_FILE_USE_INCLUDE_PATH;
741 	include_new_line = !(flags & PHP_FILE_IGNORE_NEW_LINES);
742 	skip_blank_lines = flags & PHP_FILE_SKIP_EMPTY_LINES;
743 
744 	context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
745 
746 	stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
747 	if (!stream) {
748 		RETURN_FALSE;
749 	}
750 
751 	/* Initialize return array */
752 	array_init(return_value);
753 
754 	if ((target_len = php_stream_copy_to_mem(stream, &target_buf, PHP_STREAM_COPY_ALL, 0))) {
755 		s = target_buf;
756 		e = target_buf + target_len;
757 
758 		if (!(p = php_stream_locate_eol(stream, target_buf, target_len TSRMLS_CC))) {
759 			p = e;
760 			goto parse_eol;
761 		}
762 
763 		if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) {
764 			eol_marker = '\r';
765 		}
766 
767 		/* for performance reasons the code is duplicated, so that the if (include_new_line)
768 		 * will not need to be done for every single line in the file. */
769 		if (include_new_line) {
770 			do {
771 				p++;
772 parse_eol:
773 				add_index_stringl(return_value, i++, estrndup(s, p-s), p-s, 0);
774 				s = p;
775 			} while ((p = memchr(p, eol_marker, (e-p))));
776 		} else {
777 			do {
778 				int windows_eol = 0;
779 				if (p != target_buf && eol_marker == '\n' && *(p - 1) == '\r') {
780 					windows_eol++;
781 				}
782 				if (skip_blank_lines && !(p-s-windows_eol)) {
783 					s = ++p;
784 					continue;
785 				}
786 				add_index_stringl(return_value, i++, estrndup(s, p-s-windows_eol), p-s-windows_eol, 0);
787 				s = ++p;
788 			} while ((p = memchr(p, eol_marker, (e-p))));
789 		}
790 
791 		/* handle any left overs of files without new lines */
792 		if (s != e) {
793 			p = e;
794 			goto parse_eol;
795 		}
796 	}
797 
798 	if (target_buf) {
799 		efree(target_buf);
800 	}
801 	php_stream_close(stream);
802 }
803 /* }}} */
804 
805 /* {{{ proto string tempnam(string dir, string prefix)
806    Create a unique filename in a directory */
PHP_FUNCTION(tempnam)807 PHP_FUNCTION(tempnam)
808 {
809 	char *dir, *prefix;
810 	int dir_len, prefix_len;
811 	size_t p_len;
812 	char *opened_path;
813 	char *p;
814 	int fd;
815 
816 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
817 		return;
818 	}
819 
820 	if (php_check_open_basedir(dir TSRMLS_CC)) {
821 		RETURN_FALSE;
822 	}
823 
824 	php_basename(prefix, prefix_len, NULL, 0, &p, &p_len TSRMLS_CC);
825 	if (p_len > 64) {
826 		p[63] = '\0';
827 	}
828 
829 	RETVAL_FALSE;
830 
831 	if ((fd = php_open_temporary_fd_ex(dir, p, &opened_path, 1 TSRMLS_CC)) >= 0) {
832 		close(fd);
833 		RETVAL_STRING(opened_path, 0);
834 	}
835 	efree(p);
836 }
837 /* }}} */
838 
839 /* {{{ proto resource tmpfile(void)
840    Create a temporary file that will be deleted automatically after use */
PHP_NAMED_FUNCTION(php_if_tmpfile)841 PHP_NAMED_FUNCTION(php_if_tmpfile)
842 {
843 	php_stream *stream;
844 
845 	if (zend_parse_parameters_none() == FAILURE) {
846 		return;
847 	}
848 
849 	stream = php_stream_fopen_tmpfile();
850 
851 	if (stream) {
852 		php_stream_to_zval(stream, return_value);
853 	} else {
854 		RETURN_FALSE;
855 	}
856 }
857 /* }}} */
858 
859 /* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]])
860    Open a file or a URL and return a file pointer */
PHP_NAMED_FUNCTION(php_if_fopen)861 PHP_NAMED_FUNCTION(php_if_fopen)
862 {
863 	char *filename, *mode;
864 	int filename_len, mode_len;
865 	zend_bool use_include_path = 0;
866 	zval *zcontext = NULL;
867 	php_stream *stream;
868 	php_stream_context *context = NULL;
869 
870 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
871 		RETURN_FALSE;
872 	}
873 
874 	context = php_stream_context_from_zval(zcontext, 0);
875 
876 	stream = php_stream_open_wrapper_ex(filename, mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
877 
878 	if (stream == NULL) {
879 		RETURN_FALSE;
880 	}
881 
882 	php_stream_to_zval(stream, return_value);
883 }
884 /* }}} */
885 
886 /* {{{ proto bool fclose(resource fp)
887    Close an open file pointer */
PHP_FUNCTION(fclose)888 PHPAPI PHP_FUNCTION(fclose)
889 {
890 	zval *arg1;
891 	php_stream *stream;
892 
893 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
894 		RETURN_FALSE;
895 	}
896 
897 	PHP_STREAM_TO_ZVAL(stream, &arg1);
898 
899 	if ((stream->flags & PHP_STREAM_FLAG_NO_FCLOSE) != 0) {
900 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d is not a valid stream resource", stream->rsrc_id);
901 		RETURN_FALSE;
902 	}
903 
904 	if (!stream->is_persistent) {
905 		php_stream_close(stream);
906 	} else {
907 		php_stream_pclose(stream);
908 	}
909 
910 	RETURN_TRUE;
911 }
912 /* }}} */
913 
914 /* {{{ proto resource popen(string command, string mode)
915    Execute a command and open either a read or a write pipe to it */
PHP_FUNCTION(popen)916 PHP_FUNCTION(popen)
917 {
918 	char *command, *mode;
919 	int command_len, mode_len;
920 	FILE *fp;
921 	php_stream *stream;
922 	char *posix_mode;
923 
924 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps", &command, &command_len, &mode, &mode_len) == FAILURE) {
925 		return;
926 	}
927 
928 	posix_mode = estrndup(mode, mode_len);
929 #ifndef PHP_WIN32
930 	{
931 		char *z = memchr(posix_mode, 'b', mode_len);
932 		if (z) {
933 			memmove(z, z + 1, mode_len - (z - posix_mode));
934 		}
935 	}
936 #endif
937 
938 	fp = VCWD_POPEN(command, posix_mode);
939 	if (!fp) {
940 		php_error_docref2(NULL TSRMLS_CC, command, posix_mode, E_WARNING, "%s", strerror(errno));
941 		efree(posix_mode);
942 		RETURN_FALSE;
943 	}
944 
945 	stream = php_stream_fopen_from_pipe(fp, mode);
946 
947 	if (stream == NULL)	{
948 		php_error_docref2(NULL TSRMLS_CC, command, mode, E_WARNING, "%s", strerror(errno));
949 		RETVAL_FALSE;
950 	} else {
951 		php_stream_to_zval(stream, return_value);
952 	}
953 
954 	efree(posix_mode);
955 }
956 /* }}} */
957 
958 /* {{{ proto int pclose(resource fp)
959    Close a file pointer opened by popen() */
PHP_FUNCTION(pclose)960 PHP_FUNCTION(pclose)
961 {
962 	zval *arg1;
963 	php_stream *stream;
964 
965 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
966 		RETURN_FALSE;
967 	}
968 
969 	PHP_STREAM_TO_ZVAL(stream, &arg1);
970 
971 	zend_list_delete(stream->rsrc_id);
972 	RETURN_LONG(FG(pclose_ret));
973 }
974 /* }}} */
975 
976 /* {{{ proto bool feof(resource fp)
977    Test for end-of-file on a file pointer */
PHP_FUNCTION(feof)978 PHPAPI PHP_FUNCTION(feof)
979 {
980 	zval *arg1;
981 	php_stream *stream;
982 
983 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
984 		RETURN_FALSE;
985 	}
986 
987 	PHP_STREAM_TO_ZVAL(stream, &arg1);
988 
989 	if (php_stream_eof(stream)) {
990 		RETURN_TRUE;
991 	} else {
992 		RETURN_FALSE;
993 	}
994 }
995 /* }}} */
996 
997 /* {{{ proto string fgets(resource fp[, int length])
998    Get a line from file pointer */
PHP_FUNCTION(fgets)999 PHPAPI PHP_FUNCTION(fgets)
1000 {
1001 	zval *arg1;
1002 	long len = 1024;
1003 	char *buf = NULL;
1004 	int argc = ZEND_NUM_ARGS();
1005 	size_t line_len = 0;
1006 	php_stream *stream;
1007 
1008 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &arg1, &len) == FAILURE) {
1009 		RETURN_FALSE;
1010 	}
1011 
1012 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1013 
1014 	if (argc == 1) {
1015 		/* ask streams to give us a buffer of an appropriate size */
1016 		buf = php_stream_get_line(stream, NULL, 0, &line_len);
1017 		if (buf == NULL) {
1018 			goto exit_failed;
1019 		}
1020 	} else if (argc > 1) {
1021 		if (len <= 0) {
1022 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
1023 			RETURN_FALSE;
1024 		}
1025 
1026 		buf = ecalloc(len + 1, sizeof(char));
1027 		if (php_stream_get_line(stream, buf, len, &line_len) == NULL) {
1028 			goto exit_failed;
1029 		}
1030 	}
1031 
1032 	ZVAL_STRINGL(return_value, buf, line_len, 0);
1033 	/* resize buffer if it's much larger than the result.
1034 	 * Only needed if the user requested a buffer size. */
1035 	if (argc > 1 && Z_STRLEN_P(return_value) < len / 2) {
1036 		Z_STRVAL_P(return_value) = erealloc(buf, line_len + 1);
1037 	}
1038 	return;
1039 
1040 exit_failed:
1041 	RETVAL_FALSE;
1042 	if (buf) {
1043 		efree(buf);
1044 	}
1045 }
1046 /* }}} */
1047 
1048 /* {{{ proto string fgetc(resource fp)
1049    Get a character from file pointer */
PHP_FUNCTION(fgetc)1050 PHPAPI PHP_FUNCTION(fgetc)
1051 {
1052 	zval *arg1;
1053 	char buf[2];
1054 	int result;
1055 	php_stream *stream;
1056 
1057 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
1058 		RETURN_FALSE;
1059 	}
1060 
1061 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1062 
1063 	result = php_stream_getc(stream);
1064 
1065 	if (result == EOF) {
1066 		RETVAL_FALSE;
1067 	} else {
1068 		buf[0] = result;
1069 		buf[1] = '\0';
1070 
1071 		RETURN_STRINGL(buf, 1, 1);
1072 	}
1073 }
1074 /* }}} */
1075 
1076 /* {{{ proto string fgetss(resource fp [, int length [, string allowable_tags]])
1077    Get a line from file pointer and strip HTML tags */
PHP_FUNCTION(fgetss)1078 PHPAPI PHP_FUNCTION(fgetss)
1079 {
1080 	zval *fd;
1081 	long bytes = 0;
1082 	size_t len = 0;
1083 	size_t actual_len, retval_len;
1084 	char *buf = NULL, *retval;
1085 	php_stream *stream;
1086 	char *allowed_tags=NULL;
1087 	int allowed_tags_len=0;
1088 
1089 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ls", &fd, &bytes, &allowed_tags, &allowed_tags_len) == FAILURE) {
1090 		RETURN_FALSE;
1091 	}
1092 
1093 	PHP_STREAM_TO_ZVAL(stream, &fd);
1094 
1095 	if (ZEND_NUM_ARGS() >= 2) {
1096 		if (bytes <= 0) {
1097 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
1098 			RETURN_FALSE;
1099 		}
1100 
1101 		len = (size_t) bytes;
1102 		buf = safe_emalloc(sizeof(char), (len + 1), 0);
1103 		/*needed because recv doesnt set null char at end*/
1104 		memset(buf, 0, len + 1);
1105 	}
1106 
1107 	if ((retval = php_stream_get_line(stream, buf, len, &actual_len)) == NULL)	{
1108 		if (buf != NULL) {
1109 			efree(buf);
1110 		}
1111 		RETURN_FALSE;
1112 	}
1113 
1114 	retval_len = php_strip_tags(retval, actual_len, &stream->fgetss_state, allowed_tags, allowed_tags_len);
1115 
1116 	RETURN_STRINGL(retval, retval_len, 0);
1117 }
1118 /* }}} */
1119 
1120 /* {{{ proto mixed fscanf(resource stream, string format [, string ...])
1121    Implements a mostly ANSI compatible fscanf() */
PHP_FUNCTION(fscanf)1122 PHP_FUNCTION(fscanf)
1123 {
1124 	int result, format_len, type, argc = 0;
1125 	zval ***args = NULL;
1126 	zval *file_handle;
1127 	char *buf, *format;
1128 	size_t len;
1129 	void *what;
1130 
1131 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs*", &file_handle, &format, &format_len, &args, &argc) == FAILURE) {
1132 		return;
1133 	}
1134 
1135 	what = zend_fetch_resource(&file_handle TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_stream(), php_file_le_pstream());
1136 
1137 	/* we can't do a ZEND_VERIFY_RESOURCE(what), otherwise we end up
1138 	 * with a leak if we have an invalid filehandle. This needs changing
1139 	 * if the code behind ZEND_VERIFY_RESOURCE changed. - cc */
1140 	if (!what) {
1141 		if (args) {
1142 			efree(args);
1143 		}
1144 		RETURN_FALSE;
1145 	}
1146 
1147 	buf = php_stream_get_line((php_stream *) what, NULL, 0, &len);
1148 	if (buf == NULL) {
1149 		if (args) {
1150 			efree(args);
1151 		}
1152 		RETURN_FALSE;
1153 	}
1154 
1155 	result = php_sscanf_internal(buf, format, argc, args, 0, &return_value TSRMLS_CC);
1156 
1157 	if (args) {
1158 		efree(args);
1159 	}
1160 	efree(buf);
1161 
1162 	if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
1163 		WRONG_PARAM_COUNT;
1164 	}
1165 }
1166 /* }}} */
1167 
1168 /* {{{ proto int fwrite(resource fp, string str [, int length])
1169    Binary-safe file write */
PHP_FUNCTION(fwrite)1170 PHPAPI PHP_FUNCTION(fwrite)
1171 {
1172 	zval *arg1;
1173 	char *arg2;
1174 	int arg2len;
1175 	int ret;
1176 	int num_bytes;
1177 	long arg3 = 0;
1178 	char *buffer = NULL;
1179 	php_stream *stream;
1180 
1181 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &arg1, &arg2, &arg2len, &arg3) == FAILURE) {
1182 		RETURN_FALSE;
1183 	}
1184 
1185 	if (ZEND_NUM_ARGS() == 2) {
1186 		num_bytes = arg2len;
1187 	} else {
1188 		num_bytes = MAX(0, MIN((int)arg3, arg2len));
1189 	}
1190 
1191 	if (!num_bytes) {
1192 		RETURN_LONG(0);
1193 	}
1194 
1195 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1196 
1197 	ret = php_stream_write(stream, buffer ? buffer : arg2, num_bytes);
1198 	if (buffer) {
1199 		efree(buffer);
1200 	}
1201 
1202 	RETURN_LONG(ret);
1203 }
1204 /* }}} */
1205 
1206 /* {{{ proto bool fflush(resource fp)
1207    Flushes output */
PHP_FUNCTION(fflush)1208 PHPAPI PHP_FUNCTION(fflush)
1209 {
1210 	zval *arg1;
1211 	int ret;
1212 	php_stream *stream;
1213 
1214 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
1215 		RETURN_FALSE;
1216 	}
1217 
1218 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1219 
1220 	ret = php_stream_flush(stream);
1221 	if (ret) {
1222 		RETURN_FALSE;
1223 	}
1224 	RETURN_TRUE;
1225 }
1226 /* }}} */
1227 
1228 /* {{{ proto bool rewind(resource fp)
1229    Rewind the position of a file pointer */
PHP_FUNCTION(rewind)1230 PHPAPI PHP_FUNCTION(rewind)
1231 {
1232 	zval *arg1;
1233 	php_stream *stream;
1234 
1235 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
1236 		RETURN_FALSE;
1237 	}
1238 
1239 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1240 
1241 	if (-1 == php_stream_rewind(stream)) {
1242 		RETURN_FALSE;
1243 	}
1244 	RETURN_TRUE;
1245 }
1246 /* }}} */
1247 
1248 /* {{{ proto int ftell(resource fp)
1249    Get file pointer's read/write position */
PHP_FUNCTION(ftell)1250 PHPAPI PHP_FUNCTION(ftell)
1251 {
1252 	zval *arg1;
1253 	long ret;
1254 	php_stream *stream;
1255 
1256 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
1257 		RETURN_FALSE;
1258 	}
1259 
1260 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1261 
1262 	ret = php_stream_tell(stream);
1263 	if (ret == -1)	{
1264 		RETURN_FALSE;
1265 	}
1266 	RETURN_LONG(ret);
1267 }
1268 /* }}} */
1269 
1270 /* {{{ proto int fseek(resource fp, int offset [, int whence])
1271    Seek on a file pointer */
PHP_FUNCTION(fseek)1272 PHPAPI PHP_FUNCTION(fseek)
1273 {
1274 	zval *arg1;
1275 	long arg2, whence = SEEK_SET;
1276 	php_stream *stream;
1277 
1278 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &arg1, &arg2, &whence) == FAILURE) {
1279 		RETURN_FALSE;
1280 	}
1281 
1282 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1283 
1284 	RETURN_LONG(php_stream_seek(stream, arg2, whence));
1285 }
1286 /* }}} */
1287 
1288 /* {{{ php_mkdir
1289 */
1290 
1291 /* DEPRECATED APIs: Use php_stream_mkdir() instead */
php_mkdir_ex(char * dir,long mode,int options TSRMLS_DC)1292 PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC)
1293 {
1294 	int ret;
1295 
1296 	if (php_check_open_basedir(dir TSRMLS_CC)) {
1297 		return -1;
1298 	}
1299 
1300 	if ((ret = VCWD_MKDIR(dir, (mode_t)mode)) < 0 && (options & REPORT_ERRORS)) {
1301 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
1302 	}
1303 
1304 	return ret;
1305 }
1306 
php_mkdir(char * dir,long mode TSRMLS_DC)1307 PHPAPI int php_mkdir(char *dir, long mode TSRMLS_DC)
1308 {
1309 	return php_mkdir_ex(dir, mode, REPORT_ERRORS TSRMLS_CC);
1310 }
1311 /* }}} */
1312 
1313 /* {{{ proto bool mkdir(string pathname [, int mode [, bool recursive [, resource context]]])
1314    Create a directory */
PHP_FUNCTION(mkdir)1315 PHP_FUNCTION(mkdir)
1316 {
1317 	char *dir;
1318 	int dir_len;
1319 	zval *zcontext = NULL;
1320 	long mode = 0777;
1321 	zend_bool recursive = 0;
1322 	php_stream_context *context;
1323 
1324 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lbr", &dir, &dir_len, &mode, &recursive, &zcontext) == FAILURE) {
1325 		RETURN_FALSE;
1326 	}
1327 
1328 	context = php_stream_context_from_zval(zcontext, 0);
1329 
1330 	RETURN_BOOL(php_stream_mkdir(dir, mode, (recursive ? PHP_STREAM_MKDIR_RECURSIVE : 0) | REPORT_ERRORS, context));
1331 }
1332 /* }}} */
1333 
1334 /* {{{ proto bool rmdir(string dirname[, resource context])
1335    Remove a directory */
PHP_FUNCTION(rmdir)1336 PHP_FUNCTION(rmdir)
1337 {
1338 	char *dir;
1339 	int dir_len;
1340 	zval *zcontext = NULL;
1341 	php_stream_context *context;
1342 
1343 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|r", &dir, &dir_len, &zcontext) == FAILURE) {
1344 		RETURN_FALSE;
1345 	}
1346 
1347 	context = php_stream_context_from_zval(zcontext, 0);
1348 
1349 	RETURN_BOOL(php_stream_rmdir(dir, REPORT_ERRORS, context));
1350 }
1351 /* }}} */
1352 
1353 /* {{{ proto int readfile(string filename [, bool use_include_path[, resource context]])
1354    Output a file or a URL */
PHP_FUNCTION(readfile)1355 PHP_FUNCTION(readfile)
1356 {
1357 	char *filename;
1358 	int filename_len;
1359 	int size = 0;
1360 	zend_bool use_include_path = 0;
1361 	zval *zcontext = NULL;
1362 	php_stream *stream;
1363 	php_stream_context *context = NULL;
1364 
1365 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
1366 		RETURN_FALSE;
1367 	}
1368 
1369 	context = php_stream_context_from_zval(zcontext, 0);
1370 
1371 	stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
1372 	if (stream) {
1373 		size = php_stream_passthru(stream);
1374 		php_stream_close(stream);
1375 		RETURN_LONG(size);
1376 	}
1377 
1378 	RETURN_FALSE;
1379 }
1380 /* }}} */
1381 
1382 /* {{{ proto int umask([int mask])
1383    Return or change the umask */
PHP_FUNCTION(umask)1384 PHP_FUNCTION(umask)
1385 {
1386 	long arg1 = 0;
1387 	int oldumask;
1388 
1389 	oldumask = umask(077);
1390 
1391 	if (BG(umask) == -1) {
1392 		BG(umask) = oldumask;
1393 	}
1394 
1395 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &arg1) == FAILURE) {
1396 		RETURN_FALSE;
1397 	}
1398 
1399 	if (ZEND_NUM_ARGS() == 0) {
1400 		umask(oldumask);
1401 	} else {
1402 		umask(arg1);
1403 	}
1404 
1405 	RETURN_LONG(oldumask);
1406 }
1407 /* }}} */
1408 
1409 /* {{{ proto int fpassthru(resource fp)
1410    Output all remaining data from a file pointer */
PHP_FUNCTION(fpassthru)1411 PHPAPI PHP_FUNCTION(fpassthru)
1412 {
1413 	zval *arg1;
1414 	int size;
1415 	php_stream *stream;
1416 
1417 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
1418 		RETURN_FALSE;
1419 	}
1420 
1421 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1422 
1423 	size = php_stream_passthru(stream);
1424 	RETURN_LONG(size);
1425 }
1426 /* }}} */
1427 
1428 /* {{{ proto bool rename(string old_name, string new_name[, resource context])
1429    Rename a file */
PHP_FUNCTION(rename)1430 PHP_FUNCTION(rename)
1431 {
1432 	char *old_name, *new_name;
1433 	int old_name_len, new_name_len;
1434 	zval *zcontext = NULL;
1435 	php_stream_wrapper *wrapper;
1436 	php_stream_context *context;
1437 
1438 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|r", &old_name, &old_name_len, &new_name, &new_name_len, &zcontext) == FAILURE) {
1439 		RETURN_FALSE;
1440 	}
1441 
1442 	wrapper = php_stream_locate_url_wrapper(old_name, NULL, 0 TSRMLS_CC);
1443 
1444 	if (!wrapper || !wrapper->wops) {
1445 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate stream wrapper");
1446 		RETURN_FALSE;
1447 	}
1448 
1449 	if (!wrapper->wops->rename) {
1450 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s wrapper does not support renaming", wrapper->wops->label ? wrapper->wops->label : "Source");
1451 		RETURN_FALSE;
1452 	}
1453 
1454 	if (wrapper != php_stream_locate_url_wrapper(new_name, NULL, 0 TSRMLS_CC)) {
1455 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot rename a file across wrapper types");
1456 		RETURN_FALSE;
1457 	}
1458 
1459 	context = php_stream_context_from_zval(zcontext, 0);
1460 
1461 	RETURN_BOOL(wrapper->wops->rename(wrapper, old_name, new_name, 0, context TSRMLS_CC));
1462 }
1463 /* }}} */
1464 
1465 /* {{{ proto bool unlink(string filename[, context context])
1466    Delete a file */
PHP_FUNCTION(unlink)1467 PHP_FUNCTION(unlink)
1468 {
1469 	char *filename;
1470 	int filename_len;
1471 	php_stream_wrapper *wrapper;
1472 	zval *zcontext = NULL;
1473 	php_stream_context *context = NULL;
1474 
1475 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|r", &filename, &filename_len, &zcontext) == FAILURE) {
1476 		RETURN_FALSE;
1477 	}
1478 
1479 	context = php_stream_context_from_zval(zcontext, 0);
1480 
1481 	wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
1482 
1483 	if (!wrapper || !wrapper->wops) {
1484 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate stream wrapper");
1485 		RETURN_FALSE;
1486 	}
1487 
1488 	if (!wrapper->wops->unlink) {
1489 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s does not allow unlinking", wrapper->wops->label ? wrapper->wops->label : "Wrapper");
1490 		RETURN_FALSE;
1491 	}
1492 	RETURN_BOOL(wrapper->wops->unlink(wrapper, filename, REPORT_ERRORS, context TSRMLS_CC));
1493 }
1494 /* }}} */
1495 
1496 /* {{{ proto bool ftruncate(resource fp, int size)
1497    Truncate file to 'size' length */
PHP_NAMED_FUNCTION(php_if_ftruncate)1498 PHP_NAMED_FUNCTION(php_if_ftruncate)
1499 {
1500 	zval *fp;
1501 	long size;
1502 	php_stream *stream;
1503 
1504 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &fp, &size) == FAILURE) {
1505 		RETURN_FALSE;
1506 	}
1507 
1508 	PHP_STREAM_TO_ZVAL(stream, &fp);
1509 
1510 	if (!php_stream_truncate_supported(stream)) {
1511 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream!");
1512 		RETURN_FALSE;
1513 	}
1514 
1515 	RETURN_BOOL(0 == php_stream_truncate_set_size(stream, size));
1516 }
1517 /* }}} */
1518 
1519 /* {{{ proto array fstat(resource fp)
1520    Stat() on a filehandle */
PHP_NAMED_FUNCTION(php_if_fstat)1521 PHP_NAMED_FUNCTION(php_if_fstat)
1522 {
1523 	zval *fp;
1524 	zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
1525 		 *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
1526 	php_stream *stream;
1527 	php_stream_statbuf stat_ssb;
1528 	char *stat_sb_names[13] = {
1529 		"dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
1530 		"size", "atime", "mtime", "ctime", "blksize", "blocks"
1531 	};
1532 
1533 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &fp) == FAILURE) {
1534 		RETURN_FALSE;
1535 	}
1536 
1537 	PHP_STREAM_TO_ZVAL(stream, &fp);
1538 
1539 	if (php_stream_stat(stream, &stat_ssb)) {
1540 		RETURN_FALSE;
1541 	}
1542 
1543 	array_init(return_value);
1544 
1545 	MAKE_LONG_ZVAL_INCREF(stat_dev, stat_ssb.sb.st_dev);
1546 	MAKE_LONG_ZVAL_INCREF(stat_ino, stat_ssb.sb.st_ino);
1547 	MAKE_LONG_ZVAL_INCREF(stat_mode, stat_ssb.sb.st_mode);
1548 	MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_ssb.sb.st_nlink);
1549 	MAKE_LONG_ZVAL_INCREF(stat_uid, stat_ssb.sb.st_uid);
1550 	MAKE_LONG_ZVAL_INCREF(stat_gid, stat_ssb.sb.st_gid);
1551 #ifdef HAVE_ST_RDEV
1552 	MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_ssb.sb.st_rdev);
1553 #else
1554 	MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
1555 #endif
1556 	MAKE_LONG_ZVAL_INCREF(stat_size, stat_ssb.sb.st_size);
1557 	MAKE_LONG_ZVAL_INCREF(stat_atime, stat_ssb.sb.st_atime);
1558 	MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_ssb.sb.st_mtime);
1559 	MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_ssb.sb.st_ctime);
1560 #ifdef HAVE_ST_BLKSIZE
1561 	MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_ssb.sb.st_blksize);
1562 #else
1563 	MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
1564 #endif
1565 #ifdef HAVE_ST_BLOCKS
1566 	MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_ssb.sb.st_blocks);
1567 #else
1568 	MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
1569 #endif
1570 	/* Store numeric indexes in propper order */
1571 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
1572 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
1573 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
1574 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
1575 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
1576 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
1577 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
1578 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
1579 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
1580 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
1581 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
1582 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
1583 	zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
1584 
1585 	/* Store string indexes referencing the same zval*/
1586 	zend_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *)&stat_dev, sizeof(zval *), NULL);
1587 	zend_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *)&stat_ino, sizeof(zval *), NULL);
1588 	zend_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *)&stat_mode, sizeof(zval *), NULL);
1589 	zend_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *)&stat_nlink, sizeof(zval *), NULL);
1590 	zend_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *)&stat_uid, sizeof(zval *), NULL);
1591 	zend_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *)&stat_gid, sizeof(zval *), NULL);
1592 	zend_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *)&stat_rdev, sizeof(zval *), NULL);
1593 	zend_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *)&stat_size, sizeof(zval *), NULL);
1594 	zend_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *)&stat_atime, sizeof(zval *), NULL);
1595 	zend_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *)&stat_mtime, sizeof(zval *), NULL);
1596 	zend_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *)&stat_ctime, sizeof(zval *), NULL);
1597 	zend_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *)&stat_blksize, sizeof(zval *), NULL);
1598 	zend_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *)&stat_blocks, sizeof(zval *), NULL);
1599 }
1600 /* }}} */
1601 
1602 /* {{{ proto bool copy(string source_file, string destination_file [, resource context])
1603    Copy a file */
PHP_FUNCTION(copy)1604 PHP_FUNCTION(copy)
1605 {
1606 	char *source, *target;
1607 	int source_len, target_len;
1608 	zval *zcontext = NULL;
1609 	php_stream_context *context;
1610 
1611 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|r", &source, &source_len, &target, &target_len, &zcontext) == FAILURE) {
1612 		return;
1613 	}
1614 
1615 	if (php_check_open_basedir(source TSRMLS_CC)) {
1616 		RETURN_FALSE;
1617 	}
1618 
1619 	context = php_stream_context_from_zval(zcontext, 0);
1620 
1621 	if (php_copy_file_ctx(source, target, 0, context TSRMLS_CC) == SUCCESS) {
1622 		RETURN_TRUE;
1623 	} else {
1624 		RETURN_FALSE;
1625 	}
1626 }
1627 /* }}} */
1628 
1629 /* {{{ php_copy_file
1630  */
php_copy_file(char * src,char * dest TSRMLS_DC)1631 PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC)
1632 {
1633 	return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC);
1634 }
1635 /* }}} */
1636 
1637 /* {{{ php_copy_file_ex
1638  */
php_copy_file_ex(char * src,char * dest,int src_flg TSRMLS_DC)1639 PHPAPI int php_copy_file_ex(char *src, char *dest, int src_flg TSRMLS_DC)
1640 {
1641 	return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC);
1642 }
1643 /* }}} */
1644 
1645 /* {{{ php_copy_file_ctx
1646  */
php_copy_file_ctx(char * src,char * dest,int src_flg,php_stream_context * ctx TSRMLS_DC)1647 PHPAPI int php_copy_file_ctx(char *src, char *dest, int src_flg, php_stream_context *ctx TSRMLS_DC)
1648 {
1649 	php_stream *srcstream = NULL, *deststream = NULL;
1650 	int ret = FAILURE;
1651 	php_stream_statbuf src_s, dest_s;
1652 
1653 	switch (php_stream_stat_path_ex(src, 0, &src_s, ctx)) {
1654 		case -1:
1655 			/* non-statable stream */
1656 			goto safe_to_copy;
1657 			break;
1658 		case 0:
1659 			break;
1660 		default: /* failed to stat file, does not exist? */
1661 			return ret;
1662 	}
1663 	if (S_ISDIR(src_s.sb.st_mode)) {
1664 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument to copy() function cannot be a directory");
1665 		return FAILURE;
1666 	}
1667 
1668 	switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET | PHP_STREAM_URL_STAT_NOCACHE, &dest_s, ctx)) {
1669 		case -1:
1670 			/* non-statable stream */
1671 			goto safe_to_copy;
1672 			break;
1673 		case 0:
1674 			break;
1675 		default: /* failed to stat file, does not exist? */
1676 			return ret;
1677 	}
1678 	if (S_ISDIR(dest_s.sb.st_mode)) {
1679 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument to copy() function cannot be a directory");
1680 		return FAILURE;
1681 	}
1682 	if (!src_s.sb.st_ino || !dest_s.sb.st_ino) {
1683 		goto no_stat;
1684 	}
1685 	if (src_s.sb.st_ino == dest_s.sb.st_ino && src_s.sb.st_dev == dest_s.sb.st_dev) {
1686 		return ret;
1687 	} else {
1688 		goto safe_to_copy;
1689 	}
1690 no_stat:
1691 	{
1692 		char *sp, *dp;
1693 		int res;
1694 
1695 		if ((sp = expand_filepath(src, NULL TSRMLS_CC)) == NULL) {
1696 			return ret;
1697 		}
1698 		if ((dp = expand_filepath(dest, NULL TSRMLS_CC)) == NULL) {
1699 			efree(sp);
1700 			goto safe_to_copy;
1701 		}
1702 
1703 		res =
1704 #ifndef PHP_WIN32
1705 			!strcmp(sp, dp);
1706 #else
1707 			!strcasecmp(sp, dp);
1708 #endif
1709 
1710 		efree(sp);
1711 		efree(dp);
1712 		if (res) {
1713 			return ret;
1714 		}
1715 	}
1716 safe_to_copy:
1717 
1718 	srcstream = php_stream_open_wrapper_ex(src, "rb", src_flg | REPORT_ERRORS, NULL, ctx);
1719 
1720 	if (!srcstream) {
1721 		return ret;
1722 	}
1723 
1724 	deststream = php_stream_open_wrapper_ex(dest, "wb", REPORT_ERRORS, NULL, ctx);
1725 
1726 	if (srcstream && deststream) {
1727 		ret = php_stream_copy_to_stream_ex(srcstream, deststream, PHP_STREAM_COPY_ALL, NULL);
1728 	}
1729 	if (srcstream) {
1730 		php_stream_close(srcstream);
1731 	}
1732 	if (deststream) {
1733 		php_stream_close(deststream);
1734 	}
1735 	return ret;
1736 }
1737 /* }}} */
1738 
1739 /* {{{ proto string fread(resource fp, int length)
1740    Binary-safe file read */
PHP_FUNCTION(fread)1741 PHPAPI PHP_FUNCTION(fread)
1742 {
1743 	zval *arg1;
1744 	long len;
1745 	php_stream *stream;
1746 
1747 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &arg1, &len) == FAILURE) {
1748 		RETURN_FALSE;
1749 	}
1750 
1751 	PHP_STREAM_TO_ZVAL(stream, &arg1);
1752 
1753 	if (len <= 0) {
1754 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
1755 		RETURN_FALSE;
1756 	}
1757 
1758 	Z_STRVAL_P(return_value) = emalloc(len + 1);
1759 	Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);
1760 
1761 	/* needed because recv/read/gzread doesnt put a null at the end*/
1762 	Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
1763 	Z_TYPE_P(return_value) = IS_STRING;
1764 }
1765 /* }}} */
1766 
php_fgetcsv_lookup_trailing_spaces(const char * ptr,size_t len,const char delimiter TSRMLS_DC)1767 static const char *php_fgetcsv_lookup_trailing_spaces(const char *ptr, size_t len, const char delimiter TSRMLS_DC) /* {{{ */
1768 {
1769 	int inc_len;
1770 	unsigned char last_chars[2] = { 0, 0 };
1771 
1772 	while (len > 0) {
1773 		inc_len = (*ptr == '\0' ? 1: php_mblen(ptr, len));
1774 		switch (inc_len) {
1775 			case -2:
1776 			case -1:
1777 				inc_len = 1;
1778 				php_ignore_value(php_mblen(NULL, 0));
1779 				break;
1780 			case 0:
1781 				goto quit_loop;
1782 			case 1:
1783 			default:
1784 				last_chars[0] = last_chars[1];
1785 				last_chars[1] = *ptr;
1786 				break;
1787 		}
1788 		ptr += inc_len;
1789 		len -= inc_len;
1790 	}
1791 quit_loop:
1792 	switch (last_chars[1]) {
1793 		case '\n':
1794 			if (last_chars[0] == '\r') {
1795 				return ptr - 2;
1796 			}
1797 			/* break is omitted intentionally */
1798 		case '\r':
1799 			return ptr - 1;
1800 	}
1801 	return ptr;
1802 }
1803 /* }}} */
1804 
1805 #define FPUTCSV_FLD_CHK(c) memchr(Z_STRVAL(field), c, Z_STRLEN(field))
1806 
1807 /* {{{ proto int fputcsv(resource fp, array fields [, string delimiter [, string enclosure]])
1808    Format line as CSV and write to file pointer */
PHP_FUNCTION(fputcsv)1809 PHP_FUNCTION(fputcsv)
1810 {
1811 	char delimiter = ',';	/* allow this to be set as parameter */
1812 	char enclosure = '"';	/* allow this to be set as parameter */
1813 	const char escape_char = '\\';
1814 	php_stream *stream;
1815 	zval *fp = NULL, *fields = NULL;
1816 	int ret;
1817 	char *delimiter_str = NULL, *enclosure_str = NULL;
1818 	int delimiter_str_len = 0, enclosure_str_len = 0;
1819 
1820 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|ss",
1821 			&fp, &fields, &delimiter_str, &delimiter_str_len,
1822 			&enclosure_str, &enclosure_str_len) == FAILURE) {
1823 		return;
1824 	}
1825 
1826 	if (delimiter_str != NULL) {
1827 		/* Make sure that there is at least one character in string */
1828 		if (delimiter_str_len < 1) {
1829 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
1830 			RETURN_FALSE;
1831 		} else if (delimiter_str_len > 1) {
1832 			php_error_docref(NULL TSRMLS_CC, E_NOTICE, "delimiter must be a single character");
1833 		}
1834 
1835 		/* use first character from string */
1836 		delimiter = *delimiter_str;
1837 	}
1838 
1839 	if (enclosure_str != NULL) {
1840 		if (enclosure_str_len < 1) {
1841 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
1842 			RETURN_FALSE;
1843 		} else if (enclosure_str_len > 1) {
1844 			php_error_docref(NULL TSRMLS_CC, E_NOTICE, "enclosure must be a single character");
1845 		}
1846 		/* use first character from string */
1847 		enclosure = *enclosure_str;
1848 	}
1849 
1850 	PHP_STREAM_TO_ZVAL(stream, &fp);
1851 
1852 	ret = php_fputcsv(stream, fields, delimiter, enclosure, escape_char TSRMLS_CC);
1853 	RETURN_LONG(ret);
1854 }
1855 /* }}} */
1856 
1857 /* {{{ PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC) */
php_fputcsv(php_stream * stream,zval * fields,char delimiter,char enclosure,char escape_char TSRMLS_DC)1858 PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC)
1859 {
1860 	int count, i = 0, ret;
1861 	zval **field_tmp = NULL, field;
1862 	smart_str csvline = {0};
1863 	HashPosition pos;
1864 
1865 	count = zend_hash_num_elements(Z_ARRVAL_P(fields));
1866 	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(fields), &pos);
1867 	while (zend_hash_get_current_data_ex(Z_ARRVAL_P(fields), (void **) &field_tmp, &pos) == SUCCESS) {
1868 		field = **field_tmp;
1869 
1870 		if (Z_TYPE_PP(field_tmp) != IS_STRING) {
1871 			zval_copy_ctor(&field);
1872 			convert_to_string(&field);
1873 		}
1874 
1875 		/* enclose a field that contains a delimiter, an enclosure character, or a newline */
1876 		if (FPUTCSV_FLD_CHK(delimiter) ||
1877 			FPUTCSV_FLD_CHK(enclosure) ||
1878 			FPUTCSV_FLD_CHK(escape_char) ||
1879 			FPUTCSV_FLD_CHK('\n') ||
1880 			FPUTCSV_FLD_CHK('\r') ||
1881 			FPUTCSV_FLD_CHK('\t') ||
1882 			FPUTCSV_FLD_CHK(' ')
1883 		) {
1884 			char *ch = Z_STRVAL(field);
1885 			char *end = ch + Z_STRLEN(field);
1886 			int escaped = 0;
1887 
1888 			smart_str_appendc(&csvline, enclosure);
1889 			while (ch < end) {
1890 				if (*ch == escape_char) {
1891 					escaped = 1;
1892 				} else if (!escaped && *ch == enclosure) {
1893 					smart_str_appendc(&csvline, enclosure);
1894 				} else {
1895 					escaped = 0;
1896 				}
1897 				smart_str_appendc(&csvline, *ch);
1898 				ch++;
1899 			}
1900 			smart_str_appendc(&csvline, enclosure);
1901 		} else {
1902 			smart_str_appendl(&csvline, Z_STRVAL(field), Z_STRLEN(field));
1903 		}
1904 
1905 		if (++i != count) {
1906 			smart_str_appendl(&csvline, &delimiter, 1);
1907 		}
1908 		zend_hash_move_forward_ex(Z_ARRVAL_P(fields), &pos);
1909 
1910 		if (Z_TYPE_PP(field_tmp) != IS_STRING) {
1911 			zval_dtor(&field);
1912 		}
1913 	}
1914 
1915 	smart_str_appendc(&csvline, '\n');
1916 	smart_str_0(&csvline);
1917 
1918 	ret = php_stream_write(stream, csvline.c, csvline.len);
1919 
1920 	smart_str_free(&csvline);
1921 
1922 	return ret;
1923 }
1924 /* }}} */
1925 
1926 /* {{{ proto array fgetcsv(resource fp [,int length [, string delimiter [, string enclosure [, string escape]]]])
1927    Get line from file pointer and parse for CSV fields */
PHP_FUNCTION(fgetcsv)1928 PHP_FUNCTION(fgetcsv)
1929 {
1930 	char delimiter = ',';	/* allow this to be set as parameter */
1931 	char enclosure = '"';	/* allow this to be set as parameter */
1932 	char escape = '\\';
1933 
1934 	/* first section exactly as php_fgetss */
1935 
1936 	long len = 0;
1937 	size_t buf_len;
1938 	char *buf;
1939 	php_stream *stream;
1940 
1941 	{
1942 		zval *fd, **len_zv = NULL;
1943 		char *delimiter_str = NULL;
1944 		int delimiter_str_len = 0;
1945 		char *enclosure_str = NULL;
1946 		int enclosure_str_len = 0;
1947 		char *escape_str = NULL;
1948 		int escape_str_len = 0;
1949 
1950 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|Zsss",
1951 			&fd, &len_zv, &delimiter_str, &delimiter_str_len,
1952 			&enclosure_str, &enclosure_str_len,
1953 			&escape_str, &escape_str_len) == FAILURE
1954 		) {
1955 			return;
1956 		}
1957 
1958 		if (delimiter_str != NULL) {
1959 			/* Make sure that there is at least one character in string */
1960 			if (delimiter_str_len < 1) {
1961 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
1962 				RETURN_FALSE;
1963 			} else if (delimiter_str_len > 1) {
1964 				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "delimiter must be a single character");
1965 			}
1966 
1967 			/* use first character from string */
1968 			delimiter = delimiter_str[0];
1969 		}
1970 
1971 		if (enclosure_str != NULL) {
1972 			if (enclosure_str_len < 1) {
1973 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
1974 				RETURN_FALSE;
1975 			} else if (enclosure_str_len > 1) {
1976 				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "enclosure must be a single character");
1977 			}
1978 
1979 			/* use first character from string */
1980 			enclosure = enclosure_str[0];
1981 		}
1982 
1983 		if (escape_str != NULL) {
1984 			if (escape_str_len < 1) {
1985 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be character");
1986 				RETURN_FALSE;
1987 			} else if (escape_str_len > 1) {
1988 				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "escape must be a single character");
1989 			}
1990 
1991 			escape = escape_str[0];
1992 		}
1993 
1994 		if (len_zv != NULL && Z_TYPE_PP(len_zv) != IS_NULL) {
1995 			convert_to_long_ex(len_zv);
1996 			len = Z_LVAL_PP(len_zv);
1997 			if (len < 0) {
1998 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter may not be negative");
1999 				RETURN_FALSE;
2000 			} else if (len == 0) {
2001 				len = -1;
2002 			}
2003 		} else {
2004 			len = -1;
2005 		}
2006 
2007 		PHP_STREAM_TO_ZVAL(stream, &fd);
2008 	}
2009 
2010 	if (len < 0) {
2011 		if ((buf = php_stream_get_line(stream, NULL, 0, &buf_len)) == NULL) {
2012 			RETURN_FALSE;
2013 		}
2014 	} else {
2015 		buf = emalloc(len + 1);
2016 		if (php_stream_get_line(stream, buf, len + 1, &buf_len) == NULL) {
2017 			efree(buf);
2018 			RETURN_FALSE;
2019 		}
2020 	}
2021 
2022 	php_fgetcsv(stream, delimiter, enclosure, escape, buf_len, buf, return_value TSRMLS_CC);
2023 }
2024 /* }}} */
2025 
php_fgetcsv(php_stream * stream,char delimiter,char enclosure,char escape_char,size_t buf_len,char * buf,zval * return_value TSRMLS_DC)2026 PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char escape_char, size_t buf_len, char *buf, zval *return_value TSRMLS_DC) /* {{{ */
2027 {
2028 	char *temp, *tptr, *bptr, *line_end, *limit;
2029 	size_t temp_len, line_end_len;
2030 	int inc_len;
2031 	zend_bool first_field = 1;
2032 
2033 	/* initialize internal state */
2034 	php_ignore_value(php_mblen(NULL, 0));
2035 
2036 	/* Now into new section that parses buf for delimiter/enclosure fields */
2037 
2038 	/* Strip trailing space from buf, saving end of line in case required for enclosure field */
2039 
2040 	bptr = buf;
2041 	tptr = (char *)php_fgetcsv_lookup_trailing_spaces(buf, buf_len, delimiter TSRMLS_CC);
2042 	line_end_len = buf_len - (size_t)(tptr - buf);
2043 	line_end = limit = tptr;
2044 
2045 	/* reserve workspace for building each individual field */
2046 	temp_len = buf_len;
2047 	temp = emalloc(temp_len + line_end_len + 1);
2048 
2049 	/* Initialize return array */
2050 	array_init(return_value);
2051 
2052 	/* Main loop to read CSV fields */
2053 	/* NB this routine will return a single null entry for a blank line */
2054 
2055 	do {
2056 		char *comp_end, *hunk_begin;
2057 
2058 		tptr = temp;
2059 
2060 		inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2061 		if (inc_len == 1) {
2062 			char *tmp = bptr;
2063 			while ((*tmp != delimiter) && isspace((int)*(unsigned char *)tmp)) {
2064 				tmp++;
2065 			}
2066 			if (*tmp == enclosure) {
2067 				bptr = tmp;
2068 			}
2069 		}
2070 
2071 		if (first_field && bptr == line_end) {
2072 			add_next_index_null(return_value);
2073 			break;
2074 		}
2075 		first_field = 0;
2076 		/* 2. Read field, leaving bptr pointing at start of next field */
2077 		if (inc_len != 0 && *bptr == enclosure) {
2078 			int state = 0;
2079 
2080 			bptr++;	/* move on to first character in field */
2081 			hunk_begin = bptr;
2082 
2083 			/* 2A. handle enclosure delimited field */
2084 			for (;;) {
2085 				switch (inc_len) {
2086 					case 0:
2087 						switch (state) {
2088 							case 2:
2089 								memcpy(tptr, hunk_begin, bptr - hunk_begin - 1);
2090 								tptr += (bptr - hunk_begin - 1);
2091 								hunk_begin = bptr;
2092 								goto quit_loop_2;
2093 
2094 							case 1:
2095 								memcpy(tptr, hunk_begin, bptr - hunk_begin);
2096 								tptr += (bptr - hunk_begin);
2097 								hunk_begin = bptr;
2098 								/* break is omitted intentionally */
2099 
2100 							case 0: {
2101 								char *new_buf;
2102 								size_t new_len;
2103 								char *new_temp;
2104 
2105 								if (hunk_begin != line_end) {
2106 									memcpy(tptr, hunk_begin, bptr - hunk_begin);
2107 									tptr += (bptr - hunk_begin);
2108 									hunk_begin = bptr;
2109 								}
2110 
2111 								/* add the embedded line end to the field */
2112 								memcpy(tptr, line_end, line_end_len);
2113 								tptr += line_end_len;
2114 
2115 								if (stream == NULL) {
2116 									goto quit_loop_2;
2117 								} else if ((new_buf = php_stream_get_line(stream, NULL, 0, &new_len)) == NULL) {
2118 									/* we've got an unterminated enclosure,
2119 									 * assign all the data from the start of
2120 									 * the enclosure to end of data to the
2121 									 * last element */
2122 									if ((size_t)temp_len > (size_t)(limit - buf)) {
2123 										goto quit_loop_2;
2124 									}
2125 									zval_dtor(return_value);
2126 									RETVAL_FALSE;
2127 									goto out;
2128 								}
2129 								temp_len += new_len;
2130 								new_temp = erealloc(temp, temp_len);
2131 								tptr = new_temp + (size_t)(tptr - temp);
2132 								temp = new_temp;
2133 
2134 								efree(buf);
2135 								buf_len = new_len;
2136 								bptr = buf = new_buf;
2137 								hunk_begin = buf;
2138 
2139 								line_end = limit = (char *)php_fgetcsv_lookup_trailing_spaces(buf, buf_len, delimiter TSRMLS_CC);
2140 								line_end_len = buf_len - (size_t)(limit - buf);
2141 
2142 								state = 0;
2143 							} break;
2144 						}
2145 						break;
2146 
2147 					case -2:
2148 					case -1:
2149 						php_ignore_value(php_mblen(NULL, 0));
2150 						/* break is omitted intentionally */
2151 					case 1:
2152 						/* we need to determine if the enclosure is
2153 						 * 'real' or is it escaped */
2154 						switch (state) {
2155 							case 1: /* escaped */
2156 								bptr++;
2157 								state = 0;
2158 								break;
2159 							case 2: /* embedded enclosure ? let's check it */
2160 								if (*bptr != enclosure) {
2161 									/* real enclosure */
2162 									memcpy(tptr, hunk_begin, bptr - hunk_begin - 1);
2163 									tptr += (bptr - hunk_begin - 1);
2164 									hunk_begin = bptr;
2165 									goto quit_loop_2;
2166 								}
2167 								memcpy(tptr, hunk_begin, bptr - hunk_begin);
2168 								tptr += (bptr - hunk_begin);
2169 								bptr++;
2170 								hunk_begin = bptr;
2171 								state = 0;
2172 								break;
2173 							default:
2174 								if (*bptr == enclosure) {
2175 									state = 2;
2176 								} else if (*bptr == escape_char) {
2177 									state = 1;
2178 								}
2179 								bptr++;
2180 								break;
2181 						}
2182 						break;
2183 
2184 					default:
2185 						switch (state) {
2186 							case 2:
2187 								/* real enclosure */
2188 								memcpy(tptr, hunk_begin, bptr - hunk_begin - 1);
2189 								tptr += (bptr - hunk_begin - 1);
2190 								hunk_begin = bptr;
2191 								goto quit_loop_2;
2192 							case 1:
2193 								bptr += inc_len;
2194 								memcpy(tptr, hunk_begin, bptr - hunk_begin);
2195 								tptr += (bptr - hunk_begin);
2196 								hunk_begin = bptr;
2197 								break;
2198 							default:
2199 								bptr += inc_len;
2200 								break;
2201 						}
2202 						break;
2203 				}
2204 				inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2205 			}
2206 
2207 		quit_loop_2:
2208 			/* look up for a delimiter */
2209 			for (;;) {
2210 				switch (inc_len) {
2211 					case 0:
2212 						goto quit_loop_3;
2213 
2214 					case -2:
2215 					case -1:
2216 						inc_len = 1;
2217 						php_ignore_value(php_mblen(NULL, 0));
2218 						/* break is omitted intentionally */
2219 					case 1:
2220 						if (*bptr == delimiter) {
2221 							goto quit_loop_3;
2222 						}
2223 						break;
2224 					default:
2225 						break;
2226 				}
2227 				bptr += inc_len;
2228 				inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2229 			}
2230 
2231 		quit_loop_3:
2232 			memcpy(tptr, hunk_begin, bptr - hunk_begin);
2233 			tptr += (bptr - hunk_begin);
2234 			bptr += inc_len;
2235 			comp_end = tptr;
2236 		} else {
2237 			/* 2B. Handle non-enclosure field */
2238 
2239 			hunk_begin = bptr;
2240 
2241 			for (;;) {
2242 				switch (inc_len) {
2243 					case 0:
2244 						goto quit_loop_4;
2245 					case -2:
2246 					case -1:
2247 						inc_len = 1;
2248 						php_ignore_value(php_mblen(NULL, 0));
2249 						/* break is omitted intentionally */
2250 					case 1:
2251 						if (*bptr == delimiter) {
2252 							goto quit_loop_4;
2253 						}
2254 						break;
2255 					default:
2256 						break;
2257 				}
2258 				bptr += inc_len;
2259 				inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2260 			}
2261 		quit_loop_4:
2262 			memcpy(tptr, hunk_begin, bptr - hunk_begin);
2263 			tptr += (bptr - hunk_begin);
2264 
2265 			comp_end = (char *)php_fgetcsv_lookup_trailing_spaces(temp, tptr - temp, delimiter TSRMLS_CC);
2266 			if (*bptr == delimiter) {
2267 				bptr++;
2268 			}
2269 		}
2270 
2271 		/* 3. Now pass our field back to php */
2272 		*comp_end = '\0';
2273 		add_next_index_stringl(return_value, temp, comp_end - temp, 1);
2274 	} while (inc_len > 0);
2275 
2276 out:
2277 	efree(temp);
2278 	if (stream) {
2279 		efree(buf);
2280 	}
2281 }
2282 /* }}} */
2283 
2284 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
2285 /* {{{ proto string realpath(string path)
2286    Return the resolved path */
PHP_FUNCTION(realpath)2287 PHP_FUNCTION(realpath)
2288 {
2289 	char *filename;
2290 	int filename_len;
2291 	char resolved_path_buff[MAXPATHLEN];
2292 
2293 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
2294 		return;
2295 	}
2296 
2297 	if (VCWD_REALPATH(filename, resolved_path_buff)) {
2298 		if (php_check_open_basedir(resolved_path_buff TSRMLS_CC)) {
2299 			RETURN_FALSE;
2300 		}
2301 
2302 #ifdef ZTS
2303 		if (VCWD_ACCESS(resolved_path_buff, F_OK)) {
2304 			RETURN_FALSE;
2305 		}
2306 #endif
2307 		RETURN_STRING(resolved_path_buff, 1);
2308 	} else {
2309 		RETURN_FALSE;
2310 	}
2311 }
2312 /* }}} */
2313 #endif
2314 
2315 /* See http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.2 */
2316 #define PHP_META_HTML401_CHARS "-_.:"
2317 
2318 /* {{{ php_next_meta_token
2319    Tokenizes an HTML file for get_meta_tags */
php_next_meta_token(php_meta_tags_data * md TSRMLS_DC)2320 php_meta_tags_token php_next_meta_token(php_meta_tags_data *md TSRMLS_DC)
2321 {
2322 	int ch = 0, compliment;
2323 	char buff[META_DEF_BUFSIZE + 1];
2324 
2325 	memset((void *)buff, 0, META_DEF_BUFSIZE + 1);
2326 
2327 	while (md->ulc || (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)))) {
2328 		if (php_stream_eof(md->stream)) {
2329 			break;
2330 		}
2331 
2332 		if (md->ulc) {
2333 			ch = md->lc;
2334 			md->ulc = 0;
2335 		}
2336 
2337 		switch (ch) {
2338 			case '<':
2339 				return TOK_OPENTAG;
2340 				break;
2341 
2342 			case '>':
2343 				return TOK_CLOSETAG;
2344 				break;
2345 
2346 			case '=':
2347 				return TOK_EQUAL;
2348 				break;
2349 			case '/':
2350 				return TOK_SLASH;
2351 				break;
2352 
2353 			case '\'':
2354 			case '"':
2355 				compliment = ch;
2356 				md->token_len = 0;
2357 				while (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)) && ch != compliment && ch != '<' && ch != '>') {
2358 					buff[(md->token_len)++] = ch;
2359 
2360 					if (md->token_len == META_DEF_BUFSIZE) {
2361 						break;
2362 					}
2363 				}
2364 
2365 				if (ch == '<' || ch == '>') {
2366 					/* Was just an apostrohpe */
2367 					md->ulc = 1;
2368 					md->lc = ch;
2369 				}
2370 
2371 				/* We don't need to alloc unless we are in a meta tag */
2372 				if (md->in_meta) {
2373 					md->token_data = (char *) emalloc(md->token_len + 1);
2374 					memcpy(md->token_data, buff, md->token_len+1);
2375 				}
2376 
2377 				return TOK_STRING;
2378 				break;
2379 
2380 			case '\n':
2381 			case '\r':
2382 			case '\t':
2383 				break;
2384 
2385 			case ' ':
2386 				return TOK_SPACE;
2387 				break;
2388 
2389 			default:
2390 				if (isalnum(ch)) {
2391 					md->token_len = 0;
2392 					buff[(md->token_len)++] = ch;
2393 					while (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)) && (isalnum(ch) || strchr(PHP_META_HTML401_CHARS, ch))) {
2394 						buff[(md->token_len)++] = ch;
2395 
2396 						if (md->token_len == META_DEF_BUFSIZE) {
2397 							break;
2398 						}
2399 					}
2400 
2401 					/* This is ugly, but we have to replace ungetc */
2402 					if (!isalpha(ch) && ch != '-') {
2403 						md->ulc = 1;
2404 						md->lc = ch;
2405 					}
2406 
2407 					md->token_data = (char *) emalloc(md->token_len + 1);
2408 					memcpy(md->token_data, buff, md->token_len+1);
2409 
2410 					return TOK_ID;
2411 				} else {
2412 					return TOK_OTHER;
2413 				}
2414 				break;
2415 		}
2416 	}
2417 
2418 	return TOK_EOF;
2419 }
2420 /* }}} */
2421 
2422 #ifdef HAVE_FNMATCH
2423 /* {{{ proto bool fnmatch(string pattern, string filename [, int flags])
2424    Match filename against pattern */
PHP_FUNCTION(fnmatch)2425 PHP_FUNCTION(fnmatch)
2426 {
2427 	char *pattern, *filename;
2428 	int pattern_len, filename_len;
2429 	long flags = 0;
2430 
2431 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|l", &pattern, &pattern_len, &filename, &filename_len, &flags) == FAILURE) {
2432 		return;
2433 	}
2434 
2435 	if (filename_len >= MAXPATHLEN) {
2436 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename exceeds the maximum allowed length of %d characters", MAXPATHLEN);
2437 		RETURN_FALSE;
2438 	}
2439 	if (pattern_len >= MAXPATHLEN) {
2440 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
2441 		RETURN_FALSE;
2442 	}
2443 
2444 	RETURN_BOOL( ! fnmatch( pattern, filename, flags ));
2445 }
2446 /* }}} */
2447 #endif
2448 
2449 /* {{{ proto string sys_get_temp_dir()
2450    Returns directory path used for temporary files */
PHP_FUNCTION(sys_get_temp_dir)2451 PHP_FUNCTION(sys_get_temp_dir)
2452 {
2453 	if (zend_parse_parameters_none() == FAILURE) {
2454 		return;
2455 	}
2456 	RETURN_STRING((char *)php_get_temporary_directory(), 1);
2457 }
2458 /* }}} */
2459 
2460 /*
2461  * Local variables:
2462  * tab-width: 4
2463  * c-basic-offset: 4
2464  * End:
2465  * vim600: noet sw=4 ts=4 fdm=marker
2466  * vim<600: noet sw=4 ts=4
2467  */
2468