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