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