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