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