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