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