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