PageRenderTime 64ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/spl/spl_directory.c

http://github.com/php/php-src
C | 2922 lines | 2286 code | 318 blank | 318 comment | 366 complexity | 008ab01183c483dd353e82d7af6a7ef3 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | http://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Marcus Boerger <helly@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. # include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "php_ini.h"
  21. #include "ext/standard/info.h"
  22. #include "ext/standard/file.h"
  23. #include "ext/standard/php_string.h"
  24. #include "zend_compile.h"
  25. #include "zend_exceptions.h"
  26. #include "zend_interfaces.h"
  27. #include "php_spl.h"
  28. #include "spl_functions.h"
  29. #include "spl_engine.h"
  30. #include "spl_iterators.h"
  31. #include "spl_directory.h"
  32. #include "spl_directory_arginfo.h"
  33. #include "spl_exceptions.h"
  34. #include "php.h"
  35. #include "fopen_wrappers.h"
  36. #include "ext/standard/basic_functions.h"
  37. #include "ext/standard/php_filestat.h"
  38. #define SPL_HAS_FLAG(flags, test_flag) ((flags & test_flag) ? 1 : 0)
  39. /* declare the class handlers */
  40. static zend_object_handlers spl_filesystem_object_handlers;
  41. /* includes handler to validate object state when retrieving methods */
  42. static zend_object_handlers spl_filesystem_object_check_handlers;
  43. /* decalre the class entry */
  44. PHPAPI zend_class_entry *spl_ce_SplFileInfo;
  45. PHPAPI zend_class_entry *spl_ce_DirectoryIterator;
  46. PHPAPI zend_class_entry *spl_ce_FilesystemIterator;
  47. PHPAPI zend_class_entry *spl_ce_RecursiveDirectoryIterator;
  48. PHPAPI zend_class_entry *spl_ce_GlobIterator;
  49. PHPAPI zend_class_entry *spl_ce_SplFileObject;
  50. PHPAPI zend_class_entry *spl_ce_SplTempFileObject;
  51. static void spl_filesystem_file_free_line(spl_filesystem_object *intern) /* {{{ */
  52. {
  53. if (intern->u.file.current_line) {
  54. efree(intern->u.file.current_line);
  55. intern->u.file.current_line = NULL;
  56. }
  57. if (!Z_ISUNDEF(intern->u.file.current_zval)) {
  58. zval_ptr_dtor(&intern->u.file.current_zval);
  59. ZVAL_UNDEF(&intern->u.file.current_zval);
  60. }
  61. } /* }}} */
  62. static void spl_filesystem_object_destroy_object(zend_object *object) /* {{{ */
  63. {
  64. spl_filesystem_object *intern = spl_filesystem_from_obj(object);
  65. zend_objects_destroy_object(object);
  66. switch(intern->type) {
  67. case SPL_FS_DIR:
  68. if (intern->u.dir.dirp) {
  69. php_stream_close(intern->u.dir.dirp);
  70. intern->u.dir.dirp = NULL;
  71. }
  72. break;
  73. case SPL_FS_FILE:
  74. if (intern->u.file.stream) {
  75. /*
  76. if (intern->u.file.zcontext) {
  77. zend_list_delref(Z_RESVAL_P(intern->zcontext));
  78. }
  79. */
  80. if (!intern->u.file.stream->is_persistent) {
  81. php_stream_close(intern->u.file.stream);
  82. } else {
  83. php_stream_pclose(intern->u.file.stream);
  84. }
  85. intern->u.file.stream = NULL;
  86. }
  87. break;
  88. default:
  89. break;
  90. }
  91. } /* }}} */
  92. static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
  93. {
  94. spl_filesystem_object *intern = spl_filesystem_from_obj(object);
  95. if (intern->oth_handler && intern->oth_handler->dtor) {
  96. intern->oth_handler->dtor(intern);
  97. }
  98. zend_object_std_dtor(&intern->std);
  99. if (intern->_path) {
  100. efree(intern->_path);
  101. }
  102. if (intern->file_name) {
  103. efree(intern->file_name);
  104. }
  105. switch(intern->type) {
  106. case SPL_FS_INFO:
  107. break;
  108. case SPL_FS_DIR:
  109. if (intern->u.dir.sub_path) {
  110. efree(intern->u.dir.sub_path);
  111. }
  112. break;
  113. case SPL_FS_FILE:
  114. if (intern->u.file.open_mode) {
  115. efree(intern->u.file.open_mode);
  116. }
  117. if (intern->orig_path) {
  118. efree(intern->orig_path);
  119. }
  120. spl_filesystem_file_free_line(intern);
  121. break;
  122. }
  123. } /* }}} */
  124. /* {{{ spl_ce_dir_object_new */
  125. /* creates the object by
  126. - allocating memory
  127. - initializing the object members
  128. - storing the object
  129. - setting it's handlers
  130. called from
  131. - clone
  132. - new
  133. */
  134. static zend_object *spl_filesystem_object_new_ex(zend_class_entry *class_type)
  135. {
  136. spl_filesystem_object *intern;
  137. intern = zend_object_alloc(sizeof(spl_filesystem_object), class_type);
  138. /* intern->type = SPL_FS_INFO; done by set 0 */
  139. intern->file_class = spl_ce_SplFileObject;
  140. intern->info_class = spl_ce_SplFileInfo;
  141. zend_object_std_init(&intern->std, class_type);
  142. object_properties_init(&intern->std, class_type);
  143. intern->std.handlers = &spl_filesystem_object_handlers;
  144. return &intern->std;
  145. }
  146. /* }}} */
  147. /* {{{ spl_filesystem_object_new */
  148. /* See spl_filesystem_object_new_ex */
  149. static zend_object *spl_filesystem_object_new(zend_class_entry *class_type)
  150. {
  151. return spl_filesystem_object_new_ex(class_type);
  152. }
  153. /* }}} */
  154. /* {{{ spl_filesystem_object_new_check */
  155. static zend_object *spl_filesystem_object_new_check(zend_class_entry *class_type)
  156. {
  157. spl_filesystem_object *ret = spl_filesystem_from_obj(spl_filesystem_object_new_ex(class_type));
  158. ret->std.handlers = &spl_filesystem_object_check_handlers;
  159. return &ret->std;
  160. }
  161. /* }}} */
  162. PHPAPI char* spl_filesystem_object_get_path(spl_filesystem_object *intern, size_t *len) /* {{{ */
  163. {
  164. #ifdef HAVE_GLOB
  165. if (intern->type == SPL_FS_DIR) {
  166. if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
  167. return php_glob_stream_get_path(intern->u.dir.dirp, len);
  168. }
  169. }
  170. #endif
  171. if (len) {
  172. *len = intern->_path_len;
  173. }
  174. return intern->_path;
  175. } /* }}} */
  176. static inline void spl_filesystem_object_get_file_name(spl_filesystem_object *intern) /* {{{ */
  177. {
  178. char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
  179. switch (intern->type) {
  180. case SPL_FS_INFO:
  181. case SPL_FS_FILE:
  182. if (!intern->file_name) {
  183. php_error_docref(NULL, E_ERROR, "Object not initialized");
  184. }
  185. break;
  186. case SPL_FS_DIR:
  187. {
  188. size_t path_len = 0;
  189. char *path = spl_filesystem_object_get_path(intern, &path_len);
  190. if (intern->file_name) {
  191. efree(intern->file_name);
  192. }
  193. /* if there is parent path, amend it, otherwise just use the given path as is */
  194. if (path_len == 0) {
  195. intern->file_name_len = spprintf(
  196. &intern->file_name, 0, "%s", intern->u.dir.entry.d_name);
  197. } else {
  198. intern->file_name_len = spprintf(
  199. &intern->file_name, 0, "%s%c%s", path, slash, intern->u.dir.entry.d_name);
  200. }
  201. }
  202. break;
  203. }
  204. } /* }}} */
  205. static int spl_filesystem_dir_read(spl_filesystem_object *intern) /* {{{ */
  206. {
  207. if (!intern->u.dir.dirp || !php_stream_readdir(intern->u.dir.dirp, &intern->u.dir.entry)) {
  208. intern->u.dir.entry.d_name[0] = '\0';
  209. return 0;
  210. } else {
  211. return 1;
  212. }
  213. }
  214. /* }}} */
  215. #define IS_SLASH_AT(zs, pos) (IS_SLASH(zs[pos]))
  216. static inline int spl_filesystem_is_dot(const char * d_name) /* {{{ */
  217. {
  218. return !strcmp(d_name, ".") || !strcmp(d_name, "..");
  219. }
  220. /* }}} */
  221. /* {{{ spl_filesystem_dir_open */
  222. /* open a directory resource */
  223. static void spl_filesystem_dir_open(spl_filesystem_object* intern, char *path)
  224. {
  225. int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
  226. intern->type = SPL_FS_DIR;
  227. intern->_path_len = strlen(path);
  228. intern->u.dir.dirp = php_stream_opendir(path, REPORT_ERRORS, FG(default_context));
  229. if (intern->_path_len > 1 && IS_SLASH_AT(path, intern->_path_len-1)) {
  230. intern->_path = estrndup(path, --intern->_path_len);
  231. } else {
  232. intern->_path = estrndup(path, intern->_path_len);
  233. }
  234. intern->u.dir.index = 0;
  235. if (EG(exception) || intern->u.dir.dirp == NULL) {
  236. intern->u.dir.entry.d_name[0] = '\0';
  237. if (!EG(exception)) {
  238. /* open failed w/out notice (turned to exception due to EH_THROW) */
  239. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  240. "Failed to open directory \"%s\"", path);
  241. }
  242. } else {
  243. do {
  244. spl_filesystem_dir_read(intern);
  245. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  246. }
  247. }
  248. /* }}} */
  249. static int spl_filesystem_file_open(spl_filesystem_object *intern, int use_include_path, int silent) /* {{{ */
  250. {
  251. zval tmp;
  252. intern->type = SPL_FS_FILE;
  253. php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, &tmp);
  254. if (Z_TYPE(tmp) == IS_TRUE) {
  255. intern->u.file.open_mode = NULL;
  256. intern->file_name = NULL;
  257. zend_throw_exception_ex(spl_ce_LogicException, 0, "Cannot use SplFileObject with directories");
  258. return FAILURE;
  259. }
  260. intern->u.file.context = php_stream_context_from_zval(intern->u.file.zcontext, 0);
  261. 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);
  262. if (!intern->file_name_len || !intern->u.file.stream) {
  263. if (!EG(exception)) {
  264. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot open file '%s'", intern->file_name_len ? intern->file_name : "");
  265. }
  266. intern->file_name = NULL; /* until here it is not a copy */
  267. intern->u.file.open_mode = NULL;
  268. return FAILURE;
  269. }
  270. /*
  271. if (intern->u.file.zcontext) {
  272. //zend_list_addref(Z_RES_VAL(intern->u.file.zcontext));
  273. Z_ADDREF_P(intern->u.file.zcontext);
  274. }
  275. */
  276. if (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
  277. intern->file_name_len--;
  278. }
  279. intern->orig_path = estrndup(intern->u.file.stream->orig_path, strlen(intern->u.file.stream->orig_path));
  280. intern->file_name = estrndup(intern->file_name, intern->file_name_len);
  281. intern->u.file.open_mode = estrndup(intern->u.file.open_mode, intern->u.file.open_mode_len);
  282. /* avoid reference counting in debug mode, thus do it manually */
  283. ZVAL_RES(&intern->u.file.zresource, intern->u.file.stream->res);
  284. /*!!! TODO: maybe bug?
  285. Z_SET_REFCOUNT(intern->u.file.zresource, 1);
  286. */
  287. intern->u.file.delimiter = ',';
  288. intern->u.file.enclosure = '"';
  289. intern->u.file.escape = (unsigned char) '\\';
  290. intern->u.file.func_getCurr = zend_hash_str_find_ptr(&intern->std.ce->function_table, "getcurrentline", sizeof("getcurrentline") - 1);
  291. return SUCCESS;
  292. } /* }}} */
  293. /* {{{ spl_filesystem_object_clone */
  294. /* Local zend_object creation (on stack)
  295. Load the 'other' object
  296. Create a new empty object (See spl_filesystem_object_new_ex)
  297. Open the directory
  298. Clone other members (properties)
  299. */
  300. static zend_object *spl_filesystem_object_clone(zend_object *old_object)
  301. {
  302. zend_object *new_object;
  303. spl_filesystem_object *intern;
  304. spl_filesystem_object *source;
  305. int index, skip_dots;
  306. source = spl_filesystem_from_obj(old_object);
  307. new_object = spl_filesystem_object_new_ex(old_object->ce);
  308. intern = spl_filesystem_from_obj(new_object);
  309. intern->flags = source->flags;
  310. switch (source->type) {
  311. case SPL_FS_INFO:
  312. intern->_path_len = source->_path_len;
  313. intern->_path = estrndup(source->_path, source->_path_len);
  314. intern->file_name_len = source->file_name_len;
  315. intern->file_name = estrndup(source->file_name, intern->file_name_len);
  316. break;
  317. case SPL_FS_DIR:
  318. spl_filesystem_dir_open(intern, source->_path);
  319. /* read until we hit the position in which we were before */
  320. skip_dots = SPL_HAS_FLAG(source->flags, SPL_FILE_DIR_SKIPDOTS);
  321. for(index = 0; index < source->u.dir.index; ++index) {
  322. do {
  323. spl_filesystem_dir_read(intern);
  324. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  325. }
  326. intern->u.dir.index = index;
  327. break;
  328. case SPL_FS_FILE:
  329. ZEND_ASSERT(0);
  330. }
  331. intern->file_class = source->file_class;
  332. intern->info_class = source->info_class;
  333. intern->oth = source->oth;
  334. intern->oth_handler = source->oth_handler;
  335. zend_objects_clone_members(new_object, old_object);
  336. if (intern->oth_handler && intern->oth_handler->clone) {
  337. intern->oth_handler->clone(source, intern);
  338. }
  339. return new_object;
  340. }
  341. /* }}} */
  342. void spl_filesystem_info_set_filename(spl_filesystem_object *intern, char *path, size_t len, size_t use_copy) /* {{{ */
  343. {
  344. char *p1, *p2;
  345. if (intern->file_name) {
  346. efree(intern->file_name);
  347. }
  348. intern->file_name = use_copy ? estrndup(path, len) : path;
  349. intern->file_name_len = len;
  350. while (intern->file_name_len > 1 && IS_SLASH_AT(intern->file_name, intern->file_name_len-1)) {
  351. intern->file_name[intern->file_name_len-1] = 0;
  352. intern->file_name_len--;
  353. }
  354. p1 = strrchr(intern->file_name, '/');
  355. #if defined(PHP_WIN32)
  356. p2 = strrchr(intern->file_name, '\\');
  357. #else
  358. p2 = 0;
  359. #endif
  360. if (p1 || p2) {
  361. intern->_path_len = ((p1 > p2 ? p1 : p2) - intern->file_name);
  362. } else {
  363. intern->_path_len = 0;
  364. }
  365. if (intern->_path) {
  366. efree(intern->_path);
  367. }
  368. intern->_path = estrndup(path, intern->_path_len);
  369. } /* }}} */
  370. static spl_filesystem_object *spl_filesystem_object_create_info(spl_filesystem_object *source, char *file_path, size_t file_path_len, int use_copy, zend_class_entry *ce, zval *return_value) /* {{{ */
  371. {
  372. spl_filesystem_object *intern;
  373. zval arg1;
  374. zend_error_handling error_handling;
  375. if (!file_path || !file_path_len) {
  376. #if defined(PHP_WIN32)
  377. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot create SplFileInfo for empty path");
  378. if (file_path && !use_copy) {
  379. efree(file_path);
  380. }
  381. #else
  382. if (file_path && !use_copy) {
  383. efree(file_path);
  384. }
  385. file_path_len = 1;
  386. file_path = "/";
  387. #endif
  388. return NULL;
  389. }
  390. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
  391. ce = ce ? ce : source->info_class;
  392. zend_update_class_constants(ce);
  393. intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
  394. ZVAL_OBJ(return_value, &intern->std);
  395. if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
  396. ZVAL_STRINGL(&arg1, file_path, file_path_len);
  397. zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
  398. zval_ptr_dtor(&arg1);
  399. } else {
  400. spl_filesystem_info_set_filename(intern, file_path, file_path_len, use_copy);
  401. }
  402. zend_restore_error_handling(&error_handling);
  403. return intern;
  404. } /* }}} */
  405. static spl_filesystem_object *spl_filesystem_object_create_type(int num_args, spl_filesystem_object *source, int type, zend_class_entry *ce, zval *return_value) /* {{{ */
  406. {
  407. spl_filesystem_object *intern;
  408. zend_bool use_include_path = 0;
  409. zval arg1, arg2;
  410. zend_error_handling error_handling;
  411. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
  412. switch (source->type) {
  413. case SPL_FS_INFO:
  414. case SPL_FS_FILE:
  415. break;
  416. case SPL_FS_DIR:
  417. if (!source->u.dir.entry.d_name[0]) {
  418. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Could not open file");
  419. zend_restore_error_handling(&error_handling);
  420. return NULL;
  421. }
  422. }
  423. switch (type) {
  424. case SPL_FS_INFO:
  425. ce = ce ? ce : source->info_class;
  426. if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
  427. break;
  428. }
  429. intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
  430. ZVAL_OBJ(return_value, &intern->std);
  431. spl_filesystem_object_get_file_name(source);
  432. if (ce->constructor->common.scope != spl_ce_SplFileInfo) {
  433. ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
  434. zend_call_method_with_1_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1);
  435. zval_ptr_dtor(&arg1);
  436. } else {
  437. intern->file_name = estrndup(source->file_name, source->file_name_len);
  438. intern->file_name_len = source->file_name_len;
  439. intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
  440. intern->_path = estrndup(intern->_path, intern->_path_len);
  441. }
  442. break;
  443. case SPL_FS_FILE:
  444. {
  445. ce = ce ? ce : source->file_class;
  446. if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
  447. break;
  448. }
  449. char *open_mode = "r";
  450. size_t open_mode_len = 1;
  451. zval *resource = NULL;
  452. if (zend_parse_parameters(num_args, "|sbr",
  453. &open_mode, &open_mode_len, &use_include_path, &resource) == FAILURE
  454. ) {
  455. zend_restore_error_handling(&error_handling);
  456. return NULL;
  457. }
  458. intern = spl_filesystem_from_obj(spl_filesystem_object_new_ex(ce));
  459. ZVAL_OBJ(return_value, &intern->std);
  460. spl_filesystem_object_get_file_name(source);
  461. if (ce->constructor->common.scope != spl_ce_SplFileObject) {
  462. ZVAL_STRINGL(&arg1, source->file_name, source->file_name_len);
  463. ZVAL_STRINGL(&arg2, open_mode, open_mode_len);
  464. zend_call_method_with_2_params(Z_OBJ_P(return_value), ce, &ce->constructor, "__construct", NULL, &arg1, &arg2);
  465. zval_ptr_dtor(&arg1);
  466. zval_ptr_dtor(&arg2);
  467. } else {
  468. intern->file_name = source->file_name;
  469. intern->file_name_len = source->file_name_len;
  470. intern->_path = spl_filesystem_object_get_path(source, &intern->_path_len);
  471. intern->_path = estrndup(intern->_path, intern->_path_len);
  472. intern->u.file.open_mode = open_mode;
  473. intern->u.file.open_mode_len = open_mode_len;
  474. intern->u.file.zcontext = resource;
  475. if (spl_filesystem_file_open(intern, use_include_path, 0) == FAILURE) {
  476. zend_restore_error_handling(&error_handling);
  477. zval_ptr_dtor(return_value);
  478. ZVAL_NULL(return_value);
  479. return NULL;
  480. }
  481. }
  482. break;
  483. }
  484. case SPL_FS_DIR:
  485. zend_restore_error_handling(&error_handling);
  486. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Operation not supported");
  487. return NULL;
  488. }
  489. zend_restore_error_handling(&error_handling);
  490. return NULL;
  491. } /* }}} */
  492. static int spl_filesystem_is_invalid_or_dot(const char * d_name) /* {{{ */
  493. {
  494. return d_name[0] == '\0' || spl_filesystem_is_dot(d_name);
  495. }
  496. /* }}} */
  497. static char *spl_filesystem_object_get_pathname(spl_filesystem_object *intern, size_t *len) { /* {{{ */
  498. switch (intern->type) {
  499. case SPL_FS_INFO:
  500. case SPL_FS_FILE:
  501. *len = intern->file_name_len;
  502. return intern->file_name;
  503. case SPL_FS_DIR:
  504. if (intern->u.dir.entry.d_name[0]) {
  505. spl_filesystem_object_get_file_name(intern);
  506. *len = intern->file_name_len;
  507. return intern->file_name;
  508. }
  509. }
  510. *len = 0;
  511. return NULL;
  512. }
  513. /* }}} */
  514. static inline HashTable *spl_filesystem_object_get_debug_info(zend_object *object) /* {{{ */
  515. {
  516. spl_filesystem_object *intern = spl_filesystem_from_obj(object);
  517. zval tmp;
  518. HashTable *rv;
  519. zend_string *pnstr;
  520. char *path;
  521. size_t path_len;
  522. char stmp[2];
  523. if (!intern->std.properties) {
  524. rebuild_object_properties(&intern->std);
  525. }
  526. rv = zend_array_dup(intern->std.properties);
  527. pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "pathName", sizeof("pathName")-1);
  528. path = spl_filesystem_object_get_pathname(intern, &path_len);
  529. ZVAL_STRINGL(&tmp, path ? path : "", path_len);
  530. zend_symtable_update(rv, pnstr, &tmp);
  531. zend_string_release_ex(pnstr, 0);
  532. if (intern->file_name) {
  533. pnstr = spl_gen_private_prop_name(spl_ce_SplFileInfo, "fileName", sizeof("fileName")-1);
  534. spl_filesystem_object_get_path(intern, &path_len);
  535. if (path_len && path_len < intern->file_name_len) {
  536. ZVAL_STRINGL(&tmp, intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
  537. } else {
  538. ZVAL_STRINGL(&tmp, intern->file_name, intern->file_name_len);
  539. }
  540. zend_symtable_update(rv, pnstr, &tmp);
  541. zend_string_release_ex(pnstr, 0);
  542. }
  543. if (intern->type == SPL_FS_DIR) {
  544. #ifdef HAVE_GLOB
  545. pnstr = spl_gen_private_prop_name(spl_ce_DirectoryIterator, "glob", sizeof("glob")-1);
  546. if (php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
  547. ZVAL_STRINGL(&tmp, intern->_path, intern->_path_len);
  548. } else {
  549. ZVAL_FALSE(&tmp);
  550. }
  551. zend_symtable_update(rv, pnstr, &tmp);
  552. zend_string_release_ex(pnstr, 0);
  553. #endif
  554. pnstr = spl_gen_private_prop_name(spl_ce_RecursiveDirectoryIterator, "subPathName", sizeof("subPathName")-1);
  555. if (intern->u.dir.sub_path) {
  556. ZVAL_STRINGL(&tmp, intern->u.dir.sub_path, intern->u.dir.sub_path_len);
  557. } else {
  558. ZVAL_EMPTY_STRING(&tmp);
  559. }
  560. zend_symtable_update(rv, pnstr, &tmp);
  561. zend_string_release_ex(pnstr, 0);
  562. }
  563. if (intern->type == SPL_FS_FILE) {
  564. pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "openMode", sizeof("openMode")-1);
  565. ZVAL_STRINGL(&tmp, intern->u.file.open_mode, intern->u.file.open_mode_len);
  566. zend_symtable_update(rv, pnstr, &tmp);
  567. zend_string_release_ex(pnstr, 0);
  568. stmp[1] = '\0';
  569. stmp[0] = intern->u.file.delimiter;
  570. pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "delimiter", sizeof("delimiter")-1);
  571. ZVAL_STRINGL(&tmp, stmp, 1);
  572. zend_symtable_update(rv, pnstr, &tmp);
  573. zend_string_release_ex(pnstr, 0);
  574. stmp[0] = intern->u.file.enclosure;
  575. pnstr = spl_gen_private_prop_name(spl_ce_SplFileObject, "enclosure", sizeof("enclosure")-1);
  576. ZVAL_STRINGL(&tmp, stmp, 1);
  577. zend_symtable_update(rv, pnstr, &tmp);
  578. zend_string_release_ex(pnstr, 0);
  579. }
  580. return rv;
  581. }
  582. /* }}} */
  583. zend_function *spl_filesystem_object_get_method_check(zend_object **object, zend_string *method, const zval *key) /* {{{ */
  584. {
  585. spl_filesystem_object *fsobj = spl_filesystem_from_obj(*object);
  586. if (fsobj->u.dir.dirp == NULL && fsobj->orig_path == NULL) {
  587. zend_function *func;
  588. zend_string *tmp = zend_string_init("_bad_state_ex", sizeof("_bad_state_ex") - 1, 0);
  589. func = zend_std_get_method(object, tmp, NULL);
  590. zend_string_release_ex(tmp, 0);
  591. return func;
  592. }
  593. return zend_std_get_method(object, method, key);
  594. }
  595. /* }}} */
  596. #define DIT_CTOR_FLAGS 0x00000001
  597. #define DIT_CTOR_GLOB 0x00000002
  598. void spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAMETERS, zend_long ctor_flags) /* {{{ */
  599. {
  600. spl_filesystem_object *intern;
  601. char *path;
  602. int parsed;
  603. size_t len;
  604. zend_long flags;
  605. zend_error_handling error_handling;
  606. if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_FLAGS)) {
  607. flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO;
  608. parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &path, &len, &flags);
  609. } else {
  610. flags = SPL_FILE_DIR_KEY_AS_PATHNAME|SPL_FILE_DIR_CURRENT_AS_SELF;
  611. parsed = zend_parse_parameters(ZEND_NUM_ARGS(), "p", &path, &len);
  612. }
  613. if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_SKIPDOTS)) {
  614. flags |= SPL_FILE_DIR_SKIPDOTS;
  615. }
  616. if (SPL_HAS_FLAG(ctor_flags, SPL_FILE_DIR_UNIXPATHS)) {
  617. flags |= SPL_FILE_DIR_UNIXPATHS;
  618. }
  619. if (parsed == FAILURE) {
  620. return;
  621. }
  622. if (!len) {
  623. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Directory name must not be empty.");
  624. return;
  625. }
  626. intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  627. if (intern->_path) {
  628. /* object is already initialized */
  629. php_error_docref(NULL, E_WARNING, "Directory object is already initialized");
  630. return;
  631. }
  632. intern->flags = flags;
  633. zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
  634. #ifdef HAVE_GLOB
  635. if (SPL_HAS_FLAG(ctor_flags, DIT_CTOR_GLOB) && strstr(path, "glob://") != path) {
  636. spprintf(&path, 0, "glob://%s", path);
  637. spl_filesystem_dir_open(intern, path);
  638. efree(path);
  639. } else
  640. #endif
  641. {
  642. spl_filesystem_dir_open(intern, path);
  643. }
  644. intern->u.dir.is_recursive = instanceof_function(intern->std.ce, spl_ce_RecursiveDirectoryIterator) ? 1 : 0;
  645. zend_restore_error_handling(&error_handling);
  646. }
  647. /* }}} */
  648. /* {{{ proto DirectoryIterator::__construct(string path)
  649. Cronstructs a new dir iterator from a path. */
  650. PHP_METHOD(DirectoryIterator, __construct)
  651. {
  652. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  653. }
  654. /* }}} */
  655. /* {{{ proto void DirectoryIterator::rewind()
  656. Rewind dir back to the start */
  657. PHP_METHOD(DirectoryIterator, rewind)
  658. {
  659. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  660. if (zend_parse_parameters_none() == FAILURE) {
  661. RETURN_THROWS();
  662. }
  663. intern->u.dir.index = 0;
  664. if (intern->u.dir.dirp) {
  665. php_stream_rewinddir(intern->u.dir.dirp);
  666. }
  667. spl_filesystem_dir_read(intern);
  668. }
  669. /* }}} */
  670. /* {{{ proto string DirectoryIterator::key()
  671. Return current dir entry */
  672. PHP_METHOD(DirectoryIterator, key)
  673. {
  674. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  675. if (zend_parse_parameters_none() == FAILURE) {
  676. RETURN_THROWS();
  677. }
  678. if (intern->u.dir.dirp) {
  679. RETURN_LONG(intern->u.dir.index);
  680. } else {
  681. RETURN_FALSE;
  682. }
  683. }
  684. /* }}} */
  685. /* {{{ proto DirectoryIterator DirectoryIterator::current()
  686. Return this (needed for Iterator interface) */
  687. PHP_METHOD(DirectoryIterator, current)
  688. {
  689. if (zend_parse_parameters_none() == FAILURE) {
  690. RETURN_THROWS();
  691. }
  692. ZVAL_OBJ(return_value, Z_OBJ_P(ZEND_THIS));
  693. Z_ADDREF_P(return_value);
  694. }
  695. /* }}} */
  696. /* {{{ proto void DirectoryIterator::next()
  697. Move to next entry */
  698. PHP_METHOD(DirectoryIterator, next)
  699. {
  700. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  701. int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
  702. if (zend_parse_parameters_none() == FAILURE) {
  703. RETURN_THROWS();
  704. }
  705. intern->u.dir.index++;
  706. do {
  707. spl_filesystem_dir_read(intern);
  708. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  709. if (intern->file_name) {
  710. efree(intern->file_name);
  711. intern->file_name = NULL;
  712. }
  713. }
  714. /* }}} */
  715. /* {{{ proto void DirectoryIterator::seek(int position)
  716. Seek to the given position */
  717. PHP_METHOD(DirectoryIterator, seek)
  718. {
  719. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  720. zval retval;
  721. zend_long pos;
  722. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &pos) == FAILURE) {
  723. RETURN_THROWS();
  724. }
  725. if (intern->u.dir.index > pos) {
  726. /* we first rewind */
  727. zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_rewind, "rewind", NULL);
  728. }
  729. while (intern->u.dir.index < pos) {
  730. int valid = 0;
  731. zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_valid, "valid", &retval);
  732. valid = zend_is_true(&retval);
  733. zval_ptr_dtor(&retval);
  734. if (!valid) {
  735. zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position " ZEND_LONG_FMT " is out of range", pos);
  736. RETURN_THROWS();
  737. }
  738. zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_next, "next", NULL);
  739. }
  740. } /* }}} */
  741. /* {{{ proto string DirectoryIterator::valid()
  742. Check whether dir contains more entries */
  743. PHP_METHOD(DirectoryIterator, valid)
  744. {
  745. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  746. if (zend_parse_parameters_none() == FAILURE) {
  747. RETURN_THROWS();
  748. }
  749. RETURN_BOOL(intern->u.dir.entry.d_name[0] != '\0');
  750. }
  751. /* }}} */
  752. /* {{{ proto string SplFileInfo::getPath()
  753. Return the path */
  754. PHP_METHOD(SplFileInfo, getPath)
  755. {
  756. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  757. char *path;
  758. size_t path_len;
  759. if (zend_parse_parameters_none() == FAILURE) {
  760. RETURN_THROWS();
  761. }
  762. path = spl_filesystem_object_get_path(intern, &path_len);
  763. if (path) {
  764. RETURN_STRINGL(path, path_len);
  765. } else {
  766. RETURN_EMPTY_STRING();
  767. }
  768. }
  769. /* }}} */
  770. /* {{{ proto string SplFileInfo::getFilename()
  771. Return filename only */
  772. PHP_METHOD(SplFileInfo, getFilename)
  773. {
  774. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  775. size_t path_len;
  776. if (zend_parse_parameters_none() == FAILURE) {
  777. RETURN_THROWS();
  778. }
  779. spl_filesystem_object_get_path(intern, &path_len);
  780. if (path_len && path_len < intern->file_name_len) {
  781. RETURN_STRINGL(intern->file_name + path_len + 1, intern->file_name_len - (path_len + 1));
  782. } else {
  783. RETURN_STRINGL(intern->file_name, intern->file_name_len);
  784. }
  785. }
  786. /* }}} */
  787. /* {{{ proto string DirectoryIterator::getFilename()
  788. Return filename of current dir entry */
  789. PHP_METHOD(DirectoryIterator, getFilename)
  790. {
  791. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  792. if (zend_parse_parameters_none() == FAILURE) {
  793. RETURN_THROWS();
  794. }
  795. RETURN_STRING(intern->u.dir.entry.d_name);
  796. }
  797. /* }}} */
  798. /* {{{ proto string SplFileInfo::getExtension()
  799. Returns file extension component of path */
  800. PHP_METHOD(SplFileInfo, getExtension)
  801. {
  802. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  803. char *fname = NULL;
  804. const char *p;
  805. size_t flen;
  806. size_t path_len;
  807. size_t idx;
  808. zend_string *ret;
  809. if (zend_parse_parameters_none() == FAILURE) {
  810. RETURN_THROWS();
  811. }
  812. spl_filesystem_object_get_path(intern, &path_len);
  813. if (path_len && path_len < intern->file_name_len) {
  814. fname = intern->file_name + path_len + 1;
  815. flen = intern->file_name_len - (path_len + 1);
  816. } else {
  817. fname = intern->file_name;
  818. flen = intern->file_name_len;
  819. }
  820. ret = php_basename(fname, flen, NULL, 0);
  821. p = zend_memrchr(ZSTR_VAL(ret), '.', ZSTR_LEN(ret));
  822. if (p) {
  823. idx = p - ZSTR_VAL(ret);
  824. RETVAL_STRINGL(ZSTR_VAL(ret) + idx + 1, ZSTR_LEN(ret) - idx - 1);
  825. zend_string_release_ex(ret, 0);
  826. return;
  827. } else {
  828. zend_string_release_ex(ret, 0);
  829. RETURN_EMPTY_STRING();
  830. }
  831. }
  832. /* }}}*/
  833. /* {{{ proto string DirectoryIterator::getExtension()
  834. Returns the file extension component of path */
  835. PHP_METHOD(DirectoryIterator, getExtension)
  836. {
  837. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  838. const char *p;
  839. size_t idx;
  840. zend_string *fname;
  841. if (zend_parse_parameters_none() == FAILURE) {
  842. RETURN_THROWS();
  843. }
  844. fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), NULL, 0);
  845. p = zend_memrchr(ZSTR_VAL(fname), '.', ZSTR_LEN(fname));
  846. if (p) {
  847. idx = p - ZSTR_VAL(fname);
  848. RETVAL_STRINGL(ZSTR_VAL(fname) + idx + 1, ZSTR_LEN(fname) - idx - 1);
  849. zend_string_release_ex(fname, 0);
  850. } else {
  851. zend_string_release_ex(fname, 0);
  852. RETURN_EMPTY_STRING();
  853. }
  854. }
  855. /* }}} */
  856. /* {{{ proto string SplFileInfo::getBasename([string $suffix])
  857. Returns filename component of path */
  858. PHP_METHOD(SplFileInfo, getBasename)
  859. {
  860. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  861. char *fname, *suffix = 0;
  862. size_t flen;
  863. size_t slen = 0, path_len;
  864. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
  865. RETURN_THROWS();
  866. }
  867. spl_filesystem_object_get_path(intern, &path_len);
  868. if (path_len && path_len < intern->file_name_len) {
  869. fname = intern->file_name + path_len + 1;
  870. flen = intern->file_name_len - (path_len + 1);
  871. } else {
  872. fname = intern->file_name;
  873. flen = intern->file_name_len;
  874. }
  875. RETURN_STR(php_basename(fname, flen, suffix, slen));
  876. }
  877. /* }}}*/
  878. /* {{{ proto string DirectoryIterator::getBasename([string $suffix])
  879. Returns filename component of current dir entry */
  880. PHP_METHOD(DirectoryIterator, getBasename)
  881. {
  882. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  883. char *suffix = 0;
  884. size_t slen = 0;
  885. zend_string *fname;
  886. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &suffix, &slen) == FAILURE) {
  887. RETURN_THROWS();
  888. }
  889. fname = php_basename(intern->u.dir.entry.d_name, strlen(intern->u.dir.entry.d_name), suffix, slen);
  890. RETVAL_STR(fname);
  891. }
  892. /* }}} */
  893. /* {{{ proto string SplFileInfo::getPathname()
  894. Return path and filename */
  895. PHP_METHOD(SplFileInfo, getPathname)
  896. {
  897. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  898. char *path;
  899. size_t path_len;
  900. if (zend_parse_parameters_none() == FAILURE) {
  901. RETURN_THROWS();
  902. }
  903. path = spl_filesystem_object_get_pathname(intern, &path_len);
  904. if (path != NULL) {
  905. RETURN_STRINGL(path, path_len);
  906. } else {
  907. RETURN_FALSE;
  908. }
  909. }
  910. /* }}} */
  911. /* {{{ proto string FilesystemIterator::key()
  912. Return getPathname() or getFilename() depending on flags */
  913. PHP_METHOD(FilesystemIterator, key)
  914. {
  915. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  916. if (zend_parse_parameters_none() == FAILURE) {
  917. RETURN_THROWS();
  918. }
  919. if (SPL_FILE_DIR_KEY(intern, SPL_FILE_DIR_KEY_AS_FILENAME)) {
  920. RETURN_STRING(intern->u.dir.entry.d_name);
  921. } else {
  922. spl_filesystem_object_get_file_name(intern);
  923. RETURN_STRINGL(intern->file_name, intern->file_name_len);
  924. }
  925. }
  926. /* }}} */
  927. /* {{{ proto string FilesystemIterator::current()
  928. Return getFilename(), getFileInfo() or $this depending on flags */
  929. PHP_METHOD(FilesystemIterator, current)
  930. {
  931. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  932. if (zend_parse_parameters_none() == FAILURE) {
  933. RETURN_THROWS();
  934. }
  935. if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
  936. spl_filesystem_object_get_file_name(intern);
  937. RETURN_STRINGL(intern->file_name, intern->file_name_len);
  938. } else if (SPL_FILE_DIR_CURRENT(intern, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
  939. spl_filesystem_object_get_file_name(intern);
  940. spl_filesystem_object_create_type(0, intern, SPL_FS_INFO, NULL, return_value);
  941. } else {
  942. ZVAL_OBJ(return_value, Z_OBJ_P(ZEND_THIS));
  943. Z_ADDREF_P(return_value);
  944. }
  945. }
  946. /* }}} */
  947. /* {{{ proto bool DirectoryIterator::isDot()
  948. Returns true if current entry is '.' or '..' */
  949. PHP_METHOD(DirectoryIterator, isDot)
  950. {
  951. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  952. if (zend_parse_parameters_none() == FAILURE) {
  953. RETURN_THROWS();
  954. }
  955. RETURN_BOOL(spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  956. }
  957. /* }}} */
  958. /* {{{ proto SplFileInfo::__construct(string file_name)
  959. Cronstructs a new SplFileInfo from a path. */
  960. /* When the constructor gets called the object is already created
  961. by the engine, so we must only call 'additional' initializations.
  962. */
  963. PHP_METHOD(SplFileInfo, __construct)
  964. {
  965. spl_filesystem_object *intern;
  966. char *path;
  967. size_t len;
  968. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &path, &len) == FAILURE) {
  969. RETURN_THROWS();
  970. }
  971. intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  972. spl_filesystem_info_set_filename(intern, path, len, 1);
  973. /* intern->type = SPL_FS_INFO; already set */
  974. }
  975. /* }}} */
  976. /* {{{ FileInfoFunction */
  977. #define FileInfoFunction(func_name, func_num) \
  978. PHP_METHOD(SplFileInfo, func_name) \
  979. { \
  980. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); \
  981. zend_error_handling error_handling; \
  982. if (zend_parse_parameters_none() == FAILURE) { \
  983. RETURN_THROWS(); \
  984. } \
  985. \
  986. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);\
  987. spl_filesystem_object_get_file_name(intern); \
  988. php_stat(intern->file_name, intern->file_name_len, func_num, return_value); \
  989. zend_restore_error_handling(&error_handling); \
  990. }
  991. /* }}} */
  992. /* {{{ proto int SplFileInfo::getPerms()
  993. Get file permissions */
  994. FileInfoFunction(getPerms, FS_PERMS)
  995. /* }}} */
  996. /* {{{ proto int SplFileInfo::getInode()
  997. Get file inode */
  998. FileInfoFunction(getInode, FS_INODE)
  999. /* }}} */
  1000. /* {{{ proto int SplFileInfo::getSize()
  1001. Get file size */
  1002. FileInfoFunction(getSize, FS_SIZE)
  1003. /* }}} */
  1004. /* {{{ proto int SplFileInfo::getOwner()
  1005. Get file owner */
  1006. FileInfoFunction(getOwner, FS_OWNER)
  1007. /* }}} */
  1008. /* {{{ proto int SplFileInfo::getGroup()
  1009. Get file group */
  1010. FileInfoFunction(getGroup, FS_GROUP)
  1011. /* }}} */
  1012. /* {{{ proto int SplFileInfo::getATime()
  1013. Get last access time of file */
  1014. FileInfoFunction(getATime, FS_ATIME)
  1015. /* }}} */
  1016. /* {{{ proto int SplFileInfo::getMTime()
  1017. Get last modification time of file */
  1018. FileInfoFunction(getMTime, FS_MTIME)
  1019. /* }}} */
  1020. /* {{{ proto int SplFileInfo::getCTime()
  1021. Get inode modification time of file */
  1022. FileInfoFunction(getCTime, FS_CTIME)
  1023. /* }}} */
  1024. /* {{{ proto string SplFileInfo::getType()
  1025. Get file type */
  1026. FileInfoFunction(getType, FS_TYPE)
  1027. /* }}} */
  1028. /* {{{ proto bool SplFileInfo::isWritable()
  1029. Returns true if file can be written */
  1030. FileInfoFunction(isWritable, FS_IS_W)
  1031. /* }}} */
  1032. /* {{{ proto bool SplFileInfo::isReadable()
  1033. Returns true if file can be read */
  1034. FileInfoFunction(isReadable, FS_IS_R)
  1035. /* }}} */
  1036. /* {{{ proto bool SplFileInfo::isExecutable()
  1037. Returns true if file is executable */
  1038. FileInfoFunction(isExecutable, FS_IS_X)
  1039. /* }}} */
  1040. /* {{{ proto bool SplFileInfo::isFile()
  1041. Returns true if file is a regular file */
  1042. FileInfoFunction(isFile, FS_IS_FILE)
  1043. /* }}} */
  1044. /* {{{ proto bool SplFileInfo::isDir()
  1045. Returns true if file is directory */
  1046. FileInfoFunction(isDir, FS_IS_DIR)
  1047. /* }}} */
  1048. /* {{{ proto bool SplFileInfo::isLink()
  1049. Returns true if file is symbolic link */
  1050. FileInfoFunction(isLink, FS_IS_LINK)
  1051. /* }}} */
  1052. /* {{{ proto string SplFileInfo::getLinkTarget()
  1053. Return the target of a symbolic link */
  1054. PHP_METHOD(SplFileInfo, getLinkTarget)
  1055. {
  1056. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1057. ssize_t ret;
  1058. char buff[MAXPATHLEN];
  1059. zend_error_handling error_handling;
  1060. if (zend_parse_parameters_none() == FAILURE) {
  1061. RETURN_THROWS();
  1062. }
  1063. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
  1064. if (intern->file_name == NULL) {
  1065. spl_filesystem_object_get_file_name(intern);
  1066. }
  1067. #if defined(PHP_WIN32) || HAVE_SYMLINK
  1068. if (intern->file_name == NULL) {
  1069. php_error_docref(NULL, E_WARNING, "Empty filename");
  1070. RETURN_FALSE;
  1071. } else if (!IS_ABSOLUTE_PATH(intern->file_name, intern->file_name_len)) {
  1072. char expanded_path[MAXPATHLEN];
  1073. if (!expand_filepath_with_mode(intern->file_name, expanded_path, NULL, 0, CWD_EXPAND )) {
  1074. php_error_docref(NULL, E_WARNING, "No such file or directory");
  1075. RETURN_FALSE;
  1076. }
  1077. ret = php_sys_readlink(expanded_path, buff, MAXPATHLEN - 1);
  1078. } else {
  1079. ret = php_sys_readlink(intern->file_name, buff, MAXPATHLEN-1);
  1080. }
  1081. #else
  1082. ret = -1; /* always fail if not implemented */
  1083. #endif
  1084. if (ret == -1) {
  1085. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Unable to read link %s, error: %s", intern->file_name, strerror(errno));
  1086. RETVAL_FALSE;
  1087. } else {
  1088. /* Append NULL to the end of the string */
  1089. buff[ret] = '\0';
  1090. RETVAL_STRINGL(buff, ret);
  1091. }
  1092. zend_restore_error_handling(&error_handling);
  1093. }
  1094. /* }}} */
  1095. /* {{{ proto string SplFileInfo::getRealPath()
  1096. Return the resolved path */
  1097. PHP_METHOD(SplFileInfo, getRealPath)
  1098. {
  1099. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1100. char buff[MAXPATHLEN];
  1101. char *filename;
  1102. zend_error_handling error_handling;
  1103. if (zend_parse_parameters_none() == FAILURE) {
  1104. RETURN_THROWS();
  1105. }
  1106. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
  1107. if (intern->type == SPL_FS_DIR && !intern->file_name && intern->u.dir.entry.d_name[0]) {
  1108. spl_filesystem_object_get_file_name(intern);
  1109. }
  1110. if (intern->orig_path) {
  1111. filename = intern->orig_path;
  1112. } else {
  1113. filename = intern->file_name;
  1114. }
  1115. if (filename && VCWD_REALPATH(filename, buff)) {
  1116. #ifdef ZTS
  1117. if (VCWD_ACCESS(buff, F_OK)) {
  1118. RETVAL_FALSE;
  1119. } else
  1120. #endif
  1121. RETVAL_STRING(buff);
  1122. } else {
  1123. RETVAL_FALSE;
  1124. }
  1125. zend_restore_error_handling(&error_handling);
  1126. }
  1127. /* }}} */
  1128. /* {{{ proto SplFileObject SplFileInfo::openFile([string mode = 'r' [, bool use_include_path [, resource context]]])
  1129. Open the current file */
  1130. PHP_METHOD(SplFileInfo, openFile)
  1131. {
  1132. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1133. spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_FILE, NULL, return_value);
  1134. }
  1135. /* }}} */
  1136. /* {{{ proto void SplFileInfo::setFileClass([string class_name])
  1137. Class to use in openFile() */
  1138. PHP_METHOD(SplFileInfo, setFileClass)
  1139. {
  1140. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1141. zend_class_entry *ce = spl_ce_SplFileObject;
  1142. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
  1143. RETURN_THROWS();
  1144. }
  1145. intern->file_class = ce;
  1146. }
  1147. /* }}} */
  1148. /* {{{ proto void SplFileInfo::setInfoClass([string class_name])
  1149. Class to use in getFileInfo(), getPathInfo() */
  1150. PHP_METHOD(SplFileInfo, setInfoClass)
  1151. {
  1152. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1153. zend_class_entry *ce = spl_ce_SplFileInfo;
  1154. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
  1155. RETURN_THROWS();
  1156. }
  1157. intern->info_class = ce;
  1158. }
  1159. /* }}} */
  1160. /* {{{ proto SplFileInfo SplFileInfo::getFileInfo([string $class_name])
  1161. Get/copy file info */
  1162. PHP_METHOD(SplFileInfo, getFileInfo)
  1163. {
  1164. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1165. zend_class_entry *ce = intern->info_class;
  1166. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
  1167. RETURN_THROWS();
  1168. }
  1169. spl_filesystem_object_create_type(ZEND_NUM_ARGS(), intern, SPL_FS_INFO, ce, return_value);
  1170. }
  1171. /* }}} */
  1172. /* {{{ proto SplFileInfo SplFileInfo::getPathInfo([string $class_name])
  1173. Get/copy file info */
  1174. PHP_METHOD(SplFileInfo, getPathInfo)
  1175. {
  1176. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1177. zend_class_entry *ce = intern->info_class;
  1178. size_t path_len;
  1179. char *path;
  1180. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|C", &ce) == FAILURE) {
  1181. RETURN_THROWS();
  1182. }
  1183. path = spl_filesystem_object_get_pathname(intern, &path_len);
  1184. if (path) {
  1185. char *dpath = estrndup(path, path_len);
  1186. path_len = php_dirname(dpath, path_len);
  1187. spl_filesystem_object_create_info(intern, dpath, path_len, 1, ce, return_value);
  1188. efree(dpath);
  1189. }
  1190. }
  1191. /* }}} */
  1192. /* {{{ proto void SplFileInfo::__debugInfo() */
  1193. PHP_METHOD(SplFileInfo, __debugInfo)
  1194. {
  1195. if (zend_parse_parameters_none() == FAILURE) {
  1196. return;
  1197. }
  1198. RETURN_ARR(spl_filesystem_object_get_debug_info(Z_OBJ_P(ZEND_THIS)));
  1199. } /* }}} */
  1200. /* {{{ proto SplFileInfo::_bad_state_ex(void) */
  1201. PHP_METHOD(SplFileInfo, _bad_state_ex)
  1202. {
  1203. zend_throw_exception_ex(spl_ce_LogicException, 0,
  1204. "The parent constructor was not called: the object is in an "
  1205. "invalid state ");
  1206. }
  1207. /* }}} */
  1208. /* {{{ proto FilesystemIterator::__construct(string path [, int flags])
  1209. Cronstructs a new dir iterator from a path. */
  1210. PHP_METHOD(FilesystemIterator, __construct)
  1211. {
  1212. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS | SPL_FILE_DIR_SKIPDOTS);
  1213. }
  1214. /* }}} */
  1215. /* {{{ proto void FilesystemIterator::rewind()
  1216. Rewind dir back to the start */
  1217. PHP_METHOD(FilesystemIterator, rewind)
  1218. {
  1219. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1220. int skip_dots = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_SKIPDOTS);
  1221. if (zend_parse_parameters_none() == FAILURE) {
  1222. RETURN_THROWS();
  1223. }
  1224. intern->u.dir.index = 0;
  1225. if (intern->u.dir.dirp) {
  1226. php_stream_rewinddir(intern->u.dir.dirp);
  1227. }
  1228. do {
  1229. spl_filesystem_dir_read(intern);
  1230. } while (skip_dots && spl_filesystem_is_dot(intern->u.dir.entry.d_name));
  1231. }
  1232. /* }}} */
  1233. /* {{{ proto int FilesystemIterator::getFlags()
  1234. Get handling flags */
  1235. PHP_METHOD(FilesystemIterator, getFlags)
  1236. {
  1237. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1238. if (zend_parse_parameters_none() == FAILURE) {
  1239. RETURN_THROWS();
  1240. }
  1241. RETURN_LONG(intern->flags & (SPL_FILE_DIR_KEY_MODE_MASK | SPL_FILE_DIR_CURRENT_MODE_MASK | SPL_FILE_DIR_OTHERS_MASK));
  1242. } /* }}} */
  1243. /* {{{ proto void FilesystemIterator::setFlags(long $flags)
  1244. Set handling flags */
  1245. PHP_METHOD(FilesystemIterator, setFlags)
  1246. {
  1247. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1248. zend_long flags;
  1249. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &flags) == FAILURE) {
  1250. RETURN_THROWS();
  1251. }
  1252. intern->flags &= ~(SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK);
  1253. intern->flags |= ((SPL_FILE_DIR_KEY_MODE_MASK|SPL_FILE_DIR_CURRENT_MODE_MASK|SPL_FILE_DIR_OTHERS_MASK) & flags);
  1254. } /* }}} */
  1255. /* {{{ proto bool RecursiveDirectoryIterator::hasChildren([bool $allow_links = false])
  1256. Returns whether current entry is a directory and not '.' or '..' */
  1257. PHP_METHOD(RecursiveDirectoryIterator, hasChildren)
  1258. {
  1259. zend_bool allow_links = 0;
  1260. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1261. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &allow_links) == FAILURE) {
  1262. RETURN_THROWS();
  1263. }
  1264. if (spl_filesystem_is_invalid_or_dot(intern->u.dir.entry.d_name)) {
  1265. RETURN_FALSE;
  1266. } else {
  1267. spl_filesystem_object_get_file_name(intern);
  1268. if (!allow_links && !(intern->flags & SPL_FILE_DIR_FOLLOW_SYMLINKS)) {
  1269. php_stat(intern->file_name, intern->file_name_len, FS_IS_LINK, return_value);
  1270. if (zend_is_true(return_value)) {
  1271. RETURN_FALSE;
  1272. }
  1273. }
  1274. php_stat(intern->file_name, intern->file_name_len, FS_IS_DIR, return_value);
  1275. }
  1276. }
  1277. /* }}} */
  1278. /* {{{ proto RecursiveDirectoryIterator DirectoryIterator::getChildren()
  1279. Returns an iterator for the current entry if it is a directory */
  1280. PHP_METHOD(RecursiveDirectoryIterator, getChildren)
  1281. {
  1282. zval zpath, zflags;
  1283. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1284. spl_filesystem_object *subdir;
  1285. char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
  1286. if (zend_parse_parameters_none() == FAILURE) {
  1287. RETURN_THROWS();
  1288. }
  1289. spl_filesystem_object_get_file_name(intern);
  1290. ZVAL_LONG(&zflags, intern->flags);
  1291. ZVAL_STRINGL(&zpath, intern->file_name, intern->file_name_len);
  1292. spl_instantiate_arg_ex2(Z_OBJCE_P(ZEND_THIS), return_value, &zpath, &zflags);
  1293. zval_ptr_dtor(&zpath);
  1294. subdir = Z_SPLFILESYSTEM_P(return_value);
  1295. if (subdir) {
  1296. if (intern->u.dir.sub_path && intern->u.dir.sub_path[0]) {
  1297. subdir->u.dir.sub_path_len = spprintf(&subdir->u.dir.sub_path, 0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name);
  1298. } else {
  1299. subdir->u.dir.sub_path_len = strlen(intern->u.dir.entry.d_name);
  1300. subdir->u.dir.sub_path = estrndup(intern->u.dir.entry.d_name, subdir->u.dir.sub_path_len);
  1301. }
  1302. subdir->info_class = intern->info_class;
  1303. subdir->file_class = intern->file_class;
  1304. subdir->oth = intern->oth;
  1305. }
  1306. }
  1307. /* }}} */
  1308. /* {{{ proto void RecursiveDirectoryIterator::getSubPath()
  1309. Get sub path */
  1310. PHP_METHOD(RecursiveDirectoryIterator, getSubPath)
  1311. {
  1312. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1313. if (zend_parse_parameters_none() == FAILURE) {
  1314. RETURN_THROWS();
  1315. }
  1316. if (intern->u.dir.sub_path) {
  1317. RETURN_STRINGL(intern->u.dir.sub_path, intern->u.dir.sub_path_len);
  1318. } else {
  1319. RETURN_EMPTY_STRING();
  1320. }
  1321. }
  1322. /* }}} */
  1323. /* {{{ proto void RecursiveDirectoryIterator::getSubPathname()
  1324. Get sub path and file name */
  1325. PHP_METHOD(RecursiveDirectoryIterator, getSubPathname)
  1326. {
  1327. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1328. char slash = SPL_HAS_FLAG(intern->flags, SPL_FILE_DIR_UNIXPATHS) ? '/' : DEFAULT_SLASH;
  1329. if (zend_parse_parameters_none() == FAILURE) {
  1330. RETURN_THROWS();
  1331. }
  1332. if (intern->u.dir.sub_path) {
  1333. RETURN_NEW_STR(strpprintf(0, "%s%c%s", intern->u.dir.sub_path, slash, intern->u.dir.entry.d_name));
  1334. } else {
  1335. RETURN_STRING(intern->u.dir.entry.d_name);
  1336. }
  1337. }
  1338. /* }}} */
  1339. /* {{{ proto RecursiveDirectoryIterator::__construct(string path [, int flags])
  1340. Cronstructs a new dir iterator from a path. */
  1341. PHP_METHOD(RecursiveDirectoryIterator, __construct)
  1342. {
  1343. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS);
  1344. }
  1345. /* }}} */
  1346. #ifdef HAVE_GLOB
  1347. /* {{{ proto GlobIterator::__construct(string path [, int flags])
  1348. Cronstructs a new dir iterator from a glob expression (no glob:// needed). */
  1349. PHP_METHOD(GlobIterator, __construct)
  1350. {
  1351. spl_filesystem_object_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIT_CTOR_FLAGS|DIT_CTOR_GLOB);
  1352. }
  1353. /* }}} */
  1354. /* {{{ proto int GlobIterator::count()
  1355. Return the number of directories and files found by globbing */
  1356. PHP_METHOD(GlobIterator, count)
  1357. {
  1358. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1359. if (zend_parse_parameters_none() == FAILURE) {
  1360. RETURN_THROWS();
  1361. }
  1362. if (intern->u.dir.dirp && php_stream_is(intern->u.dir.dirp ,&php_glob_stream_ops)) {
  1363. RETURN_LONG(php_glob_stream_get_count(intern->u.dir.dirp, NULL));
  1364. } else {
  1365. /* should not happen */
  1366. php_error_docref(NULL, E_ERROR, "GlobIterator lost glob state");
  1367. }
  1368. }
  1369. /* }}} */
  1370. #endif /* HAVE_GLOB */
  1371. /* {{{ forward declarations to the iterator handlers */
  1372. static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter);
  1373. static int spl_filesystem_dir_it_valid(zend_object_iterator *iter);
  1374. static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter);
  1375. static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key);
  1376. static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter);
  1377. static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter);
  1378. /* iterator handler table */
  1379. static const zend_object_iterator_funcs spl_filesystem_dir_it_funcs = {
  1380. spl_filesystem_dir_it_dtor,
  1381. spl_filesystem_dir_it_valid,
  1382. spl_filesystem_dir_it_current_data,
  1383. spl_filesystem_dir_it_current_key,
  1384. spl_filesystem_dir_it_move_forward,
  1385. spl_filesystem_dir_it_rewind,
  1386. NULL
  1387. };
  1388. /* }}} */
  1389. /* {{{ spl_ce_dir_get_iterator */
  1390. zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
  1391. {
  1392. spl_filesystem_iterator *iterator;
  1393. spl_filesystem_object *dir_object;
  1394. if (by_ref) {
  1395. zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0);
  1396. return NULL;
  1397. }
  1398. dir_object = Z_SPLFILESYSTEM_P(object);
  1399. iterator = spl_filesystem_object_to_iterator(dir_object);
  1400. Z_ADDREF_P(object);
  1401. ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object));
  1402. iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
  1403. /* ->current must be initialized; rewind doesn't set it and valid
  1404. * doesn't check whether it's set */
  1405. iterator->current = *object;
  1406. return &iterator->intern;
  1407. }
  1408. /* }}} */
  1409. /* {{{ spl_filesystem_dir_it_dtor */
  1410. static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter)
  1411. {
  1412. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1413. if (!Z_ISUNDEF(iterator->intern.data)) {
  1414. zval *object = &iterator->intern.data;
  1415. zval_ptr_dtor(object);
  1416. }
  1417. /* Otherwise we were called from the owning object free storage handler as
  1418. * it sets iterator->intern.data to IS_UNDEF.
  1419. * We don't even need to destroy iterator->current as we didn't add a
  1420. * reference to it in move_forward or get_iterator */
  1421. }
  1422. /* }}} */
  1423. /* {{{ spl_filesystem_dir_it_valid */
  1424. static int spl_filesystem_dir_it_valid(zend_object_iterator *iter)
  1425. {
  1426. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1427. return object->u.dir.entry.d_name[0] != '\0' ? SUCCESS : FAILURE;
  1428. }
  1429. /* }}} */
  1430. /* {{{ spl_filesystem_dir_it_current_data */
  1431. static zval *spl_filesystem_dir_it_current_data(zend_object_iterator *iter)
  1432. {
  1433. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1434. return &iterator->current;
  1435. }
  1436. /* }}} */
  1437. /* {{{ spl_filesystem_dir_it_current_key */
  1438. static void spl_filesystem_dir_it_current_key(zend_object_iterator *iter, zval *key)
  1439. {
  1440. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1441. ZVAL_LONG(key, object->u.dir.index);
  1442. }
  1443. /* }}} */
  1444. /* {{{ spl_filesystem_dir_it_move_forward */
  1445. static void spl_filesystem_dir_it_move_forward(zend_object_iterator *iter)
  1446. {
  1447. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1448. object->u.dir.index++;
  1449. spl_filesystem_dir_read(object);
  1450. if (object->file_name) {
  1451. efree(object->file_name);
  1452. object->file_name = NULL;
  1453. }
  1454. }
  1455. /* }}} */
  1456. /* {{{ spl_filesystem_dir_it_rewind */
  1457. static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter)
  1458. {
  1459. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1460. object->u.dir.index = 0;
  1461. if (object->u.dir.dirp) {
  1462. php_stream_rewinddir(object->u.dir.dirp);
  1463. }
  1464. spl_filesystem_dir_read(object);
  1465. }
  1466. /* }}} */
  1467. /* {{{ spl_filesystem_tree_it_dtor */
  1468. static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter)
  1469. {
  1470. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1471. if (!Z_ISUNDEF(iterator->intern.data)) {
  1472. zval *object = &iterator->intern.data;
  1473. zval_ptr_dtor(object);
  1474. } else {
  1475. if (!Z_ISUNDEF(iterator->current)) {
  1476. zval_ptr_dtor(&iterator->current);
  1477. ZVAL_UNDEF(&iterator->current);
  1478. }
  1479. }
  1480. }
  1481. /* }}} */
  1482. /* {{{ spl_filesystem_tree_it_current_data */
  1483. static zval *spl_filesystem_tree_it_current_data(zend_object_iterator *iter)
  1484. {
  1485. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1486. spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator);
  1487. if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_PATHNAME)) {
  1488. if (Z_ISUNDEF(iterator->current)) {
  1489. spl_filesystem_object_get_file_name(object);
  1490. ZVAL_STRINGL(&iterator->current, object->file_name, object->file_name_len);
  1491. }
  1492. return &iterator->current;
  1493. } else if (SPL_FILE_DIR_CURRENT(object, SPL_FILE_DIR_CURRENT_AS_FILEINFO)) {
  1494. if (Z_ISUNDEF(iterator->current)) {
  1495. spl_filesystem_object_get_file_name(object);
  1496. spl_filesystem_object_create_type(0, object, SPL_FS_INFO, NULL, &iterator->current);
  1497. }
  1498. return &iterator->current;
  1499. } else {
  1500. return &iterator->intern.data;
  1501. }
  1502. }
  1503. /* }}} */
  1504. /* {{{ spl_filesystem_tree_it_current_key */
  1505. static void spl_filesystem_tree_it_current_key(zend_object_iterator *iter, zval *key)
  1506. {
  1507. spl_filesystem_object *object = spl_filesystem_iterator_to_object((spl_filesystem_iterator *)iter);
  1508. if (SPL_FILE_DIR_KEY(object, SPL_FILE_DIR_KEY_AS_FILENAME)) {
  1509. ZVAL_STRING(key, object->u.dir.entry.d_name);
  1510. } else {
  1511. spl_filesystem_object_get_file_name(object);
  1512. ZVAL_STRINGL(key, object->file_name, object->file_name_len);
  1513. }
  1514. }
  1515. /* }}} */
  1516. /* {{{ spl_filesystem_tree_it_move_forward */
  1517. static void spl_filesystem_tree_it_move_forward(zend_object_iterator *iter)
  1518. {
  1519. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1520. spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator);
  1521. object->u.dir.index++;
  1522. do {
  1523. spl_filesystem_dir_read(object);
  1524. } while (spl_filesystem_is_dot(object->u.dir.entry.d_name));
  1525. if (object->file_name) {
  1526. efree(object->file_name);
  1527. object->file_name = NULL;
  1528. }
  1529. if (!Z_ISUNDEF(iterator->current)) {
  1530. zval_ptr_dtor(&iterator->current);
  1531. ZVAL_UNDEF(&iterator->current);
  1532. }
  1533. }
  1534. /* }}} */
  1535. /* {{{ spl_filesystem_tree_it_rewind */
  1536. static void spl_filesystem_tree_it_rewind(zend_object_iterator *iter)
  1537. {
  1538. spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
  1539. spl_filesystem_object *object = spl_filesystem_iterator_to_object(iterator);
  1540. object->u.dir.index = 0;
  1541. if (object->u.dir.dirp) {
  1542. php_stream_rewinddir(object->u.dir.dirp);
  1543. }
  1544. do {
  1545. spl_filesystem_dir_read(object);
  1546. } while (spl_filesystem_is_dot(object->u.dir.entry.d_name));
  1547. if (!Z_ISUNDEF(iterator->current)) {
  1548. zval_ptr_dtor(&iterator->current);
  1549. ZVAL_UNDEF(&iterator->current);
  1550. }
  1551. }
  1552. /* }}} */
  1553. /* {{{ iterator handler table */
  1554. static const zend_object_iterator_funcs spl_filesystem_tree_it_funcs = {
  1555. spl_filesystem_tree_it_dtor,
  1556. spl_filesystem_dir_it_valid,
  1557. spl_filesystem_tree_it_current_data,
  1558. spl_filesystem_tree_it_current_key,
  1559. spl_filesystem_tree_it_move_forward,
  1560. spl_filesystem_tree_it_rewind,
  1561. NULL
  1562. };
  1563. /* }}} */
  1564. /* {{{ spl_ce_dir_get_iterator */
  1565. zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
  1566. {
  1567. spl_filesystem_iterator *iterator;
  1568. spl_filesystem_object *dir_object;
  1569. if (by_ref) {
  1570. zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0);
  1571. return NULL;
  1572. }
  1573. dir_object = Z_SPLFILESYSTEM_P(object);
  1574. iterator = spl_filesystem_object_to_iterator(dir_object);
  1575. Z_ADDREF_P(object);
  1576. ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object));
  1577. iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
  1578. return &iterator->intern;
  1579. }
  1580. /* }}} */
  1581. /* {{{ spl_filesystem_object_cast */
  1582. static int spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int type)
  1583. {
  1584. spl_filesystem_object *intern = spl_filesystem_from_obj(readobj);
  1585. if (type == IS_STRING) {
  1586. if (readobj->ce->__tostring) {
  1587. return zend_std_cast_object_tostring(readobj, writeobj, type);
  1588. }
  1589. switch (intern->type) {
  1590. case SPL_FS_INFO:
  1591. case SPL_FS_FILE:
  1592. ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len);
  1593. return SUCCESS;
  1594. case SPL_FS_DIR:
  1595. ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
  1596. return SUCCESS;
  1597. }
  1598. } else if (type == _IS_BOOL) {
  1599. ZVAL_TRUE(writeobj);
  1600. return SUCCESS;
  1601. }
  1602. ZVAL_NULL(writeobj);
  1603. return FAILURE;
  1604. }
  1605. /* }}} */
  1606. static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /* {{{ */
  1607. {
  1608. char *buf;
  1609. size_t line_len = 0;
  1610. zend_long line_add = (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) ? 1 : 0;
  1611. spl_filesystem_file_free_line(intern);
  1612. if (php_stream_eof(intern->u.file.stream)) {
  1613. if (!silent) {
  1614. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
  1615. }
  1616. return FAILURE;
  1617. }
  1618. if (intern->u.file.max_line_len > 0) {
  1619. buf = safe_emalloc((intern->u.file.max_line_len + 1), sizeof(char), 0);
  1620. if (php_stream_get_line(intern->u.file.stream, buf, intern->u.file.max_line_len + 1, &line_len) == NULL) {
  1621. efree(buf);
  1622. buf = NULL;
  1623. } else {
  1624. buf[line_len] = '\0';
  1625. }
  1626. } else {
  1627. buf = php_stream_get_line(intern->u.file.stream, NULL, 0, &line_len);
  1628. }
  1629. if (!buf) {
  1630. intern->u.file.current_line = estrdup("");
  1631. intern->u.file.current_line_len = 0;
  1632. } else {
  1633. if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
  1634. line_len = strcspn(buf, "\r\n");
  1635. buf[line_len] = '\0';
  1636. }
  1637. intern->u.file.current_line = buf;
  1638. intern->u.file.current_line_len = line_len;
  1639. }
  1640. intern->u.file.current_line_num += line_add;
  1641. return SUCCESS;
  1642. } /* }}} */
  1643. static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function *func_ptr, int pass_num_args, zval *return_value, zval *arg2) /* {{{ */
  1644. {
  1645. zend_fcall_info fci;
  1646. zend_fcall_info_cache fcic;
  1647. zval *zresource_ptr = &intern->u.file.zresource;
  1648. int result;
  1649. int num_args = pass_num_args + (arg2 ? 2 : 1);
  1650. zval *params = (zval*)safe_emalloc(num_args, sizeof(zval), 0);
  1651. params[0] = *zresource_ptr;
  1652. if (arg2) {
  1653. params[1] = *arg2;
  1654. }
  1655. if (zend_get_parameters_array_ex(pass_num_args, params + (arg2 ? 2 : 1)) != SUCCESS) {
  1656. efree(params);
  1657. WRONG_PARAM_COUNT_WITH_RETVAL(FAILURE);
  1658. }
  1659. fci.size = sizeof(fci);
  1660. fci.object = NULL;
  1661. fci.retval = return_value;
  1662. fci.param_count = num_args;
  1663. fci.params = params;
  1664. fci.no_separation = 1;
  1665. ZVAL_STR(&fci.function_name, func_ptr->common.function_name);
  1666. fcic.function_handler = func_ptr;
  1667. fcic.called_scope = NULL;
  1668. fcic.object = NULL;
  1669. result = zend_call_function(&fci, &fcic);
  1670. if (result == FAILURE || Z_ISUNDEF_P(return_value)) {
  1671. RETVAL_FALSE;
  1672. }
  1673. efree(params);
  1674. return result;
  1675. } /* }}} */
  1676. #define FileFunctionCall(func_name, pass_num_args, arg2) /* {{{ */ \
  1677. { \
  1678. zend_function *func_ptr; \
  1679. func_ptr = (zend_function *)zend_hash_str_find_ptr(EG(function_table), #func_name, sizeof(#func_name) - 1); \
  1680. if (func_ptr == NULL) { \
  1681. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Internal error, function '%s' not found. Please report", #func_name); \
  1682. return; \
  1683. } \
  1684. spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2); \
  1685. } /* }}} */
  1686. static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, int escape, zval *return_value) /* {{{ */
  1687. {
  1688. int ret = SUCCESS;
  1689. zval *value;
  1690. do {
  1691. ret = spl_filesystem_file_read(intern, 1);
  1692. } while (ret == SUCCESS && !intern->u.file.current_line_len && SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY));
  1693. if (ret == SUCCESS) {
  1694. size_t buf_len = intern->u.file.current_line_len;
  1695. char *buf = estrndup(intern->u.file.current_line, buf_len);
  1696. if (!Z_ISUNDEF(intern->u.file.current_zval)) {
  1697. zval_ptr_dtor(&intern->u.file.current_zval);
  1698. ZVAL_UNDEF(&intern->u.file.current_zval);
  1699. }
  1700. php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf, &intern->u.file.current_zval);
  1701. if (return_value) {
  1702. value = &intern->u.file.current_zval;
  1703. ZVAL_COPY_DEREF(return_value, value);
  1704. }
  1705. }
  1706. return ret;
  1707. }
  1708. /* }}} */
  1709. static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */
  1710. {
  1711. zval retval;
  1712. /* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */
  1713. if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
  1714. if (php_stream_eof(intern->u.file.stream)) {
  1715. if (!silent) {
  1716. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot read from file %s", intern->file_name);
  1717. }
  1718. return FAILURE;
  1719. }
  1720. if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)) {
  1721. return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL);
  1722. } else {
  1723. zend_execute_data *execute_data = EG(current_execute_data);
  1724. zend_call_method_with_0_params(Z_OBJ_P(this_ptr), Z_OBJCE_P(ZEND_THIS), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
  1725. }
  1726. if (!Z_ISUNDEF(retval)) {
  1727. if (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) {
  1728. intern->u.file.current_line_num++;
  1729. }
  1730. spl_filesystem_file_free_line(intern);
  1731. if (Z_TYPE(retval) == IS_STRING) {
  1732. intern->u.file.current_line = estrndup(Z_STRVAL(retval), Z_STRLEN(retval));
  1733. intern->u.file.current_line_len = Z_STRLEN(retval);
  1734. } else {
  1735. zval *value = &retval;
  1736. ZVAL_COPY_DEREF(&intern->u.file.current_zval, value);
  1737. }
  1738. zval_ptr_dtor(&retval);
  1739. return SUCCESS;
  1740. } else {
  1741. return FAILURE;
  1742. }
  1743. } else {
  1744. return spl_filesystem_file_read(intern, silent);
  1745. }
  1746. } /* }}} */
  1747. static int spl_filesystem_file_is_empty_line(spl_filesystem_object *intern) /* {{{ */
  1748. {
  1749. if (intern->u.file.current_line) {
  1750. return intern->u.file.current_line_len == 0;
  1751. } else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
  1752. switch(Z_TYPE(intern->u.file.current_zval)) {
  1753. case IS_STRING:
  1754. return Z_STRLEN(intern->u.file.current_zval) == 0;
  1755. case IS_ARRAY:
  1756. if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)
  1757. && zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 1) {
  1758. uint32_t idx = 0;
  1759. zval *first;
  1760. while (Z_ISUNDEF(Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val)) {
  1761. idx++;
  1762. }
  1763. first = &Z_ARRVAL(intern->u.file.current_zval)->arData[idx].val;
  1764. return Z_TYPE_P(first) == IS_STRING && Z_STRLEN_P(first) == 0;
  1765. }
  1766. return zend_hash_num_elements(Z_ARRVAL(intern->u.file.current_zval)) == 0;
  1767. case IS_NULL:
  1768. return 1;
  1769. default:
  1770. return 0;
  1771. }
  1772. } else {
  1773. return 1;
  1774. }
  1775. }
  1776. /* }}} */
  1777. static int spl_filesystem_file_read_line(zval * this_ptr, spl_filesystem_object *intern, int silent) /* {{{ */
  1778. {
  1779. int ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
  1780. while (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_SKIP_EMPTY) && ret == SUCCESS && spl_filesystem_file_is_empty_line(intern)) {
  1781. spl_filesystem_file_free_line(intern);
  1782. ret = spl_filesystem_file_read_line_ex(this_ptr, intern, silent);
  1783. }
  1784. return ret;
  1785. }
  1786. /* }}} */
  1787. static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *intern) /* {{{ */
  1788. {
  1789. if(!intern->u.file.stream) {
  1790. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  1791. return;
  1792. }
  1793. if (-1 == php_stream_rewind(intern->u.file.stream)) {
  1794. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", intern->file_name);
  1795. } else {
  1796. spl_filesystem_file_free_line(intern);
  1797. intern->u.file.current_line_num = 0;
  1798. }
  1799. if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
  1800. spl_filesystem_file_read_line(this_ptr, intern, 1);
  1801. }
  1802. } /* }}} */
  1803. /* {{{ proto SplFileObject::__construct(string filename [, string mode = 'r' [, bool use_include_path [, resource context]]]])
  1804. Construct a new file object */
  1805. PHP_METHOD(SplFileObject, __construct)
  1806. {
  1807. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1808. zend_bool use_include_path = 0;
  1809. char *p1, *p2;
  1810. char *tmp_path;
  1811. size_t tmp_path_len;
  1812. zend_error_handling error_handling;
  1813. intern->u.file.open_mode = NULL;
  1814. intern->u.file.open_mode_len = 0;
  1815. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|sbr!",
  1816. &intern->file_name, &intern->file_name_len,
  1817. &intern->u.file.open_mode, &intern->u.file.open_mode_len,
  1818. &use_include_path, &intern->u.file.zcontext) == FAILURE) {
  1819. intern->u.file.open_mode = NULL;
  1820. intern->file_name = NULL;
  1821. RETURN_THROWS();
  1822. }
  1823. if (intern->u.file.open_mode == NULL) {
  1824. intern->u.file.open_mode = "r";
  1825. intern->u.file.open_mode_len = 1;
  1826. }
  1827. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
  1828. if (spl_filesystem_file_open(intern, use_include_path, 0) == SUCCESS) {
  1829. tmp_path_len = strlen(intern->u.file.stream->orig_path);
  1830. if (tmp_path_len > 1 && IS_SLASH_AT(intern->u.file.stream->orig_path, tmp_path_len-1)) {
  1831. tmp_path_len--;
  1832. }
  1833. tmp_path = estrndup(intern->u.file.stream->orig_path, tmp_path_len);
  1834. p1 = strrchr(tmp_path, '/');
  1835. #if defined(PHP_WIN32)
  1836. p2 = strrchr(tmp_path, '\\');
  1837. #else
  1838. p2 = 0;
  1839. #endif
  1840. if (p1 || p2) {
  1841. intern->_path_len = ((p1 > p2 ? p1 : p2) - tmp_path);
  1842. } else {
  1843. intern->_path_len = 0;
  1844. }
  1845. efree(tmp_path);
  1846. intern->_path = estrndup(intern->u.file.stream->orig_path, intern->_path_len);
  1847. }
  1848. zend_restore_error_handling(&error_handling);
  1849. } /* }}} */
  1850. /* {{{ proto SplTempFileObject::__construct([int max_memory])
  1851. Construct a new temp file object */
  1852. PHP_METHOD(SplTempFileObject, __construct)
  1853. {
  1854. zend_long max_memory = PHP_STREAM_MAX_MEM;
  1855. char tmp_fname[48];
  1856. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1857. zend_error_handling error_handling;
  1858. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &max_memory) == FAILURE) {
  1859. RETURN_THROWS();
  1860. }
  1861. if (max_memory < 0) {
  1862. intern->file_name = "php://memory";
  1863. intern->file_name_len = 12;
  1864. } else if (ZEND_NUM_ARGS()) {
  1865. intern->file_name_len = slprintf(tmp_fname, sizeof(tmp_fname), "php://temp/maxmemory:" ZEND_LONG_FMT, max_memory);
  1866. intern->file_name = tmp_fname;
  1867. } else {
  1868. intern->file_name = "php://temp";
  1869. intern->file_name_len = 10;
  1870. }
  1871. intern->u.file.open_mode = "wb";
  1872. intern->u.file.open_mode_len = 1;
  1873. zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
  1874. if (spl_filesystem_file_open(intern, 0, 0) == SUCCESS) {
  1875. intern->_path_len = 0;
  1876. intern->_path = estrndup("", 0);
  1877. }
  1878. zend_restore_error_handling(&error_handling);
  1879. } /* }}} */
  1880. /* {{{ proto void SplFileObject::rewind()
  1881. Rewind the file and read the first line */
  1882. PHP_METHOD(SplFileObject, rewind)
  1883. {
  1884. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1885. if (zend_parse_parameters_none() == FAILURE) {
  1886. RETURN_THROWS();
  1887. }
  1888. spl_filesystem_file_rewind(ZEND_THIS, intern);
  1889. } /* }}} */
  1890. /* {{{ proto void SplFileObject::eof()
  1891. Return whether end of file is reached */
  1892. PHP_METHOD(SplFileObject, eof)
  1893. {
  1894. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1895. if (zend_parse_parameters_none() == FAILURE) {
  1896. RETURN_THROWS();
  1897. }
  1898. if(!intern->u.file.stream) {
  1899. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  1900. RETURN_THROWS();
  1901. }
  1902. RETURN_BOOL(php_stream_eof(intern->u.file.stream));
  1903. } /* }}} */
  1904. /* {{{ proto void SplFileObject::valid()
  1905. Return !eof() */
  1906. PHP_METHOD(SplFileObject, valid)
  1907. {
  1908. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1909. if (zend_parse_parameters_none() == FAILURE) {
  1910. RETURN_THROWS();
  1911. }
  1912. if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
  1913. RETURN_BOOL(intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval));
  1914. } else {
  1915. if(!intern->u.file.stream) {
  1916. RETURN_FALSE;
  1917. }
  1918. RETVAL_BOOL(!php_stream_eof(intern->u.file.stream));
  1919. }
  1920. } /* }}} */
  1921. /* {{{ proto string SplFileObject::fgets()
  1922. Rturn next line from file */
  1923. PHP_METHOD(SplFileObject, fgets)
  1924. {
  1925. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1926. if (zend_parse_parameters_none() == FAILURE) {
  1927. RETURN_THROWS();
  1928. }
  1929. if(!intern->u.file.stream) {
  1930. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  1931. RETURN_THROWS();
  1932. }
  1933. if (spl_filesystem_file_read(intern, 0) == FAILURE) {
  1934. RETURN_FALSE;
  1935. }
  1936. RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
  1937. } /* }}} */
  1938. /* {{{ proto string SplFileObject::current()
  1939. Return current line from file */
  1940. PHP_METHOD(SplFileObject, current)
  1941. {
  1942. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1943. if (zend_parse_parameters_none() == FAILURE) {
  1944. RETURN_THROWS();
  1945. }
  1946. if(!intern->u.file.stream) {
  1947. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  1948. RETURN_THROWS();
  1949. }
  1950. if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
  1951. spl_filesystem_file_read_line(ZEND_THIS, intern, 1);
  1952. }
  1953. if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) {
  1954. RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
  1955. } else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
  1956. zval *value = &intern->u.file.current_zval;
  1957. ZVAL_COPY_DEREF(return_value, value);
  1958. return;
  1959. }
  1960. RETURN_FALSE;
  1961. } /* }}} */
  1962. /* {{{ proto int SplFileObject::key()
  1963. Return line number */
  1964. PHP_METHOD(SplFileObject, key)
  1965. {
  1966. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1967. if (zend_parse_parameters_none() == FAILURE) {
  1968. RETURN_THROWS();
  1969. }
  1970. /* Do not read the next line to support correct counting with fgetc()
  1971. if (!intern->current_line) {
  1972. spl_filesystem_file_read_line(ZEND_THIS, intern, 1);
  1973. } */
  1974. RETURN_LONG(intern->u.file.current_line_num);
  1975. } /* }}} */
  1976. /* {{{ proto void SplFileObject::next()
  1977. Read next line */
  1978. PHP_METHOD(SplFileObject, next)
  1979. {
  1980. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1981. if (zend_parse_parameters_none() == FAILURE) {
  1982. RETURN_THROWS();
  1983. }
  1984. spl_filesystem_file_free_line(intern);
  1985. if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
  1986. spl_filesystem_file_read_line(ZEND_THIS, intern, 1);
  1987. }
  1988. intern->u.file.current_line_num++;
  1989. } /* }}} */
  1990. /* {{{ proto void SplFileObject::setFlags(int flags)
  1991. Set file handling flags */
  1992. PHP_METHOD(SplFileObject, setFlags)
  1993. {
  1994. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  1995. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &intern->flags) == FAILURE) {
  1996. RETURN_THROWS();
  1997. }
  1998. } /* }}} */
  1999. /* {{{ proto int SplFileObject::getFlags()
  2000. Get file handling flags */
  2001. PHP_METHOD(SplFileObject, getFlags)
  2002. {
  2003. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2004. if (zend_parse_parameters_none() == FAILURE) {
  2005. RETURN_THROWS();
  2006. }
  2007. RETURN_LONG(intern->flags & SPL_FILE_OBJECT_MASK);
  2008. } /* }}} */
  2009. /* {{{ proto void SplFileObject::setMaxLineLen(int max_len)
  2010. Set maximum line length */
  2011. PHP_METHOD(SplFileObject, setMaxLineLen)
  2012. {
  2013. zend_long max_len;
  2014. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2015. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &max_len) == FAILURE) {
  2016. RETURN_THROWS();
  2017. }
  2018. if (max_len < 0) {
  2019. zend_throw_exception_ex(spl_ce_DomainException, 0, "Maximum line length must be greater than or equal zero");
  2020. RETURN_THROWS();
  2021. }
  2022. intern->u.file.max_line_len = max_len;
  2023. } /* }}} */
  2024. /* {{{ proto int SplFileObject::getMaxLineLen()
  2025. Get maximum line length */
  2026. PHP_METHOD(SplFileObject, getMaxLineLen)
  2027. {
  2028. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2029. if (zend_parse_parameters_none() == FAILURE) {
  2030. RETURN_THROWS();
  2031. }
  2032. RETURN_LONG((zend_long)intern->u.file.max_line_len);
  2033. } /* }}} */
  2034. /* {{{ proto bool SplFileObject::hasChildren()
  2035. Return false */
  2036. PHP_METHOD(SplFileObject, hasChildren)
  2037. {
  2038. if (zend_parse_parameters_none() == FAILURE) {
  2039. RETURN_THROWS();
  2040. }
  2041. RETURN_FALSE;
  2042. } /* }}} */
  2043. /* {{{ proto bool SplFileObject::getChildren()
  2044. Read NULL */
  2045. PHP_METHOD(SplFileObject, getChildren)
  2046. {
  2047. if (zend_parse_parameters_none() == FAILURE) {
  2048. RETURN_THROWS();
  2049. }
  2050. /* return NULL */
  2051. } /* }}} */
  2052. /* {{{ FileFunction */
  2053. #define FileFunction(func_name) \
  2054. PHP_METHOD(SplFileObject, func_name) \
  2055. { \
  2056. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); \
  2057. FileFunctionCall(func_name, ZEND_NUM_ARGS(), NULL); \
  2058. }
  2059. /* }}} */
  2060. /* {{{ proto array SplFileObject::fgetcsv([string delimiter [, string enclosure [, escape = '\\']]])
  2061. Return current line as csv */
  2062. PHP_METHOD(SplFileObject, fgetcsv)
  2063. {
  2064. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2065. char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure;
  2066. int escape = intern->u.file.escape;
  2067. char *delim = NULL, *enclo = NULL, *esc = NULL;
  2068. size_t d_len = 0, e_len = 0, esc_len = 0;
  2069. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
  2070. if(!intern->u.file.stream) {
  2071. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2072. RETURN_THROWS();
  2073. }
  2074. switch(ZEND_NUM_ARGS())
  2075. {
  2076. case 3:
  2077. if (esc_len > 1) {
  2078. php_error_docref(NULL, E_WARNING, "escape must be empty or a single character");
  2079. RETURN_FALSE;
  2080. }
  2081. if (esc_len == 0) {
  2082. escape = PHP_CSV_NO_ESCAPE;
  2083. } else {
  2084. escape = (unsigned char) esc[0];
  2085. }
  2086. /* no break */
  2087. case 2:
  2088. if (e_len != 1) {
  2089. php_error_docref(NULL, E_WARNING, "enclosure must be a character");
  2090. RETURN_FALSE;
  2091. }
  2092. enclosure = enclo[0];
  2093. /* no break */
  2094. case 1:
  2095. if (d_len != 1) {
  2096. php_error_docref(NULL, E_WARNING, "delimiter must be a character");
  2097. RETURN_FALSE;
  2098. }
  2099. delimiter = delim[0];
  2100. /* no break */
  2101. case 0:
  2102. break;
  2103. }
  2104. spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value);
  2105. }
  2106. }
  2107. /* }}} */
  2108. /* {{{ proto int SplFileObject::fputcsv(array fields, [string delimiter [, string enclosure [, string escape]]])
  2109. Output a field array as a CSV line */
  2110. PHP_METHOD(SplFileObject, fputcsv)
  2111. {
  2112. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2113. char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure;
  2114. int escape = intern->u.file.escape;
  2115. char *delim = NULL, *enclo = NULL, *esc = NULL;
  2116. size_t d_len = 0, e_len = 0, esc_len = 0;
  2117. zend_long ret;
  2118. zval *fields = NULL;
  2119. if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|sss", &fields, &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
  2120. switch(ZEND_NUM_ARGS())
  2121. {
  2122. case 4:
  2123. switch (esc_len) {
  2124. case 0:
  2125. escape = PHP_CSV_NO_ESCAPE;
  2126. break;
  2127. case 1:
  2128. escape = (unsigned char) esc[0];
  2129. break;
  2130. default:
  2131. php_error_docref(NULL, E_WARNING, "escape must be empty or a single character");
  2132. RETURN_FALSE;
  2133. }
  2134. /* no break */
  2135. case 3:
  2136. if (e_len != 1) {
  2137. php_error_docref(NULL, E_WARNING, "enclosure must be a character");
  2138. RETURN_FALSE;
  2139. }
  2140. enclosure = enclo[0];
  2141. /* no break */
  2142. case 2:
  2143. if (d_len != 1) {
  2144. php_error_docref(NULL, E_WARNING, "delimiter must be a character");
  2145. RETURN_FALSE;
  2146. }
  2147. delimiter = delim[0];
  2148. /* no break */
  2149. case 1:
  2150. case 0:
  2151. break;
  2152. }
  2153. ret = php_fputcsv(intern->u.file.stream, fields, delimiter, enclosure, escape);
  2154. if (ret < 0) {
  2155. RETURN_FALSE;
  2156. }
  2157. RETURN_LONG(ret);
  2158. }
  2159. }
  2160. /* }}} */
  2161. /* {{{ proto void SplFileObject::setCsvControl([string delimiter [, string enclosure [, string escape ]]])
  2162. Set the delimiter, enclosure and escape character used in fgetcsv */
  2163. PHP_METHOD(SplFileObject, setCsvControl)
  2164. {
  2165. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2166. char delimiter = ',', enclosure = '"';
  2167. int escape = (unsigned char) '\\';
  2168. char *delim = NULL, *enclo = NULL, *esc = NULL;
  2169. size_t d_len = 0, e_len = 0, esc_len = 0;
  2170. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) {
  2171. switch(ZEND_NUM_ARGS())
  2172. {
  2173. case 3:
  2174. switch (esc_len) {
  2175. case 0:
  2176. escape = PHP_CSV_NO_ESCAPE;
  2177. break;
  2178. case 1:
  2179. escape = (unsigned char) esc[0];
  2180. break;
  2181. default:
  2182. php_error_docref(NULL, E_WARNING, "escape must be empty or a single character");
  2183. RETURN_FALSE;
  2184. }
  2185. /* no break */
  2186. case 2:
  2187. if (e_len != 1) {
  2188. php_error_docref(NULL, E_WARNING, "enclosure must be a character");
  2189. RETURN_FALSE;
  2190. }
  2191. enclosure = enclo[0];
  2192. /* no break */
  2193. case 1:
  2194. if (d_len != 1) {
  2195. php_error_docref(NULL, E_WARNING, "delimiter must be a character");
  2196. RETURN_FALSE;
  2197. }
  2198. delimiter = delim[0];
  2199. /* no break */
  2200. case 0:
  2201. break;
  2202. }
  2203. intern->u.file.delimiter = delimiter;
  2204. intern->u.file.enclosure = enclosure;
  2205. intern->u.file.escape = escape;
  2206. }
  2207. }
  2208. /* }}} */
  2209. /* {{{ proto array SplFileObject::getCsvControl()
  2210. Get the delimiter, enclosure and escape character used in fgetcsv */
  2211. PHP_METHOD(SplFileObject, getCsvControl)
  2212. {
  2213. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2214. char delimiter[2], enclosure[2], escape[2];
  2215. array_init(return_value);
  2216. delimiter[0] = intern->u.file.delimiter;
  2217. delimiter[1] = '\0';
  2218. enclosure[0] = intern->u.file.enclosure;
  2219. enclosure[1] = '\0';
  2220. if (intern->u.file.escape == PHP_CSV_NO_ESCAPE) {
  2221. escape[0] = '\0';
  2222. } else {
  2223. escape[0] = (unsigned char) intern->u.file.escape;
  2224. escape[1] = '\0';
  2225. }
  2226. add_next_index_string(return_value, delimiter);
  2227. add_next_index_string(return_value, enclosure);
  2228. add_next_index_string(return_value, escape);
  2229. }
  2230. /* }}} */
  2231. /* {{{ proto bool SplFileObject::flock(int operation [, int &wouldblock])
  2232. Portable file locking */
  2233. FileFunction(flock)
  2234. /* }}} */
  2235. /* {{{ proto bool SplFileObject::fflush()
  2236. Flush the file */
  2237. PHP_METHOD(SplFileObject, fflush)
  2238. {
  2239. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2240. if(!intern->u.file.stream) {
  2241. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2242. RETURN_THROWS();
  2243. }
  2244. RETURN_BOOL(!php_stream_flush(intern->u.file.stream));
  2245. } /* }}} */
  2246. /* {{{ proto int SplFileObject::ftell()
  2247. Return current file position */
  2248. PHP_METHOD(SplFileObject, ftell)
  2249. {
  2250. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2251. zend_long ret;
  2252. if(!intern->u.file.stream) {
  2253. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2254. RETURN_THROWS();
  2255. }
  2256. ret = php_stream_tell(intern->u.file.stream);
  2257. if (ret == -1) {
  2258. RETURN_FALSE;
  2259. } else {
  2260. RETURN_LONG(ret);
  2261. }
  2262. } /* }}} */
  2263. /* {{{ proto int SplFileObject::fseek(int pos [, int whence = SEEK_SET])
  2264. Return current file position */
  2265. PHP_METHOD(SplFileObject, fseek)
  2266. {
  2267. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2268. zend_long pos, whence = SEEK_SET;
  2269. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &pos, &whence) == FAILURE) {
  2270. RETURN_THROWS();
  2271. }
  2272. if(!intern->u.file.stream) {
  2273. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2274. RETURN_THROWS();
  2275. }
  2276. spl_filesystem_file_free_line(intern);
  2277. RETURN_LONG(php_stream_seek(intern->u.file.stream, pos, (int)whence));
  2278. } /* }}} */
  2279. /* {{{ proto int SplFileObject::fgetc()
  2280. Get a character form the file */
  2281. PHP_METHOD(SplFileObject, fgetc)
  2282. {
  2283. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2284. char buf[2];
  2285. int result;
  2286. if(!intern->u.file.stream) {
  2287. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2288. RETURN_THROWS();
  2289. }
  2290. spl_filesystem_file_free_line(intern);
  2291. result = php_stream_getc(intern->u.file.stream);
  2292. if (result == EOF) {
  2293. RETVAL_FALSE;
  2294. } else {
  2295. if (result == '\n') {
  2296. intern->u.file.current_line_num++;
  2297. }
  2298. buf[0] = result;
  2299. buf[1] = '\0';
  2300. RETURN_STRINGL(buf, 1);
  2301. }
  2302. } /* }}} */
  2303. /* {{{ proto int SplFileObject::fpassthru()
  2304. Output all remaining data from a file pointer */
  2305. PHP_METHOD(SplFileObject, fpassthru)
  2306. {
  2307. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2308. if(!intern->u.file.stream) {
  2309. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2310. RETURN_THROWS();
  2311. }
  2312. RETURN_LONG(php_stream_passthru(intern->u.file.stream));
  2313. } /* }}} */
  2314. /* {{{ proto bool SplFileObject::fscanf(string format [, string ...])
  2315. Implements a mostly ANSI compatible fscanf() */
  2316. PHP_METHOD(SplFileObject, fscanf)
  2317. {
  2318. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2319. if(!intern->u.file.stream) {
  2320. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2321. RETURN_THROWS();
  2322. }
  2323. spl_filesystem_file_free_line(intern);
  2324. intern->u.file.current_line_num++;
  2325. FileFunctionCall(fscanf, ZEND_NUM_ARGS(), NULL);
  2326. }
  2327. /* }}} */
  2328. /* {{{ proto int|false SplFileObject::fwrite(string str [, int length])
  2329. Binary-safe file write */
  2330. PHP_METHOD(SplFileObject, fwrite)
  2331. {
  2332. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2333. char *str;
  2334. size_t str_len;
  2335. zend_long length = 0;
  2336. ssize_t written;
  2337. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &str, &str_len, &length) == FAILURE) {
  2338. RETURN_THROWS();
  2339. }
  2340. if(!intern->u.file.stream) {
  2341. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2342. RETURN_THROWS();
  2343. }
  2344. if (ZEND_NUM_ARGS() > 1) {
  2345. if (length >= 0) {
  2346. str_len = MIN((size_t)length, str_len);
  2347. } else {
  2348. /* Negative length given, nothing to write */
  2349. str_len = 0;
  2350. }
  2351. }
  2352. if (!str_len) {
  2353. RETURN_LONG(0);
  2354. }
  2355. written = php_stream_write(intern->u.file.stream, str, str_len);
  2356. if (written < 0) {
  2357. RETURN_FALSE;
  2358. }
  2359. RETURN_LONG(written);
  2360. } /* }}} */
  2361. PHP_METHOD(SplFileObject, fread)
  2362. {
  2363. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2364. zend_long length = 0;
  2365. zend_string *str;
  2366. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &length) == FAILURE) {
  2367. RETURN_THROWS();
  2368. }
  2369. if(!intern->u.file.stream) {
  2370. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2371. RETURN_THROWS();
  2372. }
  2373. if (length <= 0) {
  2374. php_error_docref(NULL, E_WARNING, "Length parameter must be greater than 0");
  2375. RETURN_FALSE;
  2376. }
  2377. str = php_stream_read_to_str(intern->u.file.stream, length);
  2378. if (!str) {
  2379. RETURN_FALSE;
  2380. }
  2381. RETURN_STR(str);
  2382. }
  2383. /* {{{ proto bool SplFileObject::fstat()
  2384. Stat() on a filehandle */
  2385. FileFunction(fstat)
  2386. /* }}} */
  2387. /* {{{ proto bool SplFileObject::ftruncate(int size)
  2388. Truncate file to 'size' length */
  2389. PHP_METHOD(SplFileObject, ftruncate)
  2390. {
  2391. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2392. zend_long size;
  2393. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &size) == FAILURE) {
  2394. RETURN_THROWS();
  2395. }
  2396. if(!intern->u.file.stream) {
  2397. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2398. RETURN_THROWS();
  2399. }
  2400. if (!php_stream_truncate_supported(intern->u.file.stream)) {
  2401. zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't truncate file %s", intern->file_name);
  2402. RETURN_THROWS();
  2403. }
  2404. RETURN_BOOL(0 == php_stream_truncate_set_size(intern->u.file.stream, size));
  2405. } /* }}} */
  2406. /* {{{ proto void SplFileObject::seek(int line_pos)
  2407. Seek to specified line */
  2408. PHP_METHOD(SplFileObject, seek)
  2409. {
  2410. spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
  2411. zend_long line_pos;
  2412. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) {
  2413. RETURN_THROWS();
  2414. }
  2415. if(!intern->u.file.stream) {
  2416. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
  2417. RETURN_THROWS();
  2418. }
  2419. if (line_pos < 0) {
  2420. zend_throw_exception_ex(spl_ce_LogicException, 0, "Can't seek file %s to negative line " ZEND_LONG_FMT, intern->file_name, line_pos);
  2421. RETURN_THROWS();
  2422. }
  2423. spl_filesystem_file_rewind(ZEND_THIS, intern);
  2424. while(intern->u.file.current_line_num < line_pos) {
  2425. if (spl_filesystem_file_read_line(ZEND_THIS, intern, 1) == FAILURE) {
  2426. break;
  2427. }
  2428. }
  2429. } /* }}} */
  2430. /* {{{ PHP_MINIT_FUNCTION(spl_directory)
  2431. */
  2432. PHP_MINIT_FUNCTION(spl_directory)
  2433. {
  2434. REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, class_SplFileInfo_methods);
  2435. memcpy(&spl_filesystem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  2436. spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std);
  2437. spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
  2438. spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast;
  2439. spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object;
  2440. spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage;
  2441. spl_ce_SplFileInfo->serialize = zend_class_serialize_deny;
  2442. spl_ce_SplFileInfo->unserialize = zend_class_unserialize_deny;
  2443. REGISTER_SPL_IMPLEMENTS(SplFileInfo, Stringable);
  2444. REGISTER_SPL_SUB_CLASS_EX(DirectoryIterator, SplFileInfo, spl_filesystem_object_new, class_DirectoryIterator_methods);
  2445. zend_class_implements(spl_ce_DirectoryIterator, 1, zend_ce_iterator);
  2446. REGISTER_SPL_IMPLEMENTS(DirectoryIterator, SeekableIterator);
  2447. spl_ce_DirectoryIterator->get_iterator = spl_filesystem_dir_get_iterator;
  2448. REGISTER_SPL_SUB_CLASS_EX(FilesystemIterator, DirectoryIterator, spl_filesystem_object_new, class_FilesystemIterator_methods);
  2449. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_MODE_MASK", SPL_FILE_DIR_CURRENT_MODE_MASK);
  2450. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_PATHNAME", SPL_FILE_DIR_CURRENT_AS_PATHNAME);
  2451. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_FILEINFO", SPL_FILE_DIR_CURRENT_AS_FILEINFO);
  2452. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "CURRENT_AS_SELF", SPL_FILE_DIR_CURRENT_AS_SELF);
  2453. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_MODE_MASK", SPL_FILE_DIR_KEY_MODE_MASK);
  2454. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_PATHNAME", SPL_FILE_DIR_KEY_AS_PATHNAME);
  2455. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "FOLLOW_SYMLINKS", SPL_FILE_DIR_FOLLOW_SYMLINKS);
  2456. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "KEY_AS_FILENAME", SPL_FILE_DIR_KEY_AS_FILENAME);
  2457. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "NEW_CURRENT_AND_KEY", SPL_FILE_DIR_KEY_AS_FILENAME|SPL_FILE_DIR_CURRENT_AS_FILEINFO);
  2458. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "OTHER_MODE_MASK", SPL_FILE_DIR_OTHERS_MASK);
  2459. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "SKIP_DOTS", SPL_FILE_DIR_SKIPDOTS);
  2460. REGISTER_SPL_CLASS_CONST_LONG(FilesystemIterator, "UNIX_PATHS", SPL_FILE_DIR_UNIXPATHS);
  2461. spl_ce_FilesystemIterator->get_iterator = spl_filesystem_tree_get_iterator;
  2462. REGISTER_SPL_SUB_CLASS_EX(RecursiveDirectoryIterator, FilesystemIterator, spl_filesystem_object_new, class_RecursiveDirectoryIterator_methods);
  2463. REGISTER_SPL_IMPLEMENTS(RecursiveDirectoryIterator, RecursiveIterator);
  2464. memcpy(&spl_filesystem_object_check_handlers, &spl_filesystem_object_handlers, sizeof(zend_object_handlers));
  2465. spl_filesystem_object_check_handlers.clone_obj = NULL;
  2466. spl_filesystem_object_check_handlers.get_method = spl_filesystem_object_get_method_check;
  2467. #ifdef HAVE_GLOB
  2468. REGISTER_SPL_SUB_CLASS_EX(GlobIterator, FilesystemIterator, spl_filesystem_object_new_check, class_GlobIterator_methods);
  2469. REGISTER_SPL_IMPLEMENTS(GlobIterator, Countable);
  2470. #endif
  2471. REGISTER_SPL_SUB_CLASS_EX(SplFileObject, SplFileInfo, spl_filesystem_object_new_check, class_SplFileObject_methods);
  2472. REGISTER_SPL_IMPLEMENTS(SplFileObject, RecursiveIterator);
  2473. REGISTER_SPL_IMPLEMENTS(SplFileObject, SeekableIterator);
  2474. REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "DROP_NEW_LINE", SPL_FILE_OBJECT_DROP_NEW_LINE);
  2475. REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_AHEAD", SPL_FILE_OBJECT_READ_AHEAD);
  2476. REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "SKIP_EMPTY", SPL_FILE_OBJECT_SKIP_EMPTY);
  2477. REGISTER_SPL_CLASS_CONST_LONG(SplFileObject, "READ_CSV", SPL_FILE_OBJECT_READ_CSV);
  2478. REGISTER_SPL_SUB_CLASS_EX(SplTempFileObject, SplFileObject, spl_filesystem_object_new_check, class_SplTempFileObject_methods);
  2479. return SUCCESS;
  2480. }
  2481. /* }}} */