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