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