You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3073 lines
99 KiB

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