root/ext/spl/spl_directory.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. spl_filesystem_file_free_line
  2. spl_filesystem_object_free_storage
  3. spl_filesystem_object_new_ex
  4. spl_filesystem_object_new
  5. spl_filesystem_object_new_check
  6. spl_filesystem_object_get_path
  7. spl_filesystem_object_get_file_name
  8. spl_filesystem_dir_read
  9. spl_filesystem_is_dot
  10. spl_filesystem_dir_open
  11. spl_filesystem_file_open
  12. spl_filesystem_object_clone
  13. spl_filesystem_info_set_filename
  14. spl_filesystem_object_create_info
  15. spl_filesystem_object_create_type
  16. spl_filesystem_is_invalid_or_dot
  17. spl_filesystem_object_get_pathname
  18. spl_filesystem_object_get_debug_info
  19. spl_filesystem_object_get_method_check
  20. spl_filesystem_object_construct
  21. SPL_METHOD
  22. SPL_METHOD
  23. SPL_METHOD
  24. SPL_METHOD
  25. SPL_METHOD
  26. SPL_METHOD
  27. SPL_METHOD
  28. SPL_METHOD
  29. SPL_METHOD
  30. SPL_METHOD
  31. SPL_METHOD
  32. SPL_METHOD
  33. SPL_METHOD
  34. SPL_METHOD
  35. SPL_METHOD
  36. SPL_METHOD
  37. SPL_METHOD
  38. SPL_METHOD
  39. SPL_METHOD
  40. FileInfoFunction
  41. SPL_METHOD
  42. SPL_METHOD
  43. SPL_METHOD
  44. SPL_METHOD
  45. SPL_METHOD
  46. SPL_METHOD
  47. SPL_METHOD
  48. SPL_METHOD
  49. SPL_METHOD
  50. SPL_METHOD
  51. SPL_METHOD
  52. SPL_METHOD
  53. SPL_METHOD
  54. SPL_METHOD
  55. SPL_METHOD
  56. SPL_METHOD
  57. SPL_METHOD
  58. SPL_METHOD
  59. spl_filesystem_dir_get_iterator
  60. spl_filesystem_dir_it_dtor
  61. spl_filesystem_dir_it_valid
  62. spl_filesystem_dir_it_current_data
  63. spl_filesystem_dir_it_current_key
  64. spl_filesystem_dir_it_move_forward
  65. spl_filesystem_dir_it_rewind
  66. spl_filesystem_tree_it_dtor
  67. spl_filesystem_tree_it_current_data
  68. spl_filesystem_tree_it_current_key
  69. spl_filesystem_tree_it_move_forward
  70. spl_filesystem_tree_it_rewind
  71. spl_filesystem_tree_get_iterator
  72. spl_filesystem_object_cast
  73. spl_filesystem_file_read
  74. spl_filesystem_file_call
  75. spl_filesystem_file_read_csv
  76. spl_filesystem_file_read_line_ex
  77. spl_filesystem_file_is_empty_line
  78. spl_filesystem_file_read_line
  79. spl_filesystem_file_rewind
  80. SPL_METHOD
  81. SPL_METHOD
  82. SPL_METHOD
  83. SPL_METHOD
  84. SPL_METHOD
  85. SPL_METHOD
  86. SPL_METHOD
  87. SPL_METHOD
  88. SPL_METHOD
  89. SPL_METHOD
  90. SPL_METHOD
  91. SPL_METHOD
  92. SPL_METHOD
  93. SPL_METHOD
  94. SPL_METHOD
  95. SPL_METHOD
  96. SPL_METHOD
  97. SPL_METHOD
  98. SPL_METHOD
  99. FileFunction
  100. SPL_METHOD
  101. SPL_METHOD
  102. SPL_METHOD
  103. SPL_METHOD
  104. SPL_METHOD
  105. SPL_METHOD
  106. SPL_METHOD
  107. SPL_METHOD
  108. FileFunction
  109. SPL_METHOD
  110. PHP_MINIT_FUNCTION

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

/* [<][>][^][v][top][bottom][index][help] */