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