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