xref: /PHP-7.1/ext/spl/spl_directory.c (revision 254a5914)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 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    | Author: Marcus Boerger <helly@php.net>                               |
16    +----------------------------------------------------------------------+
17  */
18 
19 /* $Id$ */
20 
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24 
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "ext/standard/file.h"
29 #include "ext/standard/php_string.h"
30 #include "zend_compile.h"
31 #include "zend_exceptions.h"
32 #include "zend_interfaces.h"
33 
34 #include "php_spl.h"
35 #include "spl_functions.h"
36 #include "spl_engine.h"
37 #include "spl_iterators.h"
38 #include "spl_directory.h"
39 #include "spl_exceptions.h"
40 
41 #include "php.h"
42 #include "fopen_wrappers.h"
43 
44 #include "ext/standard/basic_functions.h"
45 #include "ext/standard/php_filestat.h"
46 
47 #define SPL_HAS_FLAG(flags, test_flag) ((flags & test_flag) ? 1 : 0)
48 
49 /* declare the class handlers */
50 static zend_object_handlers spl_filesystem_object_handlers;
51 /* includes handler to validate object state when retrieving methods */
52 static zend_object_handlers spl_filesystem_object_check_handlers;
53 
54 /* decalre the class entry */
55 PHPAPI zend_class_entry *spl_ce_SplFileInfo;
56 PHPAPI zend_class_entry *spl_ce_DirectoryIterator;
57 PHPAPI zend_class_entry *spl_ce_FilesystemIterator;
58 PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator;
59 PHPAPI zend_class_entry *spl_ce_GlobIterator;
60 PHPAPI zend_class_entry *spl_ce_SplFileObject;
61 PHPAPI zend_class_entry *spl_ce_SplTempFileObject;
62 
spl_filesystem_file_free_line(spl_filesystem_object * intern)63 static void spl_filesystem_file_free_line(spl_filesystem_object *intern) /* {{{ */
64 {
65 	if (intern->u.file.current_line) {
66 		efree(intern->u.file.current_line);
67 		intern->u.file.current_line = NULL;
68 	}
69 	if (!Z_ISUNDEF(intern->u.file.current_zval)) {
70 		zval_ptr_dtor(&intern->u.file.current_zval);
71 		ZVAL_UNDEF(&intern->u.file.current_zval);
72 	}
73 } /* }}} */
74 
spl_filesystem_object_free_storage(zend_object * object)75 static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
76 {
77 	spl_filesystem_object *intern = spl_filesystem_from_obj(object);
78 
79 	if (intern->oth_handler && intern->oth_handler->dtor) {
80 		intern->oth_handler->dtor(intern);
81 	}
82 
83 	zend_object_std_dtor(&intern->std);
84 
85 	if (intern->_path) {
86 		efree(intern->_path);
87 	}
88 	if (intern->file_name) {
89 		efree(intern->file_name);
90 	}
91 	switch(intern->type) {
92 	case SPL_FS_INFO:
93 		break;
94 	case SPL_FS_DIR:
95 		if (intern->u.dir.dirp) {
96 			php_stream_close(intern->u.dir.dirp);
97 			intern->u.dir.dirp = NULL;
98 		}
99 		if (intern->u.dir.sub_path) {
100 			efree(intern->u.dir.sub_path);
101 		}
102 		break;
103 	case SPL_FS_FILE:
104 		if (intern->u.file.stream) {
105 			/*
106 			if (intern->u.file.zcontext) {
107 			   zend_list_delref(Z_RESVAL_P(intern->zcontext));
108 			}
109 			*/
110 			if (!intern->u.file.stream->is_persistent) {
111 				php_stream_close(intern->u.file.stream);
112 			} else {
113 				php_stream_pclose(intern->u.file.stream);
114 			}
115 			if (intern->u.file.open_mode) {
116 				efree(intern->u.file.open_mode);
117 			}
118 			if (intern->orig_path) {
119 				efree(intern->orig_path);
120 			}
121 		}
122 		spl_filesystem_file_free_line(intern);
123 		break;
124 	}
125 } /* }}} */
126 
127 /* {{{ spl_ce_dir_object_new */
128 /* creates the object by
129    - allocating memory
130    - initializing the object members
131    - storing the object
132    - setting it's handlers
133 
134    called from
135    - clone
136    - new
137  */
spl_filesystem_object_new_ex(zend_class_entry * class_type)138 static zend_object *spl_filesystem_object_new_ex(zend_class_entry *class_type)
139 {
140 	spl_filesystem_object *intern;
141 
142 	intern = ecalloc(1, sizeof(spl_filesystem_object) + zend_object_properties_size(class_type));
143 	/* intern->type = SPL_FS_INFO; done by set 0 */
144 	intern->file_class = spl_ce_SplFileObject;
145 	intern->info_class = spl_ce_SplFileInfo;
146 
147 	zend_object_std_init(&intern->std, class_type);
148 	object_properties_init(&intern->std, class_type);
149 	intern->std.handlers = &spl_filesystem_object_handlers;
150 
151 	return &intern->std;
152 }
153 /* }}} */
154 
155 /* {{{ spl_filesystem_object_new */
156 /* See spl_filesystem_object_new_ex */
spl_filesystem_object_new(zend_class_entry * class_type)157 static zend_object *spl_filesystem_object_new(zend_class_entry *class_type)
158 {
159 	return spl_filesystem_object_new_ex(class_type);
160 }
161 /* }}} */
162 
163 /* {{{ spl_filesystem_object_new_check */
spl_filesystem_object_new_check(zend_class_entry * class_type)164 static zend_object *spl_filesystem_object_new_check(zend_class_entry *class_type)
165 {
166 	spl_filesystem_object *ret = spl_filesystem_from_obj(spl_filesystem_object_new_ex(class_type));
167 	ret->std.handlers = &spl_filesystem_object_check_handlers;
168 	return &ret->std;
169 }
170 /* }}} */
171 
spl_filesystem_object_get_path(spl_filesystem_object * intern,size_t * len)172 PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len) /* {{{ */
173 {
174 #ifdef HAVE_GLOB
175 	if (intern->type == SPL_FS_DIR) {
176 		if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
177 			return php_glob_stream_get_path(intern->u.dir.dirp, 0, len);
178 		}
179 	}
180 #endif
181 	if (len) {
182 		*len = intern->_path_len;
183 	}
184 	return intern->_path;
185 } /* }}} */
186 
spl_filesystem_object_get_file_name(spl_filesystem_object * intern)187 static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */
188 {
189 	char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
190 
191 	switch (intern->type) {
192 		case SPL_FS_INFO:
193 		case SPL_FS_FILE:
194 			if (!intern->file_name) {
195 				php_error_docref(NULL, E_ERROR, "Object not initialized");
196 			}
197 			break;
198 		case SPL_FS_DIR:
199 			if (intern->file_name) {
200 				efree(intern->file_name);
201 			}
202 			intern->file_name_len = spprintf(&intern->file_name, 0, "%s%c%s",
203 			                                 spl_filesystem_object_get_path(intern, NULL),
204 			                                 slash, intern->u.dir.entry.d_name);
205 			break;
206 	}
207 } /* }}} */
208 
spl_filesystem_dir_read(spl_filesystem_object * intern)209 static int spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */
210 {
211 	if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
212 		intern->u.dir.entry.d_name[0] = '\0';
213 		return 0;
214 	} else {
215 		return 1;
216 	}
217 }
218 /* }}} */
219 
220 #define IS_SLASH_AT(zs, pos) (IS_SLASH(zs[pos]))
221 
spl_filesystem_is_dot(const char * d_name)222 static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */
223 {
224 	return !strcmp(d_name, ".") || !strcmp(d_name, "..");
225 }
226 /* }}} */
227 
228 /* {{{ spl_filesystem_dir_open */
229 /* open a directory resource */
spl_filesystem_dir_open(spl_filesystem_object * intern,char * path)230 static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path)
231 {
232 	int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
233 
234 	intern->type = SPL_FS_DIR;
235 	intern->_path_len = strlen(path);
236 	intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context));
237 
238 	if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) {
239 		intern->_path = estrndup(path, --intern->_path_len);
240 	} else {
241 		intern->_path = estrndup(path, intern->_path_len);
242 	}
243 	intern->u.dir.index = 0;
244 
245 	if (EG(exception) || intern->u.dir.dirp == NULL) {
246 		intern->u.dir.entry.d_name[0] = '\0';
247 		if (!EG(exception)) {
248 			/* open failed w/out notice (turned to exception due to EH_THROW) */
249 			zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
250 				"Failed to open directory \"%s\"", path);
251 		}
252 	} else {
253 		do {
254 			spl_filesystem_dir_read(intern);
255 		} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
256 	}
257 }
258 /* }}} */
259 
spl_filesystem_file_open(spl_filesystem_object * intern,int use_include_path,int silent)260 static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent) /* {{{ */
261 {
262 	zval tmp;
263 
264 	intern->type = SPL_FS_FILE;
265 
266 	php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, &tmp);
267 	if (Z_TYPE(tmp) == IS_TRUE) {
268 		intern->u.file.open_mode = NULL;
269 		intern->file_name = NULL;
270 		zend_throw_exception_ex(spl_ce_LogicException, 0, "Cannot use SplFileObject with directories");
271 		return FAILURE;
272 	}
273 
274 	intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0);
275 	intern->u.file.stream = php_stream_open_wrapper_ex(intern->file_name, intern->u.file.open_mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, intern->u.file.context);
276 
277 	if (!intern->file_name_len || !intern->u.file.stream) {
278 		if (!EG(exception)) {
279 			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", intern->file_name_len ? intern->file_name : "");
280 		}
281 		intern->file_name = NULL; /* until here it is not a copy */
282 		intern->u.file.open_mode = NULL;
283 		return FAILURE;
284 	}
285 
286 	/*
287 	if (intern->u.file.zcontext) {
288 		//zend_list_addref(Z_RES_VAL(intern->u.file.zcontext));
289 		Z_ADDREF_P(intern->u.file.zcontext);
290 	}
291 	*/
292 
293 	if (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
294 		intern->file_name_len--;
295 	}
296 
297 	intern->orig_path = estrndup(intern->u.file.stream->orig_path, strlen(intern->u.file.stream->orig_path));
298 
299 	intern->file_name = estrndup(intern->file_name, intern->file_name_len);
300 	intern->u.file.open_mode = estrndup(intern->u.file.open_mode, intern->u.file.open_mode_len);
301 
302 	/* avoid reference counting in debug mode, thus do it manually */
303 	ZVAL_RES(&intern->u.file.zresource, intern->u.file.stream->res);
304 	/*!!! TODO: maybe bug?
305 	Z_SET_REFCOUNT(intern->u.file.zresource, 1);
306 	*/
307 
308 	intern->u.file.delimiter = ',';
309 	intern->u.file.enclosure = '"';
310 	intern->u.file.escape = '\\';
311 
312 	intern->u.file.func_getCurr = zend_hash_str_find_ptr(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline") - 1);
313 
314 	return SUCCESS;
315 } /* }}} */
316 
317 /* {{{ spl_filesystem_object_clone */
318 /* Local zend_object creation (on stack)
319    Load the 'other' object
320    Create a new empty object (See spl_filesystem_object_new_ex)
321    Open the directory
322    Clone other members (properties)
323  */
spl_filesystem_object_clone(zval * zobject)324 static zend_object *spl_filesystem_object_clone(zval *zobject)
325 {
326 	zend_object *old_object;
327 	zend_object *new_object;
328 	spl_filesystem_object *intern;
329 	spl_filesystem_object *source;
330 	int index, skip_dots;
331 
332 	old_object = Z_OBJ_P(zobject);
333 	source = spl_filesystem_from_obj(old_object);
334 	new_object = spl_filesystem_object_new_ex(old_object->ce);
335 	intern = spl_filesystem_from_obj(new_object);
336 
337 	intern->flags = source->flags;
338 
339 	switch (source->type) {
340 		case SPL_FS_INFO:
341 			intern->_path_len = source->_path_len;
342 			intern->_path = estrndup(source->_path, source->_path_len);
343 			intern->file_name_len = source->file_name_len;
344 			intern->file_name = estrndup(source->file_name, intern->file_name_len);
345 			break;
346 		case SPL_FS_DIR:
347 			spl_filesystem_dir_open(intern, source->_path);
348 			/* read until we hit the position in which we were before */
349 			skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS);
350 			for(index = 0; index < source->u.dir.index; ++index) {
351 				do {
352 					spl_filesystem_dir_read(intern);
353 				} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
354 			}
355 			intern->u.dir.index = index;
356 			break;
357 		case SPL_FS_FILE:
358 			zend_throw_error(NULL, "An object of class %s cannot be cloned", ZSTR_VAL(old_object->ce->name));
359 			return new_object;
360 	}
361 
362 	intern->file_class = source->file_class;
363 	intern->info_class = source->info_class;
364 	intern->oth = source->oth;
365 	intern->oth_handler = source->oth_handler;
366 
367 	zend_objects_clone_members(new_object, old_object);
368 
369 	if (intern->oth_handler && intern->oth_handler->clone) {
370 		intern->oth_handler->clone(source, intern);
371 	}
372 
373 	return new_object;
374 }
375 /* }}} */
376 
spl_filesystem_info_set_filename(spl_filesystem_object * intern,char * path,size_t len,size_t use_copy)377 void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, size_t len, size_t use_copy) /* {{{ */
378 {
379 	char *p1, *p2;
380 
381 	if (intern->file_name) {
382 		efree(intern->file_name);
383 	}
384 
385 	intern->file_name = use_copy ? estrndup(path, len) : path;
386 	intern->file_name_len = len;
387 
388 	while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
389 		intern->file_name[intern->file_name_len-1] = 0;
390 		intern->file_name_len--;
391 	}
392 
393 	p1 = strrchr(intern->file_name, '/');
394 #if defined(PHP_WIN32) || defined(NETWARE)
395 	p2 = strrchr(intern->file_name, '\\');
396 #else
397 	p2 = 0;
398 #endif
399 	if (p1 || p2) {
400 		intern->_path_len = ((p1 > p2 ? p1 : p2) - intern->file_name);
401 	} else {
402 		intern->_path_len = 0;
403 	}
404 
405 	if (intern->_path) {
406 		efree(intern->_path);
407 	}
408 	intern->_path = estrndup(path, intern->_path_len);
409 } /* }}} */
410 
spl_filesystem_object_create_info(spl_filesystem_object * source,char * file_path,size_t file_path_len,int use_copy,zend_class_entry * ce,zval * return_value)411 static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, size_t file_path_len, int use_copy, zend_class_entry *ce, zval *return_value) /* {{{ */
412 {
413 	spl_filesystem_object *intern;
414 	zval arg1;
415 	zend_error_handling error_handling;
416 
417 	if (!file_path || !file_path_len) {
418 #if defined(PHP_WIN32)
419 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot create SplFileInfo for empty path");
420 		if (file_path && !use_copy) {
421 			efree(file_path);
422 		}
423 #else
424 		if (file_path && !use_copy) {
425 			efree(file_path);
426 		}
427 		file_path_len = 1;
428 		file_path = "/";
429 #endif
430 		return NULL;
431 	}
432 
433 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
434 
435 	ce = ce ? ce : source->info_class;
436 
437 	zend_update_class_constants(ce);
438 
439 	intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
440 	ZVAL_OBJ(return_value, &intern->std);
441 
442 	if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
443 		ZVAL_STRINGL(&arg1, file_path, file_path_len);
444 		zend_call_method_with_1_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1);
445 		zval_ptr_dtor(&arg1);
446 	} else {
447 		spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy);
448 	}
449 
450 	zend_restore_error_handling(&error_handling);
451 	return intern;
452 } /* }}} */
453 
spl_filesystem_object_create_type(int ht,spl_filesystem_object * source,int type,zend_class_entry * ce,zval * return_value)454 static spl_filesystem_object *spl_filesystem_object_create_type(int ht, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value) /* {{{ */
455 {
456 	spl_filesystem_object *intern;
457 	zend_bool use_include_path = 0;
458 	zval arg1, arg2;
459 	zend_error_handling error_handling;
460 
461 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
462 
463 	switch (source->type) {
464 		case SPL_FS_INFO:
465 		case SPL_FS_FILE:
466 			break;
467 		case SPL_FS_DIR:
468 			if (!source->u.dir.entry.d_name[0]) {
469 				zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Could not open file");
470 				zend_restore_error_handling(&error_handling);
471 				return NULL;
472 			}
473 	}
474 
475 	switch (type) {
476 		case SPL_FS_INFO:
477 			ce = ce ? ce : source->info_class;
478 
479 			if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
480 				break;
481 			}
482 
483 			intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
484 			ZVAL_OBJ(return_value, &intern->std);
485 
486 			spl_filesystem_object_get_file_name(source);
487 			if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
488 				ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
489 				zend_call_method_with_1_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1);
490 				zval_ptr_dtor(&arg1);
491 			} else {
492 				intern->file_name = estrndup(source->file_name, source->file_name_len);
493 				intern->file_name_len = source->file_name_len;
494 				intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
495 				intern->_path = estrndup(intern->_path, intern->_path_len);
496 			}
497 			break;
498 		case SPL_FS_FILE:
499 			ce = ce ? ce : source->file_class;
500 
501 			if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
502 				break;
503 			}
504 
505 			intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
506 
507 			ZVAL_OBJ(return_value, &intern->std);
508 
509 			spl_filesystem_object_get_file_name(source);
510 
511 			if (ce->constructor->common.scope != spl_ce_SplFileObject) {
512 				ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
513 				ZVAL_STRINGL(&arg2, "r", 1);
514 				zend_call_method_with_2_params(return_value, ce, &ce->constructor, "__construct", NULL, &arg1, &arg2);
515 				zval_ptr_dtor(&arg1);
516 				zval_ptr_dtor(&arg2);
517 			} else {
518 				intern->file_name = source->file_name;
519 				intern->file_name_len = source->file_name_len;
520 				intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
521 				intern->_path = estrndup(intern->_path, intern->_path_len);
522 
523 				intern->u.file.open_mode = "r";
524 				intern->u.file.open_mode_len = 1;
525 
526 				if (ht && zend_parse_parameters(ht, "|sbr",
527 							&intern->u.file.open_mode, &intern->u.file.open_mode_len,
528 							&use_include_path, &intern->u.file.zcontext) == FAILURE) {
529 					zend_restore_error_handling(&error_handling);
530 					intern->u.file.open_mode = NULL;
531 					intern->file_name = NULL;
532 					zval_ptr_dtor(return_value);
533 					ZVAL_NULL(return_value);
534 					return NULL;
535 				}
536 
537 				if (spl_filesystem_file_open(intern, use_include_path, 0) == FAILURE) {
538 					zend_restore_error_handling(&error_handling);
539 					zval_ptr_dtor(return_value);
540 					ZVAL_NULL(return_value);
541 					return NULL;
542 				}
543 			}
544 			break;
545 		case SPL_FS_DIR:
546 			zend_restore_error_handling(&error_handling);
547 			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Operation not supported");
548 			return NULL;
549 	}
550 	zend_restore_error_handling(&error_handling);
551 	return NULL;
552 } /* }}} */
553 
spl_filesystem_is_invalid_or_dot(const char * d_name)554 static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */
555 {
556 	return d_name[0] == '\0' || spl_filesystem_is_dot(d_name);
557 }
558 /* }}} */
559 
spl_filesystem_object_get_pathname(spl_filesystem_object * intern,size_t * len)560 static char *spl_filesystem_object_get_pathname(spl_filesystem_object *intern, size_t *len) { /* {{{ */
561 	switch (intern->type) {
562 		case SPL_FS_INFO:
563 		case SPL_FS_FILE:
564 			*len = intern->file_name_len;
565 			return intern->file_name;
566 		case SPL_FS_DIR:
567 			if (intern->u.dir.entry.d_name[0]) {
568 				spl_filesystem_object_get_file_name(intern);
569 				*len = intern->file_name_len;
570 				return intern->file_name;
571 			}
572 	}
573 	*len = 0;
574 	return NULL;
575 }
576 /* }}} */
577 
spl_filesystem_object_get_debug_info(zval * object,int * is_temp)578 static HashTable *spl_filesystem_object_get_debug_info(zval *object, int *is_temp) /* {{{ */
579 {
580 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(object);
581 	zval tmp;
582 	HashTable *rv;
583 	zend_string *pnstr;
584 	char *path;
585 	size_t  path_len;
586 	char stmp[2];
587 
588 	*is_temp = 1;
589 
590 	if (!intern->std.properties) {
591 		rebuild_object_properties(&intern->std);
592 	}
593 
594 	rv = zend_array_dup(intern->std.properties);
595 
596 	pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1);
597 	path = spl_filesystem_object_get_pathname(intern, &path_len);
598 	ZVAL_STRINGL(&tmp, path, path_len);
599 	zend_symtable_update(rv, pnstr, &tmp);
600 	zend_string_release(pnstr);
601 
602 	if (intern->file_name) {
603 		pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1);
604 		spl_filesystem_object_get_path(intern, &path_len);
605 
606 		if (path_len && path_len < intern->file_name_len) {
607 			ZVAL_STRINGL(&tmp, intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
608 		} else {
609 			ZVAL_STRINGL(&tmp, intern->file_name, intern->file_name_len);
610 		}
611 		zend_symtable_update(rv, pnstr, &tmp);
612 		zend_string_release(pnstr);
613 	}
614 	if (intern->type == SPL_FS_DIR) {
615 #ifdef HAVE_GLOB
616 		pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1);
617 		if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
618 			ZVAL_STRINGL(&tmp, intern->_path, intern->_path_len);
619 		} else {
620 			ZVAL_FALSE(&tmp);
621 		}
622 		zend_symtable_update(rv, pnstr, &tmp);
623 		zend_string_release(pnstr);
624 #endif
625 		pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1);
626 		if (intern->u.dir.sub_path) {
627 			ZVAL_STRINGL(&tmp, intern->u.dir.sub_path, intern->u.dir.sub_path_len);
628 		} else {
629 			ZVAL_EMPTY_STRING(&tmp);
630 		}
631 		zend_symtable_update(rv, pnstr, &tmp);
632 		zend_string_release(pnstr);
633 	}
634 	if (intern->type == SPL_FS_FILE) {
635 		pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "openMode", sizeof("openMode")-1);
636 		ZVAL_STRINGL(&tmp, intern->u.file.open_mode, intern->u.file.open_mode_len);
637 		zend_symtable_update(rv, pnstr, &tmp);
638 		zend_string_release(pnstr);
639 		stmp[1] = '\0';
640 		stmp[0] = intern->u.file.delimiter;
641 		pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "delimiter", sizeof("delimiter")-1);
642 		ZVAL_STRINGL(&tmp, stmp, 1);
643 		zend_symtable_update(rv, pnstr, &tmp);
644 		zend_string_release(pnstr);
645 		stmp[0] = intern->u.file.enclosure;
646 		pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "enclosure", sizeof("enclosure")-1);
647 		ZVAL_STRINGL(&tmp, stmp, 1);
648 		zend_symtable_update(rv, pnstr, &tmp);
649 		zend_string_release(pnstr);
650 	}
651 
652 	return rv;
653 }
654 /* }}} */
655 
spl_filesystem_object_get_method_check(zend_object ** object,zend_string * method,const zval * key)656 zend_function *spl_filesystem_object_get_method_check(zend_object **object, zend_string *method, const zval *key) /* {{{ */
657 {
658 	spl_filesystem_object *fsobj = spl_filesystem_from_obj(*object);
659 
660 	if (fsobj->u.dir.dirp == NULL && fsobj->orig_path == NULL) {
661 		zend_function *func;
662 		zend_string *tmp = zend_string_init("_bad_state_ex", sizeof("_bad_state_ex") - 1, 0);
663 		func = zend_get_std_object_handlers()->get_method(object, tmp, NULL);
664 		zend_string_release(tmp);
665 		return func;
666 	}
667 
668 	return zend_get_std_object_handlers()->get_method(object, method, key);
669 }
670 /* }}} */
671 
672 #define DIT_CTOR_FLAGS  0x00000001
673 #define DIT_CTOR_GLOB   0x00000002
674 
spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS,zend_long ctor_flags)675 void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long ctor_flags) /* {{{ */
676 {
677 	spl_filesystem_object *intern;
678 	char *path;
679 	int parsed;
680 	size_t len;
681 	zend_long flags;
682 	zend_error_handling error_handling;
683 
684 	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
685 
686 	if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
687 		flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
688 		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &path, &len, &flags);
689 	} else {
690 		flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
691 		parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "s", &path, &len);
692 	}
693 	if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_SKIPDOTS)) {
694 		flags |= SPL_FILE_DIR_SKIPDOTS;
695 	}
696 	if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_UNIXPATHS)) {
697 		flags |= SPL_FILE_DIR_UNIXPATHS;
698 	}
699 	if (parsed == FAILURE) {
700 		zend_restore_error_handling(&error_handling);
701 		return;
702 	}
703 	if (!len) {
704 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Directory name must not be empty.");
705 		zend_restore_error_handling(&error_handling);
706 		return;
707 	}
708 
709 	intern = Z_SPLFILESYSTEM_P(getThis());
710 	if (intern->_path) {
711 		/* object is alreay initialized */
712 		zend_restore_error_handling(&error_handling);
713 		php_error_docref(NULL, E_WARNING, "Directory object is already initialized");
714 		return;
715 	}
716 	intern->flags = flags;
717 #ifdef HAVE_GLOB
718 	if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && strstr(path, "glob://") != path) {
719 		spprintf(&path, 0, "glob://%s", path);
720 		spl_filesystem_dir_open(intern, path);
721 		efree(path);
722 	} else
723 #endif
724 	{
725 		spl_filesystem_dir_open(intern, path);
726 
727 	}
728 
729 	intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator) ? 1 : 0;
730 
731 	zend_restore_error_handling(&error_handling);
732 }
733 /* }}} */
734 
735 /* {{{ proto void DirectoryIterator::__construct(string path)
736  Cronstructs a new dir iterator from a path. */
SPL_METHOD(DirectoryIterator,__construct)737 SPL_METHOD(DirectoryIterator, __construct)
738 {
739 	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
740 }
741 /* }}} */
742 
743 /* {{{ proto void DirectoryIterator::rewind()
744    Rewind dir back to the start */
SPL_METHOD(DirectoryIterator,rewind)745 SPL_METHOD(DirectoryIterator, rewind)
746 {
747 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
748 
749 	if (zend_parse_parameters_none() == FAILURE) {
750 		return;
751 	}
752 
753 	intern->u.dir.index = 0;
754 	if (intern->u.dir.dirp) {
755 		php_stream_rewinddir(intern->u.dir.dirp);
756 	}
757 	spl_filesystem_dir_read(intern);
758 }
759 /* }}} */
760 
761 /* {{{ proto string DirectoryIterator::key()
762    Return current dir entry */
SPL_METHOD(DirectoryIterator,key)763 SPL_METHOD(DirectoryIterator, key)
764 {
765 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
766 
767 	if (zend_parse_parameters_none() == FAILURE) {
768 		return;
769 	}
770 
771 	if (intern->u.dir.dirp) {
772 		RETURN_LONG(intern->u.dir.index);
773 	} else {
774 		RETURN_FALSE;
775 	}
776 }
777 /* }}} */
778 
779 /* {{{ proto DirectoryIterator DirectoryIterator::current()
780    Return this (needed for Iterator interface) */
SPL_METHOD(DirectoryIterator,current)781 SPL_METHOD(DirectoryIterator, current)
782 {
783 	if (zend_parse_parameters_none() == FAILURE) {
784 		return;
785 	}
786 	ZVAL_OBJ(return_value, Z_OBJ_P(getThis()));
787 	Z_ADDREF_P(return_value);
788 }
789 /* }}} */
790 
791 /* {{{ proto void DirectoryIterator::next()
792    Move to next entry */
SPL_METHOD(DirectoryIterator,next)793 SPL_METHOD(DirectoryIterator, next)
794 {
795 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
796 	int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
797 
798 	if (zend_parse_parameters_none() == FAILURE) {
799 		return;
800 	}
801 
802 	intern->u.dir.index++;
803 	do {
804 		spl_filesystem_dir_read(intern);
805 	} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
806 	if (intern->file_name) {
807 		efree(intern->file_name);
808 		intern->file_name = NULL;
809 	}
810 }
811 /* }}} */
812 
813 /* {{{ proto void DirectoryIterator::seek(int position)
814    Seek to the given position */
SPL_METHOD(DirectoryIterator,seek)815 SPL_METHOD(DirectoryIterator, seek)
816 {
817 	spl_filesystem_object *intern    = Z_SPLFILESYSTEM_P(getThis());
818 	zval retval;
819 	zend_long pos;
820 
821 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &pos) == FAILURE) {
822 		return;
823 	}
824 
825 	if (intern->u.dir.index > pos) {
826 		/* we first rewind */
827 		zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_rewind, "rewind", NULL);
828 	}
829 
830 	while (intern->u.dir.index < pos) {
831 		int valid = 0;
832 		zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_valid, "valid", &retval);
833 		if (!Z_ISUNDEF(retval)) {
834 			valid = zend_is_true(&retval);
835 			zval_ptr_dtor(&retval);
836 		}
837 		if (!valid) {
838 			zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position " ZEND_LONG_FMT " is out of range", pos);
839 			return;
840 		}
841 		zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_next, "next", NULL);
842 	}
843 } /* }}} */
844 
845 /* {{{ proto string DirectoryIterator::valid()
846    Check whether dir contains more entries */
SPL_METHOD(DirectoryIterator,valid)847 SPL_METHOD(DirectoryIterator, valid)
848 {
849 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
850 
851 	if (zend_parse_parameters_none() == FAILURE) {
852 		return;
853 	}
854 
855 	RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0');
856 }
857 /* }}} */
858 
859 /* {{{ proto string SplFileInfo::getPath()
860    Return the path */
SPL_METHOD(SplFileInfo,getPath)861 SPL_METHOD(SplFileInfo, getPath)
862 {
863 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
864 	char *path;
865 	size_t path_len;
866 
867 	if (zend_parse_parameters_none() == FAILURE) {
868 		return;
869 	}
870 
871   	path = spl_filesystem_object_get_path(intern, &path_len);
872 	RETURN_STRINGL(path, path_len);
873 }
874 /* }}} */
875 
876 /* {{{ proto string SplFileInfo::getFilename()
877    Return filename only */
SPL_METHOD(SplFileInfo,getFilename)878 SPL_METHOD(SplFileInfo, getFilename)
879 {
880 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
881 	size_t path_len;
882 
883 	if (zend_parse_parameters_none() == FAILURE) {
884 		return;
885 	}
886 
887 	spl_filesystem_object_get_path(intern, &path_len);
888 
889 	if (path_len && path_len < intern->file_name_len) {
890 		RETURN_STRINGL(intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
891 	} else {
892 		RETURN_STRINGL(intern->file_name, intern->file_name_len);
893 	}
894 }
895 /* }}} */
896 
897 /* {{{ proto string DirectoryIterator::getFilename()
898    Return filename of current dir entry */
SPL_METHOD(DirectoryIterator,getFilename)899 SPL_METHOD(DirectoryIterator, getFilename)
900 {
901 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
902 
903 	if (zend_parse_parameters_none() == FAILURE) {
904 		return;
905 	}
906 
907 	RETURN_STRING(intern->u.dir.entry.d_name);
908 }
909 /* }}} */
910 
911 /* {{{ proto string SplFileInfo::getExtension()
912    Returns file extension component of path */
SPL_METHOD(SplFileInfo,getExtension)913 SPL_METHOD(SplFileInfo, getExtension)
914 {
915 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
916 	char *fname = NULL;
917 	const char *p;
918 	size_t flen;
919 	size_t path_len;
920 	size_t idx;
921 	zend_string *ret;
922 
923 	if (zend_parse_parameters_none() == FAILURE) {
924 		return;
925 	}
926 
927 	spl_filesystem_object_get_path(intern, &path_len);
928 
929 	if (path_len && path_len < intern->file_name_len) {
930 		fname = intern->file_name + path_len + 1;
931 		flen = intern->file_name_len - (path_len + 1);
932 	} else {
933 		fname = intern->file_name;
934 		flen = intern->file_name_len;
935 	}
936 
937 	ret = php_basename(fname, flen, NULL, 0);
938 
939 	p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
940 	if (p) {
941 		idx = p - ZSTR_VAL(ret);
942 		RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
943 		zend_string_release(ret);
944 		return;
945 	} else {
946 		zend_string_release(ret);
947 		RETURN_EMPTY_STRING();
948 	}
949 }
950 /* }}}*/
951 
952 /* {{{ proto string DirectoryIterator::getExtension()
953    Returns the file extension component of path */
SPL_METHOD(DirectoryIterator,getExtension)954 SPL_METHOD(DirectoryIterator, getExtension)
955 {
956 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
957 	const char *p;
958 	size_t idx;
959 	zend_string *fname;
960 
961 	if (zend_parse_parameters_none() == FAILURE) {
962 		return;
963 	}
964 
965 	fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0);
966 
967 	p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname));
968 	if (p) {
969 		idx = p - ZSTR_VAL(fname);
970 		RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1);
971 		zend_string_release(fname);
972 	} else {
973 		zend_string_release(fname);
974 		RETURN_EMPTY_STRING();
975 	}
976 }
977 /* }}} */
978 
979 /* {{{ proto string SplFileInfo::getBasename([string $suffix])
980    Returns filename component of path */
SPL_METHOD(SplFileInfo,getBasename)981 SPL_METHOD(SplFileInfo, getBasename)
982 {
983 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
984 	char *fname, *suffix = 0;
985 	size_t flen;
986 	size_t slen = 0, path_len;
987 
988 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
989 		return;
990 	}
991 
992 	spl_filesystem_object_get_path(intern, &path_len);
993 
994 	if (path_len && path_len < intern->file_name_len) {
995 		fname = intern->file_name + path_len + 1;
996 		flen = intern->file_name_len - (path_len + 1);
997 	} else {
998 		fname = intern->file_name;
999 		flen = intern->file_name_len;
1000 	}
1001 
1002 	RETURN_STR(php_basename(fname, flen, suffix, slen));
1003 }
1004 /* }}}*/
1005 
1006 /* {{{ proto string DirectoryIterator::getBasename([string $suffix])
1007    Returns filename component of current dir entry */
SPL_METHOD(DirectoryIterator,getBasename)1008 SPL_METHOD(DirectoryIterator, getBasename)
1009 {
1010 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1011 	char *suffix = 0;
1012 	size_t slen = 0;
1013 	zend_string *fname;
1014 
1015 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
1016 		return;
1017 	}
1018 
1019 	fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), suffix, slen);
1020 
1021 	RETVAL_STR(fname);
1022 }
1023 /* }}} */
1024 
1025 /* {{{ proto string SplFileInfo::getPathname()
1026    Return path and filename */
SPL_METHOD(SplFileInfo,getPathname)1027 SPL_METHOD(SplFileInfo, getPathname)
1028 {
1029 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1030 	char *path;
1031 	size_t path_len;
1032 
1033 	if (zend_parse_parameters_none() == FAILURE) {
1034 		return;
1035 	}
1036 	path = spl_filesystem_object_get_pathname(intern, &path_len);
1037 	if (path != NULL) {
1038 		RETURN_STRINGL(path, path_len);
1039 	} else {
1040 		RETURN_FALSE;
1041 	}
1042 }
1043 /* }}} */
1044 
1045 /* {{{ proto string FilesystemIterator::key()
1046    Return getPathname() or getFilename() depending on flags */
SPL_METHOD(FilesystemIterator,key)1047 SPL_METHOD(FilesystemIterator, key)
1048 {
1049 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1050 
1051 	if (zend_parse_parameters_none() == FAILURE) {
1052 		return;
1053 	}
1054 
1055 	if (SPL_FILE_DIR_KEY(intern, SPL_FILE_DIR_KEY_AS_FILENAME)) {
1056 		RETURN_STRING(intern->u.dir.entry.d_name);
1057 	} else {
1058 		spl_filesystem_object_get_file_name(intern);
1059 		RETURN_STRINGL(intern->file_name, intern->file_name_len);
1060 	}
1061 }
1062 /* }}} */
1063 
1064 /* {{{ proto string FilesystemIterator::current()
1065    Return getFilename(), getFileInfo() or $this depending on flags */
SPL_METHOD(FilesystemIterator,current)1066 SPL_METHOD(FilesystemIterator, current)
1067 {
1068 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1069 
1070 	if (zend_parse_parameters_none() == FAILURE) {
1071 		return;
1072 	}
1073 
1074 	if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
1075 		spl_filesystem_object_get_file_name(intern);
1076 		RETURN_STRINGL(intern->file_name, intern->file_name_len);
1077 	} else if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
1078 		spl_filesystem_object_get_file_name(intern);
1079 		spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value);
1080 	} else {
1081 		ZVAL_OBJ(return_value, Z_OBJ_P(getThis()));
1082 		Z_ADDREF_P(return_value);
1083 		/*RETURN_STRING(intern->u.dir.entry.d_name, 1);*/
1084 	}
1085 }
1086 /* }}} */
1087 
1088 /* {{{ proto bool DirectoryIterator::isDot()
1089    Returns true if current entry is '.' or  '..' */
SPL_METHOD(DirectoryIterator,isDot)1090 SPL_METHOD(DirectoryIterator, isDot)
1091 {
1092 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1093 
1094 	if (zend_parse_parameters_none() == FAILURE) {
1095 		return;
1096 	}
1097 
1098 	RETURN_BOOL(spl_filesystem_is_dot(intern->u.dir.entry.d_name));
1099 }
1100 /* }}} */
1101 
1102 /* {{{ proto void SplFileInfo::__construct(string file_name)
1103  Cronstructs a new SplFileInfo from a path. */
1104 /* When the constructor gets called the object is already created
1105    by the engine, so we must only call 'additional' initializations.
1106  */
SPL_METHOD(SplFileInfo,__construct)1107 SPL_METHOD(SplFileInfo, __construct)
1108 {
1109 	spl_filesystem_object *intern;
1110 	char *path;
1111 	size_t len;
1112 
1113 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p", &path, &len) == FAILURE) {
1114 		return;
1115 	}
1116 
1117 	intern = Z_SPLFILESYSTEM_P(getThis());
1118 
1119 	spl_filesystem_info_set_filename(intern, path, len, 1);
1120 
1121 	/* intern->type = SPL_FS_INFO; already set */
1122 }
1123 /* }}} */
1124 
1125 /* {{{ FileInfoFunction */
1126 #define FileInfoFunction(func_name, func_num) \
1127 SPL_METHOD(SplFileInfo, func_name) \
1128 { \
1129 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); \
1130 	zend_error_handling error_handling; \
1131 	if (zend_parse_parameters_none() == FAILURE) { \
1132 		return; \
1133 	} \
1134  \
1135 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);\
1136 	spl_filesystem_object_get_file_name(intern); \
1137 	php_stat(intern->file_name, intern->file_name_len, func_num, return_value); \
1138 	zend_restore_error_handling(&error_handling); \
1139 }
1140 /* }}} */
1141 
1142 /* {{{ proto int SplFileInfo::getPerms()
1143    Get file permissions */
FileInfoFunction(getPerms,FS_PERMS)1144 FileInfoFunction(getPerms, FS_PERMS)
1145 /* }}} */
1146 
1147 /* {{{ proto int SplFileInfo::getInode()
1148    Get file inode */
1149 FileInfoFunction(getInode, FS_INODE)
1150 /* }}} */
1151 
1152 /* {{{ proto int SplFileInfo::getSize()
1153    Get file size */
1154 FileInfoFunction(getSize, FS_SIZE)
1155 /* }}} */
1156 
1157 /* {{{ proto int SplFileInfo::getOwner()
1158    Get file owner */
1159 FileInfoFunction(getOwner, FS_OWNER)
1160 /* }}} */
1161 
1162 /* {{{ proto int SplFileInfo::getGroup()
1163    Get file group */
1164 FileInfoFunction(getGroup, FS_GROUP)
1165 /* }}} */
1166 
1167 /* {{{ proto int SplFileInfo::getATime()
1168    Get last access time of file */
1169 FileInfoFunction(getATime, FS_ATIME)
1170 /* }}} */
1171 
1172 /* {{{ proto int SplFileInfo::getMTime()
1173    Get last modification time of file */
1174 FileInfoFunction(getMTime, FS_MTIME)
1175 /* }}} */
1176 
1177 /* {{{ proto int SplFileInfo::getCTime()
1178    Get inode modification time of file */
1179 FileInfoFunction(getCTime, FS_CTIME)
1180 /* }}} */
1181 
1182 /* {{{ proto string SplFileInfo::getType()
1183    Get file type */
1184 FileInfoFunction(getType, FS_TYPE)
1185 /* }}} */
1186 
1187 /* {{{ proto bool SplFileInfo::isWritable()
1188    Returns true if file can be written */
1189 FileInfoFunction(isWritable, FS_IS_W)
1190 /* }}} */
1191 
1192 /* {{{ proto bool SplFileInfo::isReadable()
1193    Returns true if file can be read */
1194 FileInfoFunction(isReadable, FS_IS_R)
1195 /* }}} */
1196 
1197 /* {{{ proto bool SplFileInfo::isExecutable()
1198    Returns true if file is executable */
1199 FileInfoFunction(isExecutable, FS_IS_X)
1200 /* }}} */
1201 
1202 /* {{{ proto bool SplFileInfo::isFile()
1203    Returns true if file is a regular file */
1204 FileInfoFunction(isFile, FS_IS_FILE)
1205 /* }}} */
1206 
1207 /* {{{ proto bool SplFileInfo::isDir()
1208    Returns true if file is directory */
1209 FileInfoFunction(isDir, FS_IS_DIR)
1210 /* }}} */
1211 
1212 /* {{{ proto bool SplFileInfo::isLink()
1213    Returns true if file is symbolic link */
1214 FileInfoFunction(isLink, FS_IS_LINK)
1215 /* }}} */
1216 
1217 /* {{{ proto string SplFileInfo::getLinkTarget()
1218    Return the target of a symbolic link */
1219 SPL_METHOD(SplFileInfo, getLinkTarget)
1220 {
1221 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1222 	int ret;
1223 	char buff[MAXPATHLEN];
1224 	zend_error_handling error_handling;
1225 
1226 	if (zend_parse_parameters_none() == FAILURE) {
1227 		return;
1228 	}
1229 
1230 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
1231 
1232 	if (intern->file_name == NULL) {
1233 		spl_filesystem_object_get_file_name(intern);
1234 	}
1235 #if defined(PHP_WIN32) || HAVE_SYMLINK
1236 	if (intern->file_name == NULL) {
1237 		php_error_docref(NULL, E_WARNING, "Empty filename");
1238 		RETURN_FALSE;
1239 	} else if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) {
1240 		char expanded_path[MAXPATHLEN];
1241 		if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND )) {
1242 			php_error_docref(NULL, E_WARNING, "No such file or directory");
1243 			RETURN_FALSE;
1244 		}
1245 		ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1);
1246 	} else {
1247 		ret = php_sys_readlink(intern->file_name, buff,  MAXPATHLEN-1);
1248 	}
1249 #else
1250 	ret = -1; /* always fail if not implemented */
1251 #endif
1252 
1253 	if (ret == -1) {
1254 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", intern->file_name, strerror(errno));
1255 		RETVAL_FALSE;
1256 	} else {
1257 		/* Append NULL to the end of the string */
1258 		buff[ret] = '\0';
1259 
1260 		RETVAL_STRINGL(buff, ret);
1261 	}
1262 
1263 	zend_restore_error_handling(&error_handling);
1264 }
1265 /* }}} */
1266 
1267 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
1268 /* {{{ proto string SplFileInfo::getRealPath()
1269    Return the resolved path */
SPL_METHOD(SplFileInfo,getRealPath)1270 SPL_METHOD(SplFileInfo, getRealPath)
1271 {
1272 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1273 	char buff[MAXPATHLEN];
1274 	char *filename;
1275 	zend_error_handling error_handling;
1276 
1277 	if (zend_parse_parameters_none() == FAILURE) {
1278 		return;
1279 	}
1280 
1281 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
1282 
1283 	if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) {
1284 		spl_filesystem_object_get_file_name(intern);
1285 	}
1286 
1287 	if (intern->orig_path) {
1288 		filename = intern->orig_path;
1289 	} else {
1290 		filename = intern->file_name;
1291 	}
1292 
1293 
1294 	if (filename && VCWD_REALPATH(filename, buff)) {
1295 #ifdef ZTS
1296 		if (VCWD_ACCESS(buff, F_OK)) {
1297 			RETVAL_FALSE;
1298 		} else
1299 #endif
1300 		RETVAL_STRING(buff);
1301 	} else {
1302 		RETVAL_FALSE;
1303 	}
1304 
1305 	zend_restore_error_handling(&error_handling);
1306 }
1307 /* }}} */
1308 #endif
1309 
1310 /* {{{ proto SplFileObject SplFileInfo::openFile([string mode = 'r' [, bool use_include_path  [, resource context]]])
1311    Open the current file */
SPL_METHOD(SplFileInfo,openFile)1312 SPL_METHOD(SplFileInfo, openFile)
1313 {
1314 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1315 
1316 	spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_FILE, NULL, return_value);
1317 }
1318 /* }}} */
1319 
1320 /* {{{ proto void SplFileInfo::setFileClass([string class_name])
1321    Class to use in openFile() */
SPL_METHOD(SplFileInfo,setFileClass)1322 SPL_METHOD(SplFileInfo, setFileClass)
1323 {
1324 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1325 	zend_class_entry *ce = spl_ce_SplFileObject;
1326 	zend_error_handling error_handling;
1327 
1328 	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
1329 
1330 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
1331 		intern->file_class = ce;
1332 	}
1333 
1334 	zend_restore_error_handling(&error_handling);
1335 }
1336 /* }}} */
1337 
1338 /* {{{ proto void SplFileInfo::setInfoClass([string class_name])
1339    Class to use in getFileInfo(), getPathInfo() */
SPL_METHOD(SplFileInfo,setInfoClass)1340 SPL_METHOD(SplFileInfo, setInfoClass)
1341 {
1342 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1343 	zend_class_entry *ce = spl_ce_SplFileInfo;
1344 	zend_error_handling error_handling;
1345 
1346 	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling );
1347 
1348 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
1349 		intern->info_class = ce;
1350 	}
1351 
1352 	zend_restore_error_handling(&error_handling);
1353 }
1354 /* }}} */
1355 
1356 /* {{{ proto SplFileInfo SplFileInfo::getFileInfo([string $class_name])
1357    Get/copy file info */
SPL_METHOD(SplFileInfo,getFileInfo)1358 SPL_METHOD(SplFileInfo, getFileInfo)
1359 {
1360 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1361 	zend_class_entry *ce = intern->info_class;
1362 	zend_error_handling error_handling;
1363 
1364 	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
1365 
1366 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
1367 		spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_INFO, ce, return_value);
1368 	}
1369 
1370 	zend_restore_error_handling(&error_handling);
1371 }
1372 /* }}} */
1373 
1374 /* {{{ proto SplFileInfo SplFileInfo::getPathInfo([string $class_name])
1375    Get/copy file info */
SPL_METHOD(SplFileInfo,getPathInfo)1376 SPL_METHOD(SplFileInfo, getPathInfo)
1377 {
1378 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1379 	zend_class_entry *ce = intern->info_class;
1380 	zend_error_handling error_handling;
1381 
1382 	zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
1383 
1384 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == SUCCESS) {
1385 		size_t path_len;
1386 		char *path = spl_filesystem_object_get_pathname(intern, &path_len);
1387 		if (path) {
1388 			char *dpath = estrndup(path, path_len);
1389 			path_len = php_dirname(dpath, path_len);
1390 			spl_filesystem_object_create_info(intern, dpath, path_len, 1, ce, return_value);
1391 			efree(dpath);
1392 		}
1393 	}
1394 
1395 	zend_restore_error_handling(&error_handling);
1396 }
1397 /* }}} */
1398 
1399 /* {{{  proto SplFileInfo::_bad_state_ex(void) */
SPL_METHOD(SplFileInfo,_bad_state_ex)1400 SPL_METHOD(SplFileInfo, _bad_state_ex)
1401 {
1402 	zend_throw_exception_ex(spl_ce_LogicException, 0,
1403 		"The parent constructor was not called: the object is in an "
1404 		"invalid state ");
1405 }
1406 /* }}} */
1407 
1408 /* {{{ proto void FilesystemIterator::__construct(string path [, int flags])
1409  Cronstructs a new dir iterator from a path. */
SPL_METHOD(FilesystemIterator,__construct)1410 SPL_METHOD(FilesystemIterator, __construct)
1411 {
1412 	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS | SPL_FILE_DIR_SKIPDOTS);
1413 }
1414 /* }}} */
1415 
1416 /* {{{ proto void FilesystemIterator::rewind()
1417    Rewind dir back to the start */
SPL_METHOD(FilesystemIterator,rewind)1418 SPL_METHOD(FilesystemIterator, rewind)
1419 {
1420 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1421 	int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
1422 
1423 	if (zend_parse_parameters_none() == FAILURE) {
1424 		return;
1425 	}
1426 
1427 	intern->u.dir.index = 0;
1428 	if (intern->u.dir.dirp) {
1429 		php_stream_rewinddir(intern->u.dir.dirp);
1430 	}
1431 	do {
1432 		spl_filesystem_dir_read(intern);
1433 	} while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
1434 }
1435 /* }}} */
1436 
1437 /* {{{ proto int FilesystemIterator::getFlags()
1438    Get handling flags */
SPL_METHOD(FilesystemIterator,getFlags)1439 SPL_METHOD(FilesystemIterator, getFlags)
1440 {
1441 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1442 
1443 	if (zend_parse_parameters_none() == FAILURE) {
1444 		return;
1445 	}
1446 
1447 	RETURN_LONG(intern->flags & (SPL_FILE_DIR_KEY_MODE_MASK | SPL_FILE_DIR_CURRENT_MODE_MASK | SPL_FILE_DIR_OTHERS_MASK));
1448 } /* }}} */
1449 
1450 /* {{{ proto void FilesystemIterator::setFlags(long $flags)
1451    Set handling flags */
SPL_METHOD(FilesystemIterator,setFlags)1452 SPL_METHOD(FilesystemIterator, setFlags)
1453 {
1454 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1455 	zend_long flags;
1456 
1457 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) {
1458 		return;
1459 	}
1460 
1461 	intern->flags &= ~(SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK);
1462 	intern->flags |= ((SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK) & flags);
1463 } /* }}} */
1464 
1465 /* {{{ proto bool RecursiveDirectoryIterator::hasChildren([bool $allow_links = false])
1466    Returns whether current entry is a directory and not '.' or '..' */
SPL_METHOD(RecursiveDirectoryIterator,hasChildren)1467 SPL_METHOD(RecursiveDirectoryIterator, hasChildren)
1468 {
1469 	zend_bool allow_links = 0;
1470 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1471 
1472 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &allow_links) == FAILURE) {
1473 		return;
1474 	}
1475 	if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
1476 		RETURN_FALSE;
1477 	} else {
1478 		spl_filesystem_object_get_file_name(intern);
1479 		if (!allow_links && !(intern->flags & SPL_FILE_DIR_FOLLOW_SYMLINKS)) {
1480 			php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value);
1481 			if (zend_is_true(return_value)) {
1482 				RETURN_FALSE;
1483 			}
1484 		}
1485 		php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value);
1486     }
1487 }
1488 /* }}} */
1489 
1490 /* {{{ proto RecursiveDirectoryIterator DirectoryIterator::getChildren()
1491    Returns an iterator for the current entry if it is a directory */
SPL_METHOD(RecursiveDirectoryIterator,getChildren)1492 SPL_METHOD(RecursiveDirectoryIterator, getChildren)
1493 {
1494 	zval zpath, zflags;
1495 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1496 	spl_filesystem_object *subdir;
1497 	char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
1498 
1499 	if (zend_parse_parameters_none() == FAILURE) {
1500 		return;
1501 	}
1502 
1503 	spl_filesystem_object_get_file_name(intern);
1504 
1505 	ZVAL_LONG(&zflags, intern->flags);
1506 	ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len);
1507 	spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), return_value, &zpath, &zflags);
1508 	zval_ptr_dtor(&zpath);
1509 	zval_ptr_dtor(&zflags);
1510 
1511 	subdir = Z_SPLFILESYSTEM_P(return_value);
1512 	if (subdir) {
1513 		if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
1514 			subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name);
1515 		} else {
1516 			subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name);
1517 			subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
1518 		}
1519 		subdir->info_class = intern->info_class;
1520 		subdir->file_class = intern->file_class;
1521 		subdir->oth = intern->oth;
1522 	}
1523 }
1524 /* }}} */
1525 
1526 /* {{{ proto void RecursiveDirectoryIterator::getSubPath()
1527    Get sub path */
SPL_METHOD(RecursiveDirectoryIterator,getSubPath)1528 SPL_METHOD(RecursiveDirectoryIterator, getSubPath)
1529 {
1530 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1531 
1532 	if (zend_parse_parameters_none() == FAILURE) {
1533 		return;
1534 	}
1535 
1536 	if (intern->u.dir.sub_path) {
1537 		RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len);
1538 	} else {
1539 		RETURN_EMPTY_STRING();
1540 	}
1541 }
1542 /* }}} */
1543 
1544 /* {{{ proto void RecursiveDirectoryIterator::getSubPathname()
1545    Get sub path and file name */
SPL_METHOD(RecursiveDirectoryIterator,getSubPathname)1546 SPL_METHOD(RecursiveDirectoryIterator, getSubPathname)
1547 {
1548 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1549 	char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
1550 
1551 	if (zend_parse_parameters_none() == FAILURE) {
1552 		return;
1553 	}
1554 
1555 	if (intern->u.dir.sub_path) {
1556 		RETURN_NEW_STR(strpprintf(0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name));
1557 	} else {
1558 		RETURN_STRING(intern->u.dir.entry.d_name);
1559 	}
1560 }
1561 /* }}} */
1562 
1563 /* {{{ proto int RecursiveDirectoryIterator::__construct(string path [, int flags])
1564  Cronstructs a new dir iterator from a path. */
SPL_METHOD(RecursiveDirectoryIterator,__construct)1565 SPL_METHOD(RecursiveDirectoryIterator, __construct)
1566 {
1567 	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS);
1568 }
1569 /* }}} */
1570 
1571 #ifdef HAVE_GLOB
1572 /* {{{ proto int GlobIterator::__construct(string path [, int flags])
1573  Cronstructs a new dir iterator from a glob expression (no glob:// needed). */
SPL_METHOD(GlobIterator,__construct)1574 SPL_METHOD(GlobIterator, __construct)
1575 {
1576 	spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS|DIT_CTOR_GLOB);
1577 }
1578 /* }}} */
1579 
1580 /* {{{ proto int GlobIterator::cont()
1581    Return the number of directories and files found by globbing */
SPL_METHOD(GlobIterator,count)1582 SPL_METHOD(GlobIterator, count)
1583 {
1584 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
1585 
1586 	if (zend_parse_parameters_none() == FAILURE) {
1587 		return;
1588 	}
1589 
1590 	if (intern->u.dir.dirp && php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
1591 		RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL));
1592 	} else {
1593 		/* should not happen */
1594 		php_error_docref(NULL, E_ERROR, "GlobIterator lost glob state");
1595 	}
1596 }
1597 /* }}} */
1598 #endif /* HAVE_GLOB */
1599 
1600 /* {{{ forward declarations to the iterator handlers */
1601 static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter);
1602 static int spl_filesystem_dir_it_valid(zend_object_iterator *iter);
1603 static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter);
1604 static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key);
1605 static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter);
1606 static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter);
1607 
1608 /* iterator handler table */
1609 zend_object_iterator_funcs spl_filesystem_dir_it_funcs = {
1610 	spl_filesystem_dir_it_dtor,
1611 	spl_filesystem_dir_it_valid,
1612 	spl_filesystem_dir_it_current_data,
1613 	spl_filesystem_dir_it_current_key,
1614 	spl_filesystem_dir_it_move_forward,
1615 	spl_filesystem_dir_it_rewind,
1616 	NULL
1617 };
1618 /* }}} */
1619 
1620 /* {{{ spl_ce_dir_get_iterator */
spl_filesystem_dir_get_iterator(zend_class_entry * ce,zval * object,int by_ref)1621 zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
1622 {
1623 	spl_filesystem_iterator *iterator;
1624 	spl_filesystem_object *dir_object;
1625 
1626 	if (by_ref) {
1627 		zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
1628 	}
1629 	dir_object = Z_SPLFILESYSTEM_P(object);
1630 	iterator = spl_filesystem_object_to_iterator(dir_object);
1631 	ZVAL_COPY(&iterator->intern.data, object);
1632 	iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
1633 	/* ->current must be initialized; rewind doesn't set it and valid
1634 	 * doesn't check whether it's set */
1635 	iterator->current = *object;
1636 
1637 	return &iterator->intern;
1638 }
1639 /* }}} */
1640 
1641 /* {{{ spl_filesystem_dir_it_dtor */
spl_filesystem_dir_it_dtor(zend_object_iterator * iter)1642 static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter)
1643 {
1644 	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
1645 
1646 	if (!Z_ISUNDEF(iterator->intern.data)) {
1647 		zval *object = &iterator->intern.data;
1648 		zval_ptr_dtor(object);
1649 	}
1650 	/* Otherwise we were called from the owning object free storage handler as
1651 	 * it sets iterator->intern.data to IS_UNDEF.
1652 	 * We don't even need to destroy iterator->current as we didn't add a
1653 	 * reference to it in move_forward or get_iterator */
1654 }
1655 /* }}} */
1656 
1657 /* {{{ spl_filesystem_dir_it_valid */
spl_filesystem_dir_it_valid(zend_object_iterator * iter)1658 static int spl_filesystem_dir_it_valid(zend_object_iterator *iter)
1659 {
1660 	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1661 
1662 	return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
1663 }
1664 /* }}} */
1665 
1666 /* {{{ spl_filesystem_dir_it_current_data */
spl_filesystem_dir_it_current_data(zend_object_iterator * iter)1667 static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter)
1668 {
1669 	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
1670 
1671 	return &iterator->current;
1672 }
1673 /* }}} */
1674 
1675 /* {{{ spl_filesystem_dir_it_current_key */
spl_filesystem_dir_it_current_key(zend_object_iterator * iter,zval * key)1676 static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key)
1677 {
1678 	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1679 
1680 	ZVAL_LONG(key, object->u.dir.index);
1681 }
1682 /* }}} */
1683 
1684 /* {{{ spl_filesystem_dir_it_move_forward */
spl_filesystem_dir_it_move_forward(zend_object_iterator * iter)1685 static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter)
1686 {
1687 	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1688 
1689 	object->u.dir.index++;
1690 	spl_filesystem_dir_read(object);
1691 	if (object->file_name) {
1692 		efree(object->file_name);
1693 		object->file_name = NULL;
1694 	}
1695 }
1696 /* }}} */
1697 
1698 /* {{{ spl_filesystem_dir_it_rewind */
spl_filesystem_dir_it_rewind(zend_object_iterator * iter)1699 static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter)
1700 {
1701 	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1702 
1703 	object->u.dir.index = 0;
1704 	if (object->u.dir.dirp) {
1705 		php_stream_rewinddir(object->u.dir.dirp);
1706 	}
1707 	spl_filesystem_dir_read(object);
1708 }
1709 /* }}} */
1710 
1711 /* {{{ spl_filesystem_tree_it_dtor */
spl_filesystem_tree_it_dtor(zend_object_iterator * iter)1712 static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter)
1713 {
1714 	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
1715 
1716 	if (!Z_ISUNDEF(iterator->intern.data)) {
1717 		zval *object = &iterator->intern.data;
1718 		zval_ptr_dtor(object);
1719 	} else {
1720 		if (!Z_ISUNDEF(iterator->current)) {
1721 			zval_ptr_dtor(&iterator->current);
1722 			ZVAL_UNDEF(&iterator->current);
1723 		}
1724 	}
1725 }
1726 /* }}} */
1727 
1728 /* {{{ spl_filesystem_tree_it_current_data */
spl_filesystem_tree_it_current_data(zend_object_iterator * iter)1729 static zval *spl_filesystem_tree_it_current_data(zend_object_iterator *iter)
1730 {
1731 	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
1732 	spl_filesystem_object   *object   = spl_filesystem_iterator_to_object(iterator);
1733 
1734 	if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
1735 		if (Z_ISUNDEF(iterator->current)) {
1736 			spl_filesystem_object_get_file_name(object);
1737 			ZVAL_STRINGL(&iterator->current, object->file_name, object->file_name_len);
1738 		}
1739 		return &iterator->current;
1740 	} else if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
1741 		if (Z_ISUNDEF(iterator->current)) {
1742 			spl_filesystem_object_get_file_name(object);
1743 			spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, &iterator->current);
1744 		}
1745 		return &iterator->current;
1746 	} else {
1747 		return &iterator->intern.data;
1748 	}
1749 }
1750 /* }}} */
1751 
1752 /* {{{ spl_filesystem_tree_it_current_key */
spl_filesystem_tree_it_current_key(zend_object_iterator * iter,zval * key)1753 static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key)
1754 {
1755 	spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
1756 
1757 	if (SPL_FILE_DIR_KEY(object, SPL_FILE_DIR_KEY_AS_FILENAME)) {
1758 		ZVAL_STRING(key, object->u.dir.entry.d_name);
1759 	} else {
1760 		spl_filesystem_object_get_file_name(object);
1761 		ZVAL_STRINGL(key, object->file_name, object->file_name_len);
1762 	}
1763 }
1764 /* }}} */
1765 
1766 /* {{{ spl_filesystem_tree_it_move_forward */
spl_filesystem_tree_it_move_forward(zend_object_iterator * iter)1767 static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter)
1768 {
1769 	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
1770 	spl_filesystem_object   *object   = spl_filesystem_iterator_to_object(iterator);
1771 
1772 	object->u.dir.index++;
1773 	do {
1774 		spl_filesystem_dir_read(object);
1775 	} while (spl_filesystem_is_dot(object->u.dir.entry.d_name));
1776 	if (object->file_name) {
1777 		efree(object->file_name);
1778 		object->file_name = NULL;
1779 	}
1780 	if (!Z_ISUNDEF(iterator->current)) {
1781 		zval_ptr_dtor(&iterator->current);
1782 		ZVAL_UNDEF(&iterator->current);
1783 	}
1784 }
1785 /* }}} */
1786 
1787 /* {{{ spl_filesystem_tree_it_rewind */
spl_filesystem_tree_it_rewind(zend_object_iterator * iter)1788 static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter)
1789 {
1790 	spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
1791 	spl_filesystem_object   *object   = spl_filesystem_iterator_to_object(iterator);
1792 
1793 	object->u.dir.index = 0;
1794 	if (object->u.dir.dirp) {
1795 		php_stream_rewinddir(object->u.dir.dirp);
1796 	}
1797 	do {
1798 		spl_filesystem_dir_read(object);
1799 	} while (spl_filesystem_is_dot(object->u.dir.entry.d_name));
1800 	if (!Z_ISUNDEF(iterator->current)) {
1801 		zval_ptr_dtor(&iterator->current);
1802 		ZVAL_UNDEF(&iterator->current);
1803 	}
1804 }
1805 /* }}} */
1806 
1807 /* {{{ iterator handler table */
1808 zend_object_iterator_funcs spl_filesystem_tree_it_funcs = {
1809 	spl_filesystem_tree_it_dtor,
1810 	spl_filesystem_dir_it_valid,
1811 	spl_filesystem_tree_it_current_data,
1812 	spl_filesystem_tree_it_current_key,
1813 	spl_filesystem_tree_it_move_forward,
1814 	spl_filesystem_tree_it_rewind,
1815 	NULL
1816 };
1817 /* }}} */
1818 
1819 /* {{{ spl_ce_dir_get_iterator */
spl_filesystem_tree_get_iterator(zend_class_entry * ce,zval * object,int by_ref)1820 zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
1821 {
1822 	spl_filesystem_iterator *iterator;
1823 	spl_filesystem_object *dir_object;
1824 
1825 	if (by_ref) {
1826 		zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
1827 	}
1828 	dir_object = Z_SPLFILESYSTEM_P(object);
1829 	iterator = spl_filesystem_object_to_iterator(dir_object);
1830 
1831 	ZVAL_COPY(&iterator->intern.data, object);
1832 	iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
1833 
1834 	return &iterator->intern;
1835 }
1836 /* }}} */
1837 
1838 /* {{{ spl_filesystem_object_cast */
spl_filesystem_object_cast(zval * readobj,zval * writeobj,int type)1839 static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type)
1840 {
1841 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(readobj);
1842 
1843 	if (type == IS_STRING) {
1844 		if (Z_OBJCE_P(readobj)->__tostring) {
1845 			return std_object_handlers.cast_object(readobj, writeobj, type);
1846 		}
1847 
1848 		switch (intern->type) {
1849 		case SPL_FS_INFO:
1850 		case SPL_FS_FILE:
1851 			if (readobj == writeobj) {
1852 				zval retval;
1853 				zval *retval_ptr = &retval;
1854 
1855 				ZVAL_STRINGL(retval_ptr, intern->file_name, intern->file_name_len);
1856 				zval_ptr_dtor(readobj);
1857 				ZVAL_NEW_STR(writeobj, Z_STR_P(retval_ptr));
1858 			} else {
1859 				ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len);
1860 			}
1861 			return SUCCESS;
1862 		case SPL_FS_DIR:
1863 			if (readobj == writeobj) {
1864 				zval retval;
1865 				zval *retval_ptr = &retval;
1866 
1867 				ZVAL_STRING(retval_ptr, intern->u.dir.entry.d_name);
1868 				zval_ptr_dtor(readobj);
1869 				ZVAL_NEW_STR(writeobj, Z_STR_P(retval_ptr));
1870 			} else {
1871 				ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
1872 			}
1873 			return SUCCESS;
1874 		}
1875 	} else if (type == _IS_BOOL) {
1876 		ZVAL_TRUE(writeobj);
1877 		return SUCCESS;
1878 	}
1879 	if (readobj == writeobj) {
1880 		zval_ptr_dtor(readobj);
1881 	}
1882 	ZVAL_NULL(writeobj);
1883 	return FAILURE;
1884 }
1885 /* }}} */
1886 
1887 /* {{{ declare method parameters */
1888 /* supply a name and default to call by parameter */
1889 ZEND_BEGIN_ARG_INFO(arginfo_info___construct, 0)
1890 	ZEND_ARG_INFO(0, file_name)
1891 ZEND_END_ARG_INFO()
1892 
1893 ZEND_BEGIN_ARG_INFO_EX(arginfo_info_openFile, 0, 0, 0)
1894 	ZEND_ARG_INFO(0, open_mode)
1895 	ZEND_ARG_INFO(0, use_include_path)
1896 	ZEND_ARG_INFO(0, context)
1897 ZEND_END_ARG_INFO()
1898 
1899 ZEND_BEGIN_ARG_INFO_EX(arginfo_info_optinalFileClass, 0, 0, 0)
1900 	ZEND_ARG_INFO(0, class_name)
1901 ZEND_END_ARG_INFO()
1902 
1903 ZEND_BEGIN_ARG_INFO_EX(arginfo_optinalSuffix, 0, 0, 0)
1904 	ZEND_ARG_INFO(0, suffix)
1905 ZEND_END_ARG_INFO()
1906 
1907 ZEND_BEGIN_ARG_INFO(arginfo_splfileinfo_void, 0)
1908 ZEND_END_ARG_INFO()
1909 
1910 /* the method table */
1911 /* each method can have its own parameters and visibility */
1912 static const zend_function_entry spl_SplFileInfo_functions[] = {
1913 	SPL_ME(SplFileInfo,       __construct,   arginfo_info___construct, ZEND_ACC_PUBLIC)
1914 	SPL_ME(SplFileInfo,       getPath,       arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1915 	SPL_ME(SplFileInfo,       getFilename,   arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1916 	SPL_ME(SplFileInfo,       getExtension,  arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1917 	SPL_ME(SplFileInfo,       getBasename,   arginfo_optinalSuffix, ZEND_ACC_PUBLIC)
1918 	SPL_ME(SplFileInfo,       getPathname,   arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1919 	SPL_ME(SplFileInfo,       getPerms,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1920 	SPL_ME(SplFileInfo,       getInode,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1921 	SPL_ME(SplFileInfo,       getSize,       arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1922 	SPL_ME(SplFileInfo,       getOwner,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1923 	SPL_ME(SplFileInfo,       getGroup,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1924 	SPL_ME(SplFileInfo,       getATime,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1925 	SPL_ME(SplFileInfo,       getMTime,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1926 	SPL_ME(SplFileInfo,       getCTime,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1927 	SPL_ME(SplFileInfo,       getType,       arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1928 	SPL_ME(SplFileInfo,       isWritable,    arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1929 	SPL_ME(SplFileInfo,       isReadable,    arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1930 	SPL_ME(SplFileInfo,       isExecutable,  arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1931 	SPL_ME(SplFileInfo,       isFile,        arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1932 	SPL_ME(SplFileInfo,       isDir,         arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1933 	SPL_ME(SplFileInfo,       isLink,        arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1934 	SPL_ME(SplFileInfo,       getLinkTarget, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1935 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
1936 	SPL_ME(SplFileInfo,       getRealPath,   arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1937 #endif
1938 	SPL_ME(SplFileInfo,       getFileInfo,   arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
1939 	SPL_ME(SplFileInfo,       getPathInfo,   arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
1940 	SPL_ME(SplFileInfo,       openFile,      arginfo_info_openFile,         ZEND_ACC_PUBLIC)
1941 	SPL_ME(SplFileInfo,       setFileClass,  arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
1942 	SPL_ME(SplFileInfo,       setInfoClass,  arginfo_info_optinalFileClass, ZEND_ACC_PUBLIC)
1943 	SPL_ME(SplFileInfo,       _bad_state_ex, NULL,							ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
1944 	SPL_MA(SplFileInfo,       __toString, SplFileInfo, getPathname, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1945 	PHP_FE_END
1946 };
1947 
1948 ZEND_BEGIN_ARG_INFO(arginfo_dir___construct, 0)
1949 	ZEND_ARG_INFO(0, path)
1950 ZEND_END_ARG_INFO()
1951 
1952 ZEND_BEGIN_ARG_INFO(arginfo_dir_it_seek, 0)
1953 	ZEND_ARG_INFO(0, position)
1954 ZEND_END_ARG_INFO();
1955 
1956 /* the method table */
1957 /* each method can have its own parameters and visibility */
1958 static const zend_function_entry spl_DirectoryIterator_functions[] = {
1959 	SPL_ME(DirectoryIterator, __construct,   arginfo_dir___construct, ZEND_ACC_PUBLIC)
1960 	SPL_ME(DirectoryIterator, getFilename,   arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1961 	SPL_ME(DirectoryIterator, getExtension,  arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1962 	SPL_ME(DirectoryIterator, getBasename,   arginfo_optinalSuffix, ZEND_ACC_PUBLIC)
1963 	SPL_ME(DirectoryIterator, isDot,         arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1964 	SPL_ME(DirectoryIterator, rewind,        arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1965 	SPL_ME(DirectoryIterator, valid,         arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1966 	SPL_ME(DirectoryIterator, key,           arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1967 	SPL_ME(DirectoryIterator, current,       arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1968 	SPL_ME(DirectoryIterator, next,          arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1969 	SPL_ME(DirectoryIterator, seek,          arginfo_dir_it_seek, ZEND_ACC_PUBLIC)
1970 	SPL_MA(DirectoryIterator, __toString, DirectoryIterator, getFilename, arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1971 	PHP_FE_END
1972 };
1973 
1974 ZEND_BEGIN_ARG_INFO_EX(arginfo_r_dir___construct, 0, 0, 1)
1975 	ZEND_ARG_INFO(0, path)
1976 	ZEND_ARG_INFO(0, flags)
1977 ZEND_END_ARG_INFO()
1978 
1979 ZEND_BEGIN_ARG_INFO_EX(arginfo_r_dir_hasChildren, 0, 0, 0)
1980 	ZEND_ARG_INFO(0, allow_links)
1981 ZEND_END_ARG_INFO()
1982 
1983 ZEND_BEGIN_ARG_INFO_EX(arginfo_r_dir_setFlags, 0, 0, 0)
1984 	ZEND_ARG_INFO(0, flags)
1985 ZEND_END_ARG_INFO()
1986 
1987 static const zend_function_entry spl_FilesystemIterator_functions[] = {
1988 	SPL_ME(FilesystemIterator, __construct,   arginfo_r_dir___construct, ZEND_ACC_PUBLIC)
1989 	SPL_ME(FilesystemIterator, rewind,        arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1990 	SPL_ME(DirectoryIterator,  next,          arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1991 	SPL_ME(FilesystemIterator, key,           arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1992 	SPL_ME(FilesystemIterator, current,       arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1993 	SPL_ME(FilesystemIterator, getFlags,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
1994 	SPL_ME(FilesystemIterator, setFlags,      arginfo_r_dir_setFlags, ZEND_ACC_PUBLIC)
1995 	PHP_FE_END
1996 };
1997 
1998 static const zend_function_entry spl_RecursiveDirectoryIterator_functions[] = {
1999 	SPL_ME(RecursiveDirectoryIterator, __construct,   arginfo_r_dir___construct, ZEND_ACC_PUBLIC)
2000 	SPL_ME(RecursiveDirectoryIterator, hasChildren,   arginfo_r_dir_hasChildren, ZEND_ACC_PUBLIC)
2001 	SPL_ME(RecursiveDirectoryIterator, getChildren,   arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
2002 	SPL_ME(RecursiveDirectoryIterator, getSubPath,    arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
2003 	SPL_ME(RecursiveDirectoryIterator, getSubPathname,arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
2004 	PHP_FE_END
2005 };
2006 
2007 #ifdef HAVE_GLOB
2008 static const zend_function_entry spl_GlobIterator_functions[] = {
2009 	SPL_ME(GlobIterator, __construct,   arginfo_r_dir___construct, ZEND_ACC_PUBLIC)
2010 	SPL_ME(GlobIterator, count,         arginfo_splfileinfo_void,  ZEND_ACC_PUBLIC)
2011 	PHP_FE_END
2012 };
2013 #endif
2014 /* }}} */
2015 
spl_filesystem_file_read(spl_filesystem_object * intern,int silent)2016 static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /* {{{ */
2017 {
2018 	char *buf;
2019 	size_t line_len = 0;
2020 	zend_long line_add = (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) ? 1 : 0;
2021 
2022 	spl_filesystem_file_free_line(intern);
2023 
2024 	if (php_stream_eof(intern->u.file.stream)) {
2025 		if (!silent) {
2026 			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
2027 		}
2028 		return FAILURE;
2029 	}
2030 
2031 	if (intern->u.file.max_line_len > 0) {
2032 		buf = safe_emalloc((intern->u.file.max_line_len + 1), sizeof(char), 0);
2033 		if (php_stream_get_line(intern->u.file.stream, buf, intern->u.file.max_line_len + 1, &line_len) == NULL) {
2034 			efree(buf);
2035 			buf = NULL;
2036 		} else {
2037 			buf[line_len] = '\0';
2038 		}
2039 	} else {
2040 		buf = php_stream_get_line(intern->u.file.stream, NULL, 0, &line_len);
2041 	}
2042 
2043 	if (!buf) {
2044 		intern->u.file.current_line = estrdup("");
2045 		intern->u.file.current_line_len = 0;
2046 	} else {
2047 		if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
2048 			line_len = strcspn(buf, "\r\n");
2049 			buf[line_len] = '\0';
2050 		}
2051 
2052 		intern->u.file.current_line = buf;
2053 		intern->u.file.current_line_len = line_len;
2054 	}
2055 	intern->u.file.current_line_num += line_add;
2056 
2057 	return SUCCESS;
2058 } /* }}} */
2059 
spl_filesystem_file_call(spl_filesystem_object * intern,zend_function * func_ptr,int pass_num_args,zval * return_value,zval * arg2)2060 static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function *func_ptr, int pass_num_args, zval *return_value, zval *arg2) /* {{{ */
2061 {
2062 	zend_fcall_info fci;
2063 	zend_fcall_info_cache fcic;
2064 	zval *zresource_ptr = &intern->u.file.zresource, retval;
2065 	int result;
2066 	int num_args = pass_num_args + (arg2 ? 2 : 1);
2067 
2068 	zval *params = (zval*)safe_emalloc(num_args, sizeof(zval), 0);
2069 
2070 	params[0] = *zresource_ptr;
2071 
2072 	if (arg2) {
2073 		params[1] = *arg2;
2074 	}
2075 
2076 	if (zend_get_parameters_array_ex(pass_num_args, params + (arg2 ? 2 : 1)) != SUCCESS) {
2077 		efree(params);
2078 		WRONG_PARAM_COUNT_WITH_RETVAL(FAILURE);
2079 	}
2080 
2081 	ZVAL_UNDEF(&retval);
2082 
2083 	fci.size = sizeof(fci);
2084 	fci.object = NULL;
2085 	fci.retval = &retval;
2086 	fci.param_count = num_args;
2087 	fci.params = params;
2088 	fci.no_separation = 1;
2089 	ZVAL_STR(&fci.function_name, func_ptr->common.function_name);
2090 
2091 	fcic.initialized = 1;
2092 	fcic.function_handler = func_ptr;
2093 	fcic.calling_scope = NULL;
2094 	fcic.called_scope = NULL;
2095 	fcic.object = NULL;
2096 
2097 	result = zend_call_function(&fci, &fcic);
2098 
2099 	if (result == FAILURE || Z_ISUNDEF(retval)) {
2100 		RETVAL_FALSE;
2101 	} else {
2102 		ZVAL_ZVAL(return_value, &retval, 0, 0);
2103 	}
2104 
2105 	efree(params);
2106 	return result;
2107 } /* }}} */
2108 
2109 #define FileFunctionCall(func_name, pass_num_args, arg2) /* {{{ */ \
2110 { \
2111 	zend_function *func_ptr; \
2112 	func_ptr = (zend_function *)zend_hash_str_find_ptr(EG(function_table), #func_name, sizeof(#func_name) - 1); \
2113 	if (func_ptr == NULL) { \
2114 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Internal error, function '%s' not found. Please report", #func_name); \
2115 		return; \
2116 	} \
2117 	spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2); \
2118 } /* }}} */
2119 
spl_filesystem_file_read_csv(spl_filesystem_object * intern,char delimiter,char enclosure,char escape,zval * return_value)2120 static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, char escape, zval *return_value) /* {{{ */
2121 {
2122 	int ret = SUCCESS;
2123 	zval *value;
2124 
2125 	do {
2126 		ret = spl_filesystem_file_read(intern, 1);
2127 	} while (ret == SUCCESS && !intern->u.file.current_line_len && SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY));
2128 
2129 	if (ret == SUCCESS) {
2130 		size_t buf_len = intern->u.file.current_line_len;
2131 		char *buf = estrndup(intern->u.file.current_line, buf_len);
2132 
2133 		if (!Z_ISUNDEF(intern->u.file.current_zval)) {
2134 			zval_ptr_dtor(&intern->u.file.current_zval);
2135 			ZVAL_UNDEF(&intern->u.file.current_zval);
2136 		}
2137 
2138 		php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf, &intern->u.file.current_zval);
2139 		if (return_value) {
2140 			zval_ptr_dtor(return_value);
2141 			value = &intern->u.file.current_zval;
2142 			ZVAL_DEREF(value);
2143 			ZVAL_COPY(return_value, value);
2144 		}
2145 	}
2146 	return ret;
2147 }
2148 /* }}} */
2149 
spl_filesystem_file_read_line_ex(zval * this_ptr,spl_filesystem_object * intern,int silent)2150 static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */
2151 {
2152 	zval retval;
2153 
2154 	/* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */
2155 	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
2156 		if (php_stream_eof(intern->u.file.stream)) {
2157 			if (!silent) {
2158 				zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
2159 			}
2160 			return FAILURE;
2161 		}
2162 		if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)) {
2163 			return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL);
2164 		} else {
2165 			zend_execute_data *execute_data = EG(current_execute_data);
2166 			zend_call_method_with_0_params(this_ptr, Z_OBJCE(EX(This)), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
2167 		}
2168 		if (!Z_ISUNDEF(retval)) {
2169 			if (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) {
2170 				intern->u.file.current_line_num++;
2171 			}
2172 			spl_filesystem_file_free_line(intern);
2173 			if (Z_TYPE(retval) == IS_STRING) {
2174 				intern->u.file.current_line = estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
2175 				intern->u.file.current_line_len = Z_STRLEN(retval);
2176 			} else {
2177 				zval *value = &retval;
2178 
2179 				ZVAL_DEREF(value);
2180 				ZVAL_COPY(&intern->u.file.current_zval, value);
2181 			}
2182 			zval_ptr_dtor(&retval);
2183 			return SUCCESS;
2184 		} else {
2185 			return FAILURE;
2186 		}
2187 	} else {
2188 		return spl_filesystem_file_read(intern, silent);
2189 	}
2190 } /* }}} */
2191 
spl_filesystem_file_is_empty_line(spl_filesystem_object * intern)2192 static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern) /* {{{ */
2193 {
2194 	if (intern->u.file.current_line) {
2195 		return intern->u.file.current_line_len == 0;
2196 	} else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
2197 		switch(Z_TYPE(intern->u.file.current_zval)) {
2198 			case IS_STRING:
2199 				return Z_STRLEN(intern->u.file.current_zval) == 0;
2200 			case IS_ARRAY:
2201 				if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)
2202 						&& zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 1) {
2203 					uint idx = 0;
2204 					zval *first;
2205 
2206 					while (Z_ISUNDEF(Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val)) {
2207 						idx++;
2208 					}
2209 					first = &Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val;
2210 					return Z_TYPE_P(first) == IS_STRING && Z_STRLEN_P(first) == 0;
2211 				}
2212 				return zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 0;
2213 			case IS_NULL:
2214 				return 1;
2215 			default:
2216 				return 0;
2217 		}
2218 	} else {
2219 		return 1;
2220 	}
2221 }
2222 /* }}} */
2223 
spl_filesystem_file_read_line(zval * this_ptr,spl_filesystem_object * intern,int silent)2224 static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */
2225 {
2226 	int ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
2227 
2228 	while (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && spl_filesystem_file_is_empty_line(intern)) {
2229 		spl_filesystem_file_free_line(intern);
2230 		ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
2231 	}
2232 
2233 	return ret;
2234 }
2235 /* }}} */
2236 
spl_filesystem_file_rewind(zval * this_ptr,spl_filesystem_object * intern)2237 static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */
2238 {
2239 	if(!intern->u.file.stream) {
2240 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2241 		return;
2242 	}
2243 	if (-1 == php_stream_rewind(intern->u.file.stream)) {
2244 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", intern->file_name);
2245 	} else {
2246 		spl_filesystem_file_free_line(intern);
2247 		intern->u.file.current_line_num = 0;
2248 	}
2249 	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2250 		spl_filesystem_file_read_line(this_ptr, intern, 1);
2251 	}
2252 } /* }}} */
2253 
2254 /* {{{ proto void SplFileObject::__construct(string filename [, string mode = 'r' [, bool use_include_path  [, resource context]]]])
2255    Construct a new file object */
SPL_METHOD(SplFileObject,__construct)2256 SPL_METHOD(SplFileObject, __construct)
2257 {
2258 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2259 	zend_bool use_include_path = 0;
2260 	char *p1, *p2;
2261 	char *tmp_path;
2262 	size_t   tmp_path_len;
2263 	zend_error_handling error_handling;
2264 
2265 	intern->u.file.open_mode = NULL;
2266 	intern->u.file.open_mode_len = 0;
2267 
2268 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "p|sbr!",
2269 			&intern->file_name, &intern->file_name_len,
2270 			&intern->u.file.open_mode, &intern->u.file.open_mode_len,
2271 			&use_include_path, &intern->u.file.zcontext) == FAILURE) {
2272 		intern->u.file.open_mode = NULL;
2273 		intern->file_name = NULL;
2274 		return;
2275 	}
2276 
2277 	if (intern->u.file.open_mode == NULL) {
2278 		intern->u.file.open_mode = "r";
2279 		intern->u.file.open_mode_len = 1;
2280 	}
2281 
2282 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
2283 
2284 	if (spl_filesystem_file_open(intern, use_include_path, 0) == SUCCESS) {
2285 		tmp_path_len = strlen(intern->u.file.stream->orig_path);
2286 
2287 		if (tmp_path_len > 1 && IS_SLASH_AT(intern->u.file.stream->orig_path, tmp_path_len-1)) {
2288 			tmp_path_len--;
2289 		}
2290 
2291 		tmp_path = estrndup(intern->u.file.stream->orig_path, tmp_path_len);
2292 
2293 		p1 = strrchr(tmp_path, '/');
2294 #if defined(PHP_WIN32) || defined(NETWARE)
2295 		p2 = strrchr(tmp_path, '\\');
2296 #else
2297 		p2 = 0;
2298 #endif
2299 		if (p1 || p2) {
2300 			intern->_path_len = ((p1 > p2 ? p1 : p2) - tmp_path);
2301 		} else {
2302 			intern->_path_len = 0;
2303 		}
2304 
2305 		efree(tmp_path);
2306 
2307 		intern->_path = estrndup(intern->u.file.stream->orig_path, intern->_path_len);
2308 	}
2309 
2310 	zend_restore_error_handling(&error_handling);
2311 
2312 } /* }}} */
2313 
2314 /* {{{ proto void SplTempFileObject::__construct([int max_memory])
2315    Construct a new temp file object */
SPL_METHOD(SplTempFileObject,__construct)2316 SPL_METHOD(SplTempFileObject, __construct)
2317 {
2318 	zend_long max_memory = PHP_STREAM_MAX_MEM;
2319 	char tmp_fname[48];
2320 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2321 	zend_error_handling error_handling;
2322 
2323 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|l", &max_memory) == FAILURE) {
2324 		return;
2325 	}
2326 
2327 	if (max_memory < 0) {
2328 		intern->file_name = "php://memory";
2329 		intern->file_name_len = 12;
2330 	} else if (ZEND_NUM_ARGS()) {
2331 		intern->file_name_len = slprintf(tmp_fname, sizeof(tmp_fname), "php://temp/maxmemory:" ZEND_LONG_FMT, max_memory);
2332 		intern->file_name = tmp_fname;
2333 	} else {
2334 		intern->file_name = "php://temp";
2335 		intern->file_name_len = 10;
2336 	}
2337 	intern->u.file.open_mode = "wb";
2338 	intern->u.file.open_mode_len = 1;
2339 
2340 	zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
2341 	if (spl_filesystem_file_open(intern, 0, 0) == SUCCESS) {
2342 		intern->_path_len = 0;
2343 		intern->_path = estrndup("", 0);
2344 	}
2345 	zend_restore_error_handling(&error_handling);
2346 } /* }}} */
2347 
2348 /* {{{ proto void SplFileObject::rewind()
2349    Rewind the file and read the first line */
SPL_METHOD(SplFileObject,rewind)2350 SPL_METHOD(SplFileObject, rewind)
2351 {
2352 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2353 
2354 	if (zend_parse_parameters_none() == FAILURE) {
2355 		return;
2356 	}
2357 
2358 	spl_filesystem_file_rewind(getThis(), intern);
2359 } /* }}} */
2360 
2361 /* {{{ proto void SplFileObject::eof()
2362    Return whether end of file is reached */
SPL_METHOD(SplFileObject,eof)2363 SPL_METHOD(SplFileObject, eof)
2364 {
2365 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2366 
2367 	if (zend_parse_parameters_none() == FAILURE) {
2368 		return;
2369 	}
2370 
2371 	if(!intern->u.file.stream) {
2372 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2373 		return;
2374 	}
2375 
2376 	RETURN_BOOL(php_stream_eof(intern->u.file.stream));
2377 } /* }}} */
2378 
2379 /* {{{ proto void SplFileObject::valid()
2380    Return !eof() */
SPL_METHOD(SplFileObject,valid)2381 SPL_METHOD(SplFileObject, valid)
2382 {
2383 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2384 
2385 	if (zend_parse_parameters_none() == FAILURE) {
2386 		return;
2387 	}
2388 
2389 	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2390 		RETURN_BOOL(intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval));
2391 	} else {
2392 		if(!intern->u.file.stream) {
2393 			RETURN_FALSE;
2394 		}
2395 		RETVAL_BOOL(!php_stream_eof(intern->u.file.stream));
2396 	}
2397 } /* }}} */
2398 
2399 /* {{{ proto string SplFileObject::fgets()
2400    Rturn next line from file */
SPL_METHOD(SplFileObject,fgets)2401 SPL_METHOD(SplFileObject, fgets)
2402 {
2403 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2404 
2405 	if (zend_parse_parameters_none() == FAILURE) {
2406 		return;
2407 	}
2408 
2409 	if(!intern->u.file.stream) {
2410 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2411 		return;
2412 	}
2413 
2414 	if (spl_filesystem_file_read(intern, 0) == FAILURE) {
2415 		RETURN_FALSE;
2416 	}
2417 	RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
2418 } /* }}} */
2419 
2420 /* {{{ proto string SplFileObject::current()
2421    Return current line from file */
SPL_METHOD(SplFileObject,current)2422 SPL_METHOD(SplFileObject, current)
2423 {
2424 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2425 
2426 	if (zend_parse_parameters_none() == FAILURE) {
2427 		return;
2428 	}
2429 
2430 	if(!intern->u.file.stream) {
2431 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2432 		return;
2433 	}
2434 
2435 	if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
2436 		spl_filesystem_file_read_line(getThis(), intern, 1);
2437 	}
2438 	if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) {
2439 		RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
2440 	} else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
2441 		zval *value = &intern->u.file.current_zval;
2442 
2443 		ZVAL_DEREF(value);
2444 		ZVAL_COPY(return_value, value);
2445 		return;
2446 	}
2447 	RETURN_FALSE;
2448 } /* }}} */
2449 
2450 /* {{{ proto int SplFileObject::key()
2451    Return line number */
SPL_METHOD(SplFileObject,key)2452 SPL_METHOD(SplFileObject, key)
2453 {
2454 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2455 
2456 	if (zend_parse_parameters_none() == FAILURE) {
2457 		return;
2458 	}
2459 
2460 /*	Do not read the next line to support correct counting with fgetc()
2461 	if (!intern->current_line) {
2462 		spl_filesystem_file_read_line(getThis(), intern, 1);
2463 	} */
2464 	RETURN_LONG(intern->u.file.current_line_num);
2465 } /* }}} */
2466 
2467 /* {{{ proto void SplFileObject::next()
2468    Read next line */
SPL_METHOD(SplFileObject,next)2469 SPL_METHOD(SplFileObject, next)
2470 {
2471 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2472 
2473 	if (zend_parse_parameters_none() == FAILURE) {
2474 		return;
2475 	}
2476 
2477 	spl_filesystem_file_free_line(intern);
2478 	if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2479 		spl_filesystem_file_read_line(getThis(), intern, 1);
2480 	}
2481 	intern->u.file.current_line_num++;
2482 } /* }}} */
2483 
2484 /* {{{ proto void SplFileObject::setFlags(int flags)
2485    Set file handling flags */
SPL_METHOD(SplFileObject,setFlags)2486 SPL_METHOD(SplFileObject, setFlags)
2487 {
2488 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2489 
2490 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &intern->flags) == FAILURE) {
2491 		return;
2492 	}
2493 } /* }}} */
2494 
2495 /* {{{ proto int SplFileObject::getFlags()
2496    Get file handling flags */
SPL_METHOD(SplFileObject,getFlags)2497 SPL_METHOD(SplFileObject, getFlags)
2498 {
2499 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2500 
2501 	if (zend_parse_parameters_none() == FAILURE) {
2502 		return;
2503 	}
2504 
2505 	RETURN_LONG(intern->flags & SPL_FILE_OBJECT_MASK);
2506 } /* }}} */
2507 
2508 /* {{{ proto void SplFileObject::setMaxLineLen(int max_len)
2509    Set maximum line length */
SPL_METHOD(SplFileObject,setMaxLineLen)2510 SPL_METHOD(SplFileObject, setMaxLineLen)
2511 {
2512 	zend_long max_len;
2513 
2514 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2515 
2516 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &max_len) == FAILURE) {
2517 		return;
2518 	}
2519 
2520 	if (max_len < 0) {
2521 		zend_throw_exception_ex(spl_ce_DomainException, 0, "Maximum line length must be greater than or equal zero");
2522 		return;
2523 	}
2524 
2525 	intern->u.file.max_line_len = max_len;
2526 } /* }}} */
2527 
2528 /* {{{ proto int SplFileObject::getMaxLineLen()
2529    Get maximum line length */
SPL_METHOD(SplFileObject,getMaxLineLen)2530 SPL_METHOD(SplFileObject, getMaxLineLen)
2531 {
2532 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2533 
2534 	if (zend_parse_parameters_none() == FAILURE) {
2535 		return;
2536 	}
2537 
2538 	RETURN_LONG((zend_long)intern->u.file.max_line_len);
2539 } /* }}} */
2540 
2541 /* {{{ proto bool SplFileObject::hasChildren()
2542    Return false */
SPL_METHOD(SplFileObject,hasChildren)2543 SPL_METHOD(SplFileObject, hasChildren)
2544 {
2545 	if (zend_parse_parameters_none() == FAILURE) {
2546 		return;
2547 	}
2548 
2549 	RETURN_FALSE;
2550 } /* }}} */
2551 
2552 /* {{{ proto bool SplFileObject::getChildren()
2553    Read NULL */
SPL_METHOD(SplFileObject,getChildren)2554 SPL_METHOD(SplFileObject, getChildren)
2555 {
2556 	if (zend_parse_parameters_none() == FAILURE) {
2557 		return;
2558 	}
2559 	/* return NULL */
2560 } /* }}} */
2561 
2562 /* {{{ FileFunction */
2563 #define FileFunction(func_name) \
2564 SPL_METHOD(SplFileObject, func_name) \
2565 { \
2566 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis()); \
2567 	FileFunctionCall(func_name, ZEND_NUM_ARGS(), NULL); \
2568 }
2569 /* }}} */
2570 
2571 /* {{{ proto array SplFileObject::fgetcsv([string delimiter [, string enclosure [, escape = '\\']]])
2572    Return current line as csv */
SPL_METHOD(SplFileObject,fgetcsv)2573 SPL_METHOD(SplFileObject, fgetcsv)
2574 {
2575 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2576 	char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape;
2577 	char *delim = NULL, *enclo = NULL, *esc = NULL;
2578 	size_t d_len = 0, e_len = 0, esc_len = 0;
2579 
2580 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
2581 
2582 		if(!intern->u.file.stream) {
2583 			zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2584 			return;
2585 		}
2586 
2587 		switch(ZEND_NUM_ARGS())
2588 		{
2589 		case 3:
2590 			if (esc_len != 1) {
2591 				php_error_docref(NULL, E_WARNING, "escape must be a character");
2592 				RETURN_FALSE;
2593 			}
2594 			escape = esc[0];
2595 			/* no break */
2596 		case 2:
2597 			if (e_len != 1) {
2598 				php_error_docref(NULL, E_WARNING, "enclosure must be a character");
2599 				RETURN_FALSE;
2600 			}
2601 			enclosure = enclo[0];
2602 			/* no break */
2603 		case 1:
2604 			if (d_len != 1) {
2605 				php_error_docref(NULL, E_WARNING, "delimiter must be a character");
2606 				RETURN_FALSE;
2607 			}
2608 			delimiter = delim[0];
2609 			/* no break */
2610 		case 0:
2611 			break;
2612 		}
2613 		spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value);
2614 	}
2615 }
2616 /* }}} */
2617 
2618 /* {{{ proto int SplFileObject::fputcsv(array fields, [string delimiter [, string enclosure [, string escape]]])
2619    Output a field array as a CSV line */
SPL_METHOD(SplFileObject,fputcsv)2620 SPL_METHOD(SplFileObject, fputcsv)
2621 {
2622 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2623 	char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape;
2624 	char *delim = NULL, *enclo = NULL, *esc = NULL;
2625 	size_t d_len = 0, e_len = 0, esc_len = 0;
2626 	zend_long ret;
2627 	zval *fields = NULL;
2628 
2629 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|sss", &fields, &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
2630 		switch(ZEND_NUM_ARGS())
2631 		{
2632 		case 4:
2633 			if (esc_len != 1) {
2634 				php_error_docref(NULL, E_WARNING, "escape must be a character");
2635 				RETURN_FALSE;
2636 			}
2637 			escape = esc[0];
2638 			/* no break */
2639 		case 3:
2640 			if (e_len != 1) {
2641 				php_error_docref(NULL, E_WARNING, "enclosure must be a character");
2642 				RETURN_FALSE;
2643 			}
2644 			enclosure = enclo[0];
2645 			/* no break */
2646 		case 2:
2647 			if (d_len != 1) {
2648 				php_error_docref(NULL, E_WARNING, "delimiter must be a character");
2649 				RETURN_FALSE;
2650 			}
2651 			delimiter = delim[0];
2652 			/* no break */
2653 		case 1:
2654 		case 0:
2655 			break;
2656 		}
2657 		ret = php_fputcsv(intern->u.file.stream, fields, delimiter, enclosure, escape);
2658 		RETURN_LONG(ret);
2659 	}
2660 }
2661 /* }}} */
2662 
2663 /* {{{ proto void SplFileObject::setCsvControl([string delimiter [, string enclosure [, string escape ]]])
2664    Set the delimiter, enclosure and escape character used in fgetcsv */
SPL_METHOD(SplFileObject,setCsvControl)2665 SPL_METHOD(SplFileObject, setCsvControl)
2666 {
2667 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2668 	char delimiter = ',', enclosure = '"', escape='\\';
2669 	char *delim = NULL, *enclo = NULL, *esc = NULL;
2670 	size_t d_len = 0, e_len = 0, esc_len = 0;
2671 
2672 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
2673 		switch(ZEND_NUM_ARGS())
2674 		{
2675 		case 3:
2676 			if (esc_len != 1) {
2677 				php_error_docref(NULL, E_WARNING, "escape must be a character");
2678 				RETURN_FALSE;
2679 			}
2680 			escape = esc[0];
2681 			/* no break */
2682 		case 2:
2683 			if (e_len != 1) {
2684 				php_error_docref(NULL, E_WARNING, "enclosure must be a character");
2685 				RETURN_FALSE;
2686 			}
2687 			enclosure = enclo[0];
2688 			/* no break */
2689 		case 1:
2690 			if (d_len != 1) {
2691 				php_error_docref(NULL, E_WARNING, "delimiter must be a character");
2692 				RETURN_FALSE;
2693 			}
2694 			delimiter = delim[0];
2695 			/* no break */
2696 		case 0:
2697 			break;
2698 		}
2699 		intern->u.file.delimiter = delimiter;
2700 		intern->u.file.enclosure = enclosure;
2701 		intern->u.file.escape    = escape;
2702 	}
2703 }
2704 /* }}} */
2705 
2706 /* {{{ proto array SplFileObject::getCsvControl()
2707    Get the delimiter, enclosure and escape character used in fgetcsv */
SPL_METHOD(SplFileObject,getCsvControl)2708 SPL_METHOD(SplFileObject, getCsvControl)
2709 {
2710 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2711 	char delimiter[2], enclosure[2], escape[2];
2712 
2713 	array_init(return_value);
2714 
2715 	delimiter[0] = intern->u.file.delimiter;
2716 	delimiter[1] = '\0';
2717 	enclosure[0] = intern->u.file.enclosure;
2718 	enclosure[1] = '\0';
2719 	escape[0] = intern->u.file.escape;
2720 	escape[1] = '\0';
2721 
2722 	add_next_index_string(return_value, delimiter);
2723 	add_next_index_string(return_value, enclosure);
2724 	add_next_index_string(return_value, escape);
2725 }
2726 /* }}} */
2727 
2728 /* {{{ proto bool SplFileObject::flock(int operation [, int &wouldblock])
2729    Portable file locking */
2730 FileFunction(flock)
2731 /* }}} */
2732 
2733 /* {{{ proto bool SplFileObject::fflush()
2734    Flush the file */
SPL_METHOD(SplFileObject,fflush)2735 SPL_METHOD(SplFileObject, fflush)
2736 {
2737 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2738 
2739 	if(!intern->u.file.stream) {
2740 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2741 		return;
2742 	}
2743 
2744 	RETURN_BOOL(!php_stream_flush(intern->u.file.stream));
2745 } /* }}} */
2746 
2747 /* {{{ proto int SplFileObject::ftell()
2748    Return current file position */
SPL_METHOD(SplFileObject,ftell)2749 SPL_METHOD(SplFileObject, ftell)
2750 {
2751 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2752 	zend_long ret;
2753 
2754 	if(!intern->u.file.stream) {
2755 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2756 		return;
2757 	}
2758 
2759 	ret = php_stream_tell(intern->u.file.stream);
2760 
2761 	if (ret == -1) {
2762 		RETURN_FALSE;
2763 	} else {
2764 		RETURN_LONG(ret);
2765 	}
2766 } /* }}} */
2767 
2768 /* {{{ proto int SplFileObject::fseek(int pos [, int whence = SEEK_SET])
2769    Return current file position */
SPL_METHOD(SplFileObject,fseek)2770 SPL_METHOD(SplFileObject, fseek)
2771 {
2772 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2773 	zend_long pos, whence = SEEK_SET;
2774 
2775 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &pos, &whence) == FAILURE) {
2776 		return;
2777 	}
2778 
2779 	if(!intern->u.file.stream) {
2780 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2781 		return;
2782 	}
2783 
2784 	spl_filesystem_file_free_line(intern);
2785 	RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, (int)whence));
2786 } /* }}} */
2787 
2788 /* {{{ proto int SplFileObject::fgetc()
2789    Get a character form the file */
SPL_METHOD(SplFileObject,fgetc)2790 SPL_METHOD(SplFileObject, fgetc)
2791 {
2792 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2793 	char buf[2];
2794 	int result;
2795 
2796 	if(!intern->u.file.stream) {
2797 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2798 		return;
2799 	}
2800 
2801 	spl_filesystem_file_free_line(intern);
2802 
2803 	result = php_stream_getc(intern->u.file.stream);
2804 
2805 	if (result == EOF) {
2806 		RETVAL_FALSE;
2807 	} else {
2808 		if (result == '\n') {
2809 			intern->u.file.current_line_num++;
2810 		}
2811 		buf[0] = result;
2812 		buf[1] = '\0';
2813 
2814 		RETURN_STRINGL(buf, 1);
2815 	}
2816 } /* }}} */
2817 
2818 /* {{{ proto string SplFileObject::fgetss([string allowable_tags])
2819    Get a line from file pointer and strip HTML tags */
SPL_METHOD(SplFileObject,fgetss)2820 SPL_METHOD(SplFileObject, fgetss)
2821 {
2822 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2823 	zval arg2;
2824 
2825 	if(!intern->u.file.stream) {
2826 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2827 		return;
2828 	}
2829 
2830 	if (intern->u.file.max_line_len > 0) {
2831 		ZVAL_LONG(&arg2, intern->u.file.max_line_len);
2832 	} else {
2833 		ZVAL_LONG(&arg2, 1024);
2834 	}
2835 
2836 	spl_filesystem_file_free_line(intern);
2837 	intern->u.file.current_line_num++;
2838 
2839 	FileFunctionCall(fgetss, ZEND_NUM_ARGS(), &arg2);
2840 } /* }}} */
2841 
2842 /* {{{ proto int SplFileObject::fpassthru()
2843    Output all remaining data from a file pointer */
SPL_METHOD(SplFileObject,fpassthru)2844 SPL_METHOD(SplFileObject, fpassthru)
2845 {
2846 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2847 
2848 	if(!intern->u.file.stream) {
2849 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2850 		return;
2851 	}
2852 
2853 	RETURN_LONG(php_stream_passthru(intern->u.file.stream));
2854 } /* }}} */
2855 
2856 /* {{{ proto bool SplFileObject::fscanf(string format [, string ...])
2857    Implements a mostly ANSI compatible fscanf() */
SPL_METHOD(SplFileObject,fscanf)2858 SPL_METHOD(SplFileObject, fscanf)
2859 {
2860 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2861 
2862 	if(!intern->u.file.stream) {
2863 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2864 		return;
2865 	}
2866 
2867 	spl_filesystem_file_free_line(intern);
2868 	intern->u.file.current_line_num++;
2869 
2870 	FileFunctionCall(fscanf, ZEND_NUM_ARGS(), NULL);
2871 }
2872 /* }}} */
2873 
2874 /* {{{ proto mixed SplFileObject::fwrite(string str [, int length])
2875    Binary-safe file write */
SPL_METHOD(SplFileObject,fwrite)2876 SPL_METHOD(SplFileObject, fwrite)
2877 {
2878 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2879 	char *str;
2880 	size_t str_len;
2881 	zend_long length = 0;
2882 
2883 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &length) == FAILURE) {
2884 		return;
2885 	}
2886 
2887 	if(!intern->u.file.stream) {
2888 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2889 		return;
2890 	}
2891 
2892 	if (ZEND_NUM_ARGS() > 1) {
2893 		if (length >= 0) {
2894 			str_len = MIN((size_t)length, str_len);
2895 		} else {
2896 			/* Negative length given, nothing to write */
2897 			str_len = 0;
2898 		}
2899 	}
2900 	if (!str_len) {
2901 		RETURN_LONG(0);
2902 	}
2903 
2904 	RETURN_LONG(php_stream_write(intern->u.file.stream, str, str_len));
2905 } /* }}} */
2906 
SPL_METHOD(SplFileObject,fread)2907 SPL_METHOD(SplFileObject, fread)
2908 {
2909 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2910 	zend_long length = 0;
2911 
2912 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &length) == FAILURE) {
2913 		return;
2914 	}
2915 
2916 	if(!intern->u.file.stream) {
2917 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2918 		return;
2919 	}
2920 
2921 	if (length <= 0) {
2922 		php_error_docref(NULL, E_WARNING, "Length parameter must be greater than 0");
2923 		RETURN_FALSE;
2924 	}
2925 
2926 	ZVAL_NEW_STR(return_value, zend_string_alloc(length, 0));
2927 	Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length);
2928 
2929 	/* needed because recv/read/gzread doesnt put a null at the end*/
2930 	Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
2931 }
2932 
2933 /* {{{ proto bool SplFileObject::fstat()
2934    Stat() on a filehandle */
2935 FileFunction(fstat)
2936 /* }}} */
2937 
2938 /* {{{ proto bool SplFileObject::ftruncate(int size)
2939    Truncate file to 'size' length */
SPL_METHOD(SplFileObject,ftruncate)2940 SPL_METHOD(SplFileObject, ftruncate)
2941 {
2942 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2943 	zend_long size;
2944 
2945 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &size) == FAILURE) {
2946 		return;
2947 	}
2948 
2949 	if(!intern->u.file.stream) {
2950 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2951 		return;
2952 	}
2953 
2954 	if (!php_stream_truncate_supported(intern->u.file.stream)) {
2955 		zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", intern->file_name);
2956 		RETURN_FALSE;
2957 	}
2958 
2959 	RETURN_BOOL(0 == php_stream_truncate_set_size(intern->u.file.stream, size));
2960 } /* }}} */
2961 
2962 /* {{{ proto void SplFileObject::seek(int line_pos)
2963    Seek to specified line */
SPL_METHOD(SplFileObject,seek)2964 SPL_METHOD(SplFileObject, seek)
2965 {
2966 	spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(getThis());
2967 	zend_long line_pos;
2968 
2969 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) {
2970 		return;
2971 	}
2972 	if(!intern->u.file.stream) {
2973 		zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2974 		return;
2975 	}
2976 
2977 	if (line_pos < 0) {
2978 		zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't seek file %s to negative line " ZEND_LONG_FMT, intern->file_name, line_pos);
2979 		RETURN_FALSE;
2980 	}
2981 
2982 	spl_filesystem_file_rewind(getThis(), intern);
2983 
2984 	while(intern->u.file.current_line_num < line_pos) {
2985 		if (spl_filesystem_file_read_line(getThis(), intern, 1) == FAILURE) {
2986 			break;
2987 		}
2988 	}
2989 } /* }}} */
2990 
2991 /* {{{ Function/Class/Method definitions */
2992 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object___construct, 0, 0, 1)
2993 	ZEND_ARG_INFO(0, file_name)
2994 	ZEND_ARG_INFO(0, open_mode)
2995 	ZEND_ARG_INFO(0, use_include_path)
2996 	ZEND_ARG_INFO(0, context)
2997 ZEND_END_ARG_INFO()
2998 
2999 ZEND_BEGIN_ARG_INFO(arginfo_file_object_setFlags, 0)
3000 	ZEND_ARG_INFO(0, flags)
3001 ZEND_END_ARG_INFO()
3002 
3003 ZEND_BEGIN_ARG_INFO(arginfo_file_object_setMaxLineLen, 0)
3004 	ZEND_ARG_INFO(0, max_len)
3005 ZEND_END_ARG_INFO()
3006 
3007 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetcsv, 0, 0, 0)
3008 	ZEND_ARG_INFO(0, delimiter)
3009 	ZEND_ARG_INFO(0, enclosure)
3010 	ZEND_ARG_INFO(0, escape)
3011 ZEND_END_ARG_INFO()
3012 
3013 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fputcsv, 0, 0, 1)
3014 	ZEND_ARG_INFO(0, fields)
3015 	ZEND_ARG_INFO(0, delimiter)
3016 	ZEND_ARG_INFO(0, enclosure)
3017 	ZEND_ARG_INFO(0, escape)
3018 ZEND_END_ARG_INFO()
3019 
3020 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_flock, 0, 0, 1)
3021 	ZEND_ARG_INFO(0, operation)
3022 	ZEND_ARG_INFO(1, wouldblock)
3023 ZEND_END_ARG_INFO()
3024 
3025 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fseek, 0, 0, 1)
3026 	ZEND_ARG_INFO(0, pos)
3027 	ZEND_ARG_INFO(0, whence)
3028 ZEND_END_ARG_INFO()
3029 
3030 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fgetss, 0, 0, 0)
3031 	ZEND_ARG_INFO(0, allowable_tags)
3032 ZEND_END_ARG_INFO()
3033 
3034 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fscanf, 0, 0, 1)
3035 	ZEND_ARG_INFO(0, format)
3036 	ZEND_ARG_VARIADIC_INFO(1, vars)
3037 ZEND_END_ARG_INFO()
3038 
3039 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fwrite, 0, 0, 1)
3040 	ZEND_ARG_INFO(0, str)
3041 	ZEND_ARG_INFO(0, length)
3042 ZEND_END_ARG_INFO()
3043 
3044 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_fread, 0, 0, 1)
3045 	ZEND_ARG_INFO(0, length)
3046 ZEND_END_ARG_INFO()
3047 
3048 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_ftruncate, 0, 0, 1)
3049 	ZEND_ARG_INFO(0, size)
3050 ZEND_END_ARG_INFO()
3051 
3052 ZEND_BEGIN_ARG_INFO_EX(arginfo_file_object_seek, 0, 0, 1)
3053 	ZEND_ARG_INFO(0, line_pos)
3054 ZEND_END_ARG_INFO()
3055 
3056 static const zend_function_entry spl_SplFileObject_functions[] = {
3057 	SPL_ME(SplFileObject, __construct,    arginfo_file_object___construct,   ZEND_ACC_PUBLIC)
3058 	SPL_ME(SplFileObject, rewind,         arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3059 	SPL_ME(SplFileObject, eof,            arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3060 	SPL_ME(SplFileObject, valid,          arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3061 	SPL_ME(SplFileObject, fgets,          arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3062 	SPL_ME(SplFileObject, fgetcsv,        arginfo_file_object_fgetcsv,       ZEND_ACC_PUBLIC)
3063 	SPL_ME(SplFileObject, fputcsv,        arginfo_file_object_fputcsv,       ZEND_ACC_PUBLIC)
3064 	SPL_ME(SplFileObject, setCsvControl,  arginfo_file_object_fgetcsv,       ZEND_ACC_PUBLIC)
3065 	SPL_ME(SplFileObject, getCsvControl,  arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3066 	SPL_ME(SplFileObject, flock,          arginfo_file_object_flock,         ZEND_ACC_PUBLIC)
3067 	SPL_ME(SplFileObject, fflush,         arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3068 	SPL_ME(SplFileObject, ftell,          arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3069 	SPL_ME(SplFileObject, fseek,          arginfo_file_object_fseek,         ZEND_ACC_PUBLIC)
3070 	SPL_ME(SplFileObject, fgetc,          arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3071 	SPL_ME(SplFileObject, fpassthru,      arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3072 	SPL_ME(SplFileObject, fgetss,         arginfo_file_object_fgetss,        ZEND_ACC_PUBLIC)
3073 	SPL_ME(SplFileObject, fscanf,         arginfo_file_object_fscanf,        ZEND_ACC_PUBLIC)
3074 	SPL_ME(SplFileObject, fwrite,         arginfo_file_object_fwrite,        ZEND_ACC_PUBLIC)
3075 	SPL_ME(SplFileObject, fread,          arginfo_file_object_fread,         ZEND_ACC_PUBLIC)
3076 	SPL_ME(SplFileObject, fstat,          arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3077 	SPL_ME(SplFileObject, ftruncate,      arginfo_file_object_ftruncate,     ZEND_ACC_PUBLIC)
3078 	SPL_ME(SplFileObject, current,        arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3079 	SPL_ME(SplFileObject, key,            arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3080 	SPL_ME(SplFileObject, next,           arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3081 	SPL_ME(SplFileObject, setFlags,       arginfo_file_object_setFlags,      ZEND_ACC_PUBLIC)
3082 	SPL_ME(SplFileObject, getFlags,       arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3083 	SPL_ME(SplFileObject, setMaxLineLen,  arginfo_file_object_setMaxLineLen, ZEND_ACC_PUBLIC)
3084 	SPL_ME(SplFileObject, getMaxLineLen,  arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3085 	SPL_ME(SplFileObject, hasChildren,    arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3086 	SPL_ME(SplFileObject, getChildren,    arginfo_splfileinfo_void,          ZEND_ACC_PUBLIC)
3087 	SPL_ME(SplFileObject, seek,           arginfo_file_object_seek,          ZEND_ACC_PUBLIC)
3088 	/* mappings */
3089 	SPL_MA(SplFileObject, getCurrentLine, SplFileObject, fgets,      arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
3090 	SPL_MA(SplFileObject, __toString,     SplFileObject, current,    arginfo_splfileinfo_void, ZEND_ACC_PUBLIC)
3091 	PHP_FE_END
3092 };
3093 
3094 ZEND_BEGIN_ARG_INFO_EX(arginfo_temp_file_object___construct, 0, 0, 0)
3095 	ZEND_ARG_INFO(0, max_memory)
3096 ZEND_END_ARG_INFO()
3097 
3098 static const zend_function_entry spl_SplTempFileObject_functions[] = {
3099 	SPL_ME(SplTempFileObject, __construct, arginfo_temp_file_object___construct,  ZEND_ACC_PUBLIC)
3100 	PHP_FE_END
3101 };
3102 /* }}} */
3103 
3104 /* {{{ PHP_MINIT_FUNCTION(spl_directory)
3105  */
PHP_MINIT_FUNCTION(spl_directory)3106 PHP_MINIT_FUNCTION(spl_directory)
3107 {
3108 	REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, spl_SplFileInfo_functions);
3109 	memcpy(&spl_filesystem_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
3110 	spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std);
3111 	spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
3112 	spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast;
3113 	spl_filesystem_object_handlers.get_debug_info  = spl_filesystem_object_get_debug_info;
3114 	spl_filesystem_object_handlers.dtor_obj = zend_objects_destroy_object;
3115 	spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage;
3116 	spl_ce_SplFileInfo->serialize = zend_class_serialize_deny;
3117 	spl_ce_SplFileInfo->unserialize = zend_class_unserialize_deny;
3118 
3119 
3120 	REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, spl_DirectoryIterator_functions);
3121 	zend_class_implements(spl_ce_DirectoryIterator, 1, zend_ce_iterator);
3122 	REGISTER_SPL_IMPLEMENTS(DirectoryIterator, SeekableIterator);
3123 
3124 	spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator;
3125 
3126 	REGISTER_SPL_SUB_CLASS_EX(FilesystemIterator, DirectoryIterator, spl_filesystem_object_new, spl_FilesystemIterator_functions);
3127 
3128 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_MODE_MASK",   SPL_FILE_DIR_CURRENT_MODE_MASK);
3129 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_PATHNAME", SPL_FILE_DIR_CURRENT_AS_PATHNAME);
3130 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_FILEINFO", SPL_FILE_DIR_CURRENT_AS_FILEINFO);
3131 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_SELF",     SPL_FILE_DIR_CURRENT_AS_SELF);
3132 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_MODE_MASK",       SPL_FILE_DIR_KEY_MODE_MASK);
3133 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_PATHNAME",     SPL_FILE_DIR_KEY_AS_PATHNAME);
3134 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "FOLLOW_SYMLINKS",     SPL_FILE_DIR_FOLLOW_SYMLINKS);
3135 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_FILENAME",     SPL_FILE_DIR_KEY_AS_FILENAME);
3136 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "NEW_CURRENT_AND_KEY", SPL_FILE_DIR_KEY_AS_FILENAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO);
3137 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "OTHER_MODE_MASK",     SPL_FILE_DIR_OTHERS_MASK);
3138 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "SKIP_DOTS",           SPL_FILE_DIR_SKIPDOTS);
3139 	REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "UNIX_PATHS",          SPL_FILE_DIR_UNIXPATHS);
3140 
3141 	spl_ce_FilesystemIterator->get_iterator = spl_filesystem_tree_get_iterator;
3142 
3143 	REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, FilesystemIterator, spl_filesystem_object_new, spl_RecursiveDirectoryIterator_functions);
3144 	REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator);
3145 
3146 	memcpy(&spl_filesystem_object_check_handlers, &spl_filesystem_object_handlers, sizeof(zend_object_handlers));
3147 	spl_filesystem_object_check_handlers.get_method = spl_filesystem_object_get_method_check;
3148 
3149 #ifdef HAVE_GLOB
3150 	REGISTER_SPL_SUB_CLASS_EX(GlobIterator, FilesystemIterator, spl_filesystem_object_new_check, spl_GlobIterator_functions);
3151 	REGISTER_SPL_IMPLEMENTS(GlobIterator, Countable);
3152 #endif
3153 
3154 	REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_new_check, spl_SplFileObject_functions);
3155 	REGISTER_SPL_IMPLEMENTS(SplFileObject, RecursiveIterator);
3156 	REGISTER_SPL_IMPLEMENTS(SplFileObject, SeekableIterator);
3157 
3158 	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "DROP_NEW_LINE", SPL_FILE_OBJECT_DROP_NEW_LINE);
3159 	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_AHEAD",    SPL_FILE_OBJECT_READ_AHEAD);
3160 	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "SKIP_EMPTY",    SPL_FILE_OBJECT_SKIP_EMPTY);
3161 	REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_CSV",      SPL_FILE_OBJECT_READ_CSV);
3162 
3163 	REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new_check, spl_SplTempFileObject_functions);
3164 	return SUCCESS;
3165 }
3166 /* }}} */
3167 
3168 /*
3169  * Local variables:
3170  * tab-width: 4
3171  * c-basic-offset: 4
3172  * End:
3173  * vim600: noet sw=4 ts=4 fdm=marker
3174  * vim<600: noet sw=4 ts=4
3175  */
3176