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.

694 lines
23 KiB

23 years ago
23 years ago
23 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
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
23 years ago
23 years ago
23 years ago
21 years ago
21 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
21 years ago
21 years ago
23 years ago
23 years ago
21 years ago
23 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
23 years ago
23 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2005 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.0 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_0.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. | Authors: 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 "php_spl.h"
  26. #include "spl_functions.h"
  27. #include "spl_engine.h"
  28. #include "spl_array.h"
  29. #include "spl_directory.h"
  30. #include "spl_iterators.h"
  31. #include "spl_sxe.h"
  32. #include "spl_exceptions.h"
  33. #include "spl_observer.h"
  34. #include "zend_exceptions.h"
  35. #include "zend_interfaces.h"
  36. #ifdef COMPILE_DL_SPL
  37. ZEND_GET_MODULE(spl)
  38. #endif
  39. ZEND_DECLARE_MODULE_GLOBALS(spl)
  40. /* {{{ spl_functions_none
  41. */
  42. function_entry spl_functions_none[] = {
  43. {NULL, NULL, NULL}
  44. };
  45. /* }}} */
  46. /* {{{ spl_init_globals
  47. */
  48. static void spl_init_globals(zend_spl_globals *spl_globals)
  49. {
  50. spl_globals->autoload_extensions = NULL;
  51. spl_globals->autoload_functions = NULL;
  52. }
  53. /* }}} */
  54. static zend_class_entry * spl_find_ce_by_name(zend_uchar ztype, void *name, int len, zend_bool autoload TSRMLS_DC)
  55. {
  56. zend_class_entry **ce;
  57. int found;
  58. if (!autoload) {
  59. char *lc_name;
  60. lc_name = zend_u_str_tolower_dup(ztype, name, len);
  61. found = zend_u_hash_find(EG(class_table), ztype, lc_name, len +1, (void **) &ce);
  62. efree(lc_name);
  63. } else {
  64. found = zend_u_lookup_class(ztype, name, len, &ce TSRMLS_CC);
  65. }
  66. if (found != SUCCESS) {
  67. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Class %v does not exist%s", name, autoload ? " and could not be loaded" : "");
  68. return NULL;
  69. }
  70. return *ce;
  71. }
  72. /* {{{ array class_parents(object instance)
  73. Return an array containing the names of all parent classes */
  74. PHP_FUNCTION(class_parents)
  75. {
  76. zval *obj;
  77. zend_class_entry *parent_class, *ce;
  78. zend_bool autoload = 1;
  79. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) {
  80. RETURN_FALSE;
  81. }
  82. if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_UNICODE) {
  83. php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected");
  84. RETURN_FALSE;
  85. }
  86. if (Z_TYPE_P(obj) == IS_STRING || Z_TYPE_P(obj) == IS_UNICODE) {
  87. if (NULL == (ce = spl_find_ce_by_name(Z_TYPE_P(obj), Z_UNIVAL_P(obj), Z_UNILEN_P(obj), autoload TSRMLS_CC))) {
  88. RETURN_FALSE;
  89. }
  90. } else {
  91. ce = Z_OBJCE_P(obj);
  92. }
  93. array_init(return_value);
  94. parent_class = ce->parent;
  95. while (parent_class) {
  96. spl_add_class_name(return_value, parent_class, 0, 0 TSRMLS_CC);
  97. parent_class = parent_class->parent;
  98. }
  99. }
  100. /* }}} */
  101. /* {{{ proto array class_implements(mixed what [, bool autoload ])
  102. Return all classes and interfaces implemented by SPL */
  103. PHP_FUNCTION(class_implements)
  104. {
  105. zval *obj;
  106. zend_bool autoload = 1;
  107. zend_class_entry *ce;
  108. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &obj, &autoload) == FAILURE) {
  109. RETURN_FALSE;
  110. }
  111. if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_UNICODE) {
  112. php_error_docref(NULL TSRMLS_CC, E_WARNING, "object or string expected");
  113. RETURN_FALSE;
  114. }
  115. if (Z_TYPE_P(obj) == IS_STRING || Z_TYPE_P(obj) == IS_UNICODE) {
  116. if (NULL == (ce = spl_find_ce_by_name(Z_TYPE_P(obj), Z_UNIVAL_P(obj), Z_UNILEN_P(obj), autoload TSRMLS_CC))) {
  117. RETURN_FALSE;
  118. }
  119. } else {
  120. ce = Z_OBJCE_P(obj);
  121. }
  122. array_init(return_value);
  123. spl_add_interfaces(return_value, ce, 1, ZEND_ACC_INTERFACE TSRMLS_CC);
  124. }
  125. /* }}} */
  126. #define SPL_ADD_CLASS(class_name, z_list, sub, allow, ce_flags) \
  127. spl_add_classes(U_CLASS_ENTRY(spl_ce_ ## class_name), z_list, sub, allow, ce_flags TSRMLS_CC)
  128. #define SPL_LIST_CLASSES(z_list, sub, allow, ce_flags) \
  129. SPL_ADD_CLASS(AppendIterator, z_list, sub, allow, ce_flags); \
  130. SPL_ADD_CLASS(ArrayIterator, z_list, sub, allow, ce_flags); \
  131. SPL_ADD_CLASS(ArrayObject, z_list, sub, allow, ce_flags); \
  132. SPL_ADD_CLASS(BadFunctionCallException, z_list, sub, allow, ce_flags); \
  133. SPL_ADD_CLASS(BadMethodCallException, z_list, sub, allow, ce_flags); \
  134. SPL_ADD_CLASS(CachingIterator, z_list, sub, allow, ce_flags); \
  135. SPL_ADD_CLASS(Countable, z_list, sub, allow, ce_flags); \
  136. SPL_ADD_CLASS(DirectoryIterator, z_list, sub, allow, ce_flags); \
  137. SPL_ADD_CLASS(DomainException, z_list, sub, allow, ce_flags); \
  138. SPL_ADD_CLASS(EmptyIterator, z_list, sub, allow, ce_flags); \
  139. SPL_ADD_CLASS(FilterIterator, z_list, sub, allow, ce_flags); \
  140. SPL_ADD_CLASS(InfiniteIterator, z_list, sub, allow, ce_flags); \
  141. SPL_ADD_CLASS(InvalidArgumentException, z_list, sub, allow, ce_flags); \
  142. SPL_ADD_CLASS(IteratorIterator, z_list, sub, allow, ce_flags); \
  143. SPL_ADD_CLASS(LengthException, z_list, sub, allow, ce_flags); \
  144. SPL_ADD_CLASS(LimitIterator, z_list, sub, allow, ce_flags); \
  145. SPL_ADD_CLASS(LogicException, z_list, sub, allow, ce_flags); \
  146. SPL_ADD_CLASS(NoRewindIterator, z_list, sub, allow, ce_flags); \
  147. SPL_ADD_CLASS(OuterIterator, z_list, sub, allow, ce_flags); \
  148. SPL_ADD_CLASS(OutOfBoundsException, z_list, sub, allow, ce_flags); \
  149. SPL_ADD_CLASS(OutOfRangeException, z_list, sub, allow, ce_flags); \
  150. SPL_ADD_CLASS(OverflowException, z_list, sub, allow, ce_flags); \
  151. SPL_ADD_CLASS(ParentIterator, z_list, sub, allow, ce_flags); \
  152. SPL_ADD_CLASS(RangeException, z_list, sub, allow, ce_flags); \
  153. SPL_ADD_CLASS(RecursiveArrayIterator, z_list, sub, allow, ce_flags); \
  154. SPL_ADD_CLASS(RecursiveCachingIterator, z_list, sub, allow, ce_flags); \
  155. SPL_ADD_CLASS(RecursiveDirectoryIterator, z_list, sub, allow, ce_flags); \
  156. SPL_ADD_CLASS(RecursiveFilterIterator, z_list, sub, allow, ce_flags); \
  157. SPL_ADD_CLASS(RecursiveIterator, z_list, sub, allow, ce_flags); \
  158. SPL_ADD_CLASS(RecursiveIteratorIterator, z_list, sub, allow, ce_flags); \
  159. SPL_ADD_CLASS(RecursiveRegExIterator, z_list, sub, allow, ce_flags); \
  160. SPL_ADD_CLASS(RegExIterator, z_list, sub, allow, ce_flags); \
  161. SPL_ADD_CLASS(RuntimeException, z_list, sub, allow, ce_flags); \
  162. SPL_ADD_CLASS(SeekableIterator, z_list, sub, allow, ce_flags); \
  163. SPL_ADD_CLASS(SimpleXMLIterator, z_list, sub, allow, ce_flags); \
  164. SPL_ADD_CLASS(SplFileInfo, z_list, sub, allow, ce_flags); \
  165. SPL_ADD_CLASS(SplFileObject, z_list, sub, allow, ce_flags); \
  166. SPL_ADD_CLASS(SplObjectStorage, z_list, sub, allow, ce_flags); \
  167. SPL_ADD_CLASS(SplObserver, z_list, sub, allow, ce_flags); \
  168. SPL_ADD_CLASS(SplSubject, z_list, sub, allow, ce_flags); \
  169. SPL_ADD_CLASS(SplTempFileObject, z_list, sub, allow, ce_flags); \
  170. SPL_ADD_CLASS(UnderflowException, z_list, sub, allow, ce_flags); \
  171. SPL_ADD_CLASS(UnexpectedValueException, z_list, sub, allow, ce_flags); \
  172. /* {{{ proto array spl_classes()
  173. Return an array containing the names of all clsses and interfaces defined in SPL */
  174. PHP_FUNCTION(spl_classes)
  175. {
  176. array_init(return_value);
  177. SPL_LIST_CLASSES(return_value, 0, 0, 0)
  178. }
  179. /* }}} */
  180. int spl_autoload(const char *class_name, const char * lc_name, int class_name_len, const char * file_extension TSRMLS_DC) /* {{{ */
  181. {
  182. char *class_file;
  183. int class_file_len;
  184. int dummy = 1;
  185. zend_file_handle file_handle;
  186. zend_op_array *new_op_array;
  187. zval *result = NULL;
  188. class_file_len = spprintf(&class_file, 0, "%s%s", lc_name, file_extension);
  189. if (zend_stream_open(class_file, &file_handle TSRMLS_CC) == SUCCESS) {
  190. if (!file_handle.opened_path) {
  191. file_handle.opened_path = estrndup(class_file, class_file_len);
  192. }
  193. if (zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) {
  194. new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
  195. zend_destroy_file_handle(&file_handle TSRMLS_CC);
  196. } else {
  197. new_op_array = NULL;
  198. zend_file_handle_dtor(&file_handle);
  199. }
  200. if (new_op_array) {
  201. EG(return_value_ptr_ptr) = &result;
  202. EG(active_op_array) = new_op_array;
  203. zend_execute(new_op_array TSRMLS_CC);
  204. destroy_op_array(new_op_array TSRMLS_CC);
  205. efree(new_op_array);
  206. if (!EG(exception)) {
  207. if (EG(return_value_ptr_ptr)) {
  208. zval_ptr_dtor(EG(return_value_ptr_ptr));
  209. }
  210. }
  211. efree(class_file);
  212. return zend_hash_exists(EG(class_table), (char*)lc_name, class_name_len+1);
  213. }
  214. }
  215. efree(class_file);
  216. return 0;
  217. } /* }}} */
  218. /* {{{ void spl_autoload(string class_name [, string file_extensions])
  219. Default implementation for __autoload() */
  220. PHP_FUNCTION(spl_autoload)
  221. {
  222. char *class_name, *lc_name, *file_exts;
  223. int class_name_len, file_exts_len, found = 0;
  224. char *copy, *pos1, *pos2;
  225. zval **original_return_value = EG(return_value_ptr_ptr);
  226. zend_op **original_opline_ptr = EG(opline_ptr);
  227. zend_op_array *original_active_op_array = EG(active_op_array);
  228. zend_function_state *original_function_state_ptr = EG(function_state_ptr);
  229. zval err_mode;
  230. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &class_name, &class_name_len, &file_exts, &file_exts_len) == FAILURE) {
  231. RETURN_FALSE;
  232. }
  233. ZVAL_LONG(&err_mode, EG(error_reporting));
  234. php_alter_ini_entry("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
  235. copy = pos1 = estrdup(ZEND_NUM_ARGS() > 1 ? file_exts : SPL_G(autoload_extensions));
  236. lc_name = zend_str_tolower_dup(class_name, class_name_len);
  237. while(pos1 && *pos1 && !EG(exception)) {
  238. EG(return_value_ptr_ptr) = original_return_value;
  239. EG(opline_ptr) = original_opline_ptr;
  240. EG(active_op_array) = original_active_op_array;
  241. EG(function_state_ptr) = original_function_state_ptr;
  242. pos2 = strchr(pos1, ',');
  243. if (pos2) *pos2 = '\0';
  244. if (spl_autoload(class_name, lc_name, class_name_len, pos1 TSRMLS_CC)) {
  245. found = 1;
  246. break; /* loaded */
  247. }
  248. pos1 = pos2 ? pos2 + 1 : NULL;
  249. }
  250. efree(lc_name);
  251. if (copy) {
  252. efree(copy);
  253. }
  254. if (!EG(error_reporting) && Z_LVAL(err_mode) != EG(error_reporting)) {
  255. convert_to_string(&err_mode);
  256. zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), Z_STRVAL(err_mode), Z_STRLEN(err_mode), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
  257. zendi_zval_dtor(err_mode);
  258. }
  259. EG(return_value_ptr_ptr) = original_return_value;
  260. EG(opline_ptr) = original_opline_ptr;
  261. EG(active_op_array) = original_active_op_array;
  262. EG(function_state_ptr) = original_function_state_ptr;
  263. if (!found) {
  264. zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_LogicException), 0 TSRMLS_CC, "Class %s could not be loaded", class_name);
  265. }
  266. } /* }}} */
  267. /* {{{ void string spl_autoload_extensions([string file_extensions])
  268. Register and return default file extensions for spl_autoload */
  269. PHP_FUNCTION(spl_autoload_extensions)
  270. {
  271. char *file_exts;
  272. int file_exts_len;
  273. if (ZEND_NUM_ARGS() > 0) {
  274. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file_exts, &file_exts_len) == FAILURE) {
  275. return;
  276. }
  277. if (SPL_G(autoload_extensions)) {
  278. efree(SPL_G(autoload_extensions));
  279. }
  280. SPL_G(autoload_extensions) = estrdup(file_exts);
  281. }
  282. RETURN_STRING(SPL_G(autoload_extensions), 1);
  283. } /* }}} */
  284. typedef struct {
  285. zend_function *func_ptr;
  286. zval *obj;
  287. zend_class_entry *ce;
  288. } autoload_func_info;
  289. static void autoload_func_info_dtor(autoload_func_info *alfi)
  290. {
  291. if (alfi->obj) {
  292. zval_ptr_dtor(&alfi->obj);
  293. }
  294. }
  295. /* {{{ void spl_autoload_call(string class_name)
  296. Try all registerd autoload function to load the requested class */
  297. PHP_FUNCTION(spl_autoload_call)
  298. {
  299. zval **class_name, *retval = NULL;
  300. char *func_name, *lc_name;
  301. uint func_name_len;
  302. ulong dummy;
  303. HashPosition function_pos;
  304. autoload_func_info *alfi;
  305. if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &class_name) == FAILURE ||
  306. Z_TYPE_PP(class_name) != (UG(unicode)?IS_UNICODE:IS_STRING)) {
  307. return;
  308. }
  309. if (SPL_G(autoload_functions)) {
  310. lc_name = zend_u_str_tolower_dup(Z_TYPE_PP(class_name), Z_UNIVAL_PP(class_name), Z_UNILEN_PP(class_name));
  311. zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &function_pos);
  312. while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), &function_pos) == SUCCESS && !EG(exception)) {
  313. zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &func_name_len, &dummy, 0, &function_pos);
  314. zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &alfi, &function_pos);
  315. zend_call_method(alfi->obj ? &alfi->obj : NULL, alfi->ce, &alfi->func_ptr, func_name, func_name_len, &retval, 1, *class_name, NULL TSRMLS_CC);
  316. if (retval) {
  317. zval_ptr_dtor(&retval);
  318. }
  319. if (zend_u_hash_exists(EG(class_table), Z_TYPE_PP(class_name), lc_name, Z_UNILEN_PP(class_name)+1)) {
  320. break;
  321. }
  322. zend_hash_move_forward_ex(SPL_G(autoload_functions), &function_pos);
  323. }
  324. efree(lc_name);
  325. } else {
  326. /* do not use or overwrite &EG(autoload_func) here */
  327. zend_call_method_with_1_params(NULL, NULL, NULL, "spl_autoload", NULL, *class_name);
  328. }
  329. } /* }}} */
  330. /* {{{ void spl_autoload_register([string autoload_function = "spl_autoload" [, throw = true]])
  331. Register given function as __autoload() implementation */
  332. PHP_FUNCTION(spl_autoload_register)
  333. {
  334. zval zfunc_name;
  335. char *func_name;
  336. uint func_name_len;
  337. char *lc_name = NULL;
  338. zval *zcallable = NULL;
  339. zend_bool do_throw = 1;
  340. zend_function *spl_func_ptr;
  341. autoload_func_info alfi;
  342. zval **obj_ptr;
  343. zend_uchar func_name_type;
  344. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "|tb", &func_name, &func_name_len, &func_name_type, &do_throw) == FAILURE) {
  345. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &zcallable, &do_throw) == FAILURE) {
  346. return;
  347. }
  348. if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_IS_STATIC, &zfunc_name, &alfi.ce, &alfi.func_ptr, &obj_ptr TSRMLS_CC)) {
  349. if (do_throw) {
  350. zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_LogicException), 0 TSRMLS_CC, "Passed array does not specify a callable static method");
  351. }
  352. zval_dtor(&zfunc_name);
  353. return;
  354. } else if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
  355. if (do_throw) {
  356. zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_LogicException), 0 TSRMLS_CC, "Passed array specifies a non static method but no object");
  357. }
  358. zval_dtor(&zfunc_name);
  359. return;
  360. }
  361. func_name_type = Z_TYPE(zfunc_name);
  362. func_name_len = Z_UNILEN(zfunc_name);
  363. lc_name = zend_u_str_tolower_dup(func_name_type, Z_UNIVAL(zfunc_name), func_name_len);
  364. zval_dtor(&zfunc_name);
  365. if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
  366. alfi.obj = *obj_ptr;
  367. alfi.obj->refcount++;
  368. } else {
  369. alfi.obj = NULL;
  370. }
  371. } else if (ZEND_NUM_ARGS()) {
  372. lc_name = zend_u_str_tolower_dup(func_name_type, func_name, func_name_len);
  373. if ((func_name_len == sizeof("spl_autoload_call")-1) &&
  374. (ZEND_U_EQUAL(func_name_type, lc_name, func_name_len, "spl_autoload_call", sizeof("spl_autoload_call")-1))) {
  375. if (do_throw) {
  376. zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_LogicException), 0 TSRMLS_CC, "Function spl_autoload_call() cannot be registered");
  377. }
  378. efree(lc_name);
  379. return;
  380. }
  381. if (zend_u_hash_find(EG(function_table), func_name_type, lc_name, func_name_len+1, (void **) &alfi.func_ptr) == FAILURE) {
  382. if (do_throw) {
  383. zend_throw_exception_ex(U_CLASS_ENTRY(spl_ce_LogicException), 0 TSRMLS_CC, "Function '%R' not found", func_name_type, func_name);
  384. }
  385. efree(lc_name);
  386. return;
  387. }
  388. alfi.obj = NULL;
  389. alfi.ce = NULL;
  390. }
  391. if (ZEND_NUM_ARGS()) {
  392. if (!SPL_G(autoload_functions)) {
  393. ALLOC_HASHTABLE(SPL_G(autoload_functions));
  394. zend_u_hash_init(SPL_G(autoload_functions), 1, NULL, (dtor_func_t) autoload_func_info_dtor, 0, UG(unicode));
  395. }
  396. zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &spl_func_ptr);
  397. if (EG(autoload_func) == spl_func_ptr) { /* registered already, so we insert that first */
  398. autoload_func_info spl_alfi;
  399. spl_alfi.func_ptr = spl_func_ptr;
  400. spl_alfi.obj = NULL;
  401. spl_alfi.ce = NULL;
  402. zend_hash_add(SPL_G(autoload_functions), "spl_autoload", sizeof("spl_autoload"), &spl_alfi, sizeof(autoload_func_info), NULL);
  403. }
  404. zend_u_hash_add(SPL_G(autoload_functions), func_name_type, lc_name, func_name_len+1, &alfi, sizeof(autoload_func_info), NULL);
  405. efree(lc_name);
  406. }
  407. if (SPL_G(autoload_functions)) {
  408. zend_hash_find(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call"), (void **) &EG(autoload_func));
  409. } else {
  410. zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &EG(autoload_func));
  411. }
  412. } /* }}} */
  413. /* {{{ bool spl_autoload_unregister(string autoload_function)
  414. Unregister given function as __autoload() implementation */
  415. PHP_FUNCTION(spl_autoload_unregister)
  416. {
  417. char *func_name, *lc_name;
  418. int func_name_len, success = FAILURE;
  419. zend_function *spl_func_ptr;
  420. zend_uchar func_name_type;
  421. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &func_name, &func_name_len, &func_name_type) == FAILURE) {
  422. return;
  423. }
  424. lc_name = zend_u_str_tolower_dup(func_name_type, func_name, func_name_len);
  425. if (SPL_G(autoload_functions)) {
  426. if ((func_name_len == sizeof("spl_autoload_call")-1) &&
  427. (ZEND_U_EQUAL(func_name_type, lc_name, func_name_len, "spl_autoload_call", sizeof("spl_autoload_call")-1))) {
  428. /* remove all */
  429. zend_hash_destroy(SPL_G(autoload_functions));
  430. FREE_HASHTABLE(SPL_G(autoload_functions));
  431. SPL_G(autoload_functions) = NULL;
  432. EG(autoload_func) = NULL;
  433. success = SUCCESS;
  434. } else {
  435. /* remove specific */
  436. success = zend_u_hash_del(SPL_G(autoload_functions), func_name_type, lc_name, func_name_len+1);
  437. }
  438. } else if ((func_name_len == sizeof("spl_autoload")-1) &&
  439. (ZEND_U_EQUAL(func_name_type, lc_name, func_name_len, "spl_autoload", sizeof("spl_autoload")-1))) {
  440. /* register single spl_autoload() */
  441. zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &spl_func_ptr);
  442. if (EG(autoload_func) == spl_func_ptr) {
  443. success = SUCCESS;
  444. EG(autoload_func) = NULL;
  445. }
  446. }
  447. efree(lc_name);
  448. RETURN_BOOL(success == SUCCESS);
  449. } /* }}} */
  450. /* {{{ false|array spl_autoload_functions()
  451. Return all registered __autoload() functionns */
  452. PHP_FUNCTION(spl_autoload_functions)
  453. {
  454. zend_function *fptr, **func_ptr_ptr;
  455. HashPosition function_pos;
  456. if (!EG(autoload_func)) {
  457. if (zend_hash_find(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME), (void **) &fptr) == SUCCESS) {
  458. array_init(return_value);
  459. add_next_index_stringl(return_value, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 1);
  460. return;
  461. }
  462. RETURN_FALSE;
  463. }
  464. zend_hash_find(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call"), (void **) &fptr);
  465. if (EG(autoload_func) == fptr) {
  466. array_init(return_value);
  467. zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &function_pos);
  468. while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), &function_pos) == SUCCESS) {
  469. zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &func_ptr_ptr, &function_pos);
  470. if ((*func_ptr_ptr)->common.scope) {
  471. zval *tmp;
  472. MAKE_STD_ZVAL(tmp);
  473. array_init(tmp);
  474. add_next_index_text(tmp, (*func_ptr_ptr)->common.scope->name, 1);
  475. add_next_index_text(tmp, (*func_ptr_ptr)->common.function_name, 1);
  476. add_next_index_zval(return_value, tmp);
  477. } else
  478. add_next_index_text(return_value, (*func_ptr_ptr)->common.function_name, 1);
  479. zend_hash_move_forward_ex(SPL_G(autoload_functions), &function_pos);
  480. }
  481. return;
  482. }
  483. array_init(return_value);
  484. add_next_index_text(return_value, EG(autoload_func)->common.function_name, 1);
  485. } /* }}} */
  486. int spl_build_class_list_string(zval **entry, char **list TSRMLS_DC) /* {{{ */
  487. {
  488. char *res;
  489. spprintf(&res, 0, "%s, %s", *list, Z_STRVAL_PP(entry));
  490. efree(*list);
  491. *list = res;
  492. return ZEND_HASH_APPLY_KEEP;
  493. } /* }}} */
  494. /* {{{ PHP_MINFO(spl)
  495. */
  496. PHP_MINFO_FUNCTION(spl)
  497. {
  498. zval list;
  499. char *strg;
  500. php_info_print_table_start();
  501. php_info_print_table_header(2, "SPL support", "enabled");
  502. INIT_PZVAL(&list);
  503. array_init(&list);
  504. SPL_LIST_CLASSES(&list, 0, 1, ZEND_ACC_INTERFACE)
  505. strg = estrdup("");
  506. zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg TSRMLS_CC);
  507. zval_dtor(&list);
  508. php_info_print_table_row(2, "Interfaces", strg + 2);
  509. efree(strg);
  510. INIT_PZVAL(&list);
  511. array_init(&list);
  512. SPL_LIST_CLASSES(&list, 0, -1, ZEND_ACC_INTERFACE)
  513. strg = estrdup("");
  514. zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg TSRMLS_CC);
  515. zval_dtor(&list);
  516. php_info_print_table_row(2, "Classes", strg + 2);
  517. efree(strg);
  518. php_info_print_table_end();
  519. }
  520. /* }}} */
  521. /* {{{ spl_functions
  522. */
  523. function_entry spl_functions[] = {
  524. PHP_FE(spl_classes, NULL)
  525. PHP_FE(spl_autoload, NULL)
  526. PHP_FE(spl_autoload_extensions, NULL)
  527. PHP_FE(spl_autoload_register, NULL)
  528. PHP_FE(spl_autoload_unregister, NULL)
  529. PHP_FE(spl_autoload_functions, NULL)
  530. PHP_FE(spl_autoload_call, NULL)
  531. PHP_FE(class_parents, NULL)
  532. PHP_FE(class_implements, NULL)
  533. #ifdef SPL_ITERATORS_H
  534. PHP_FE(iterator_to_array, NULL)
  535. PHP_FE(iterator_count, NULL)
  536. #endif /* SPL_ITERATORS_H */
  537. {NULL, NULL, NULL}
  538. };
  539. /* }}} */
  540. /* {{{ PHP_MINIT_FUNCTION(spl)
  541. */
  542. PHP_MINIT_FUNCTION(spl)
  543. {
  544. ZEND_INIT_MODULE_GLOBALS(spl, spl_init_globals, NULL);
  545. PHP_MINIT(spl_iterators)(INIT_FUNC_ARGS_PASSTHRU);
  546. PHP_MINIT(spl_array)(INIT_FUNC_ARGS_PASSTHRU);
  547. PHP_MINIT(spl_directory)(INIT_FUNC_ARGS_PASSTHRU);
  548. PHP_MINIT(spl_sxe)(INIT_FUNC_ARGS_PASSTHRU);
  549. PHP_MINIT(spl_exceptions)(INIT_FUNC_ARGS_PASSTHRU);
  550. PHP_MINIT(spl_observer)(INIT_FUNC_ARGS_PASSTHRU);
  551. return SUCCESS;
  552. }
  553. /* }}} */
  554. PHP_RINIT_FUNCTION(spl) /* {{{ */
  555. {
  556. SPL_G(autoload_extensions) = estrndup(".inc,.php", sizeof(".inc,.php")-1);
  557. SPL_G(autoload_functions) = NULL;
  558. return SUCCESS;
  559. } /* }}} */
  560. PHP_RSHUTDOWN_FUNCTION(spl) /* {{{ */
  561. {
  562. if (SPL_G(autoload_extensions)) {
  563. efree(SPL_G(autoload_extensions));
  564. SPL_G(autoload_extensions) = NULL;
  565. }
  566. if (SPL_G(autoload_functions)) {
  567. zend_hash_destroy(SPL_G(autoload_functions));
  568. FREE_HASHTABLE(SPL_G(autoload_functions));
  569. SPL_G(autoload_functions) = NULL;
  570. }
  571. return SUCCESS;
  572. } /* }}} */
  573. #ifdef HAVE_SIMPLEXML
  574. static zend_module_dep spl_deps[] = {
  575. ZEND_MOD_REQUIRED("libxml")
  576. ZEND_MOD_REQUIRED("simplexml")
  577. {NULL, NULL, NULL}
  578. };
  579. #endif
  580. /* {{{ spl_module_entry
  581. */
  582. zend_module_entry spl_module_entry = {
  583. #ifdef HAVE_SIMPLEXML
  584. STANDARD_MODULE_HEADER_EX, NULL,
  585. spl_deps,
  586. #else
  587. STANDARD_MODULE_HEADER,
  588. #endif
  589. "SPL",
  590. spl_functions,
  591. PHP_MINIT(spl),
  592. NULL,
  593. PHP_RINIT(spl),
  594. PHP_RSHUTDOWN(spl),
  595. PHP_MINFO(spl),
  596. "0.2",
  597. STANDARD_MODULE_PROPERTIES
  598. };
  599. /* }}} */
  600. /*
  601. * Local variables:
  602. * tab-width: 4
  603. * c-basic-offset: 4
  604. * End:
  605. * vim600: fdm=marker
  606. * vim: noet sw=4 ts=4
  607. */