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.

5493 lines
166 KiB

18 years ago
19 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
19 years ago
18 years ago
18 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
20 years ago
20 years ago
18 years ago
18 years ago
18 years ago
20 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
20 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
20 years ago
20 years ago
20 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
20 years ago
18 years ago
18 years ago
18 years ago
20 years ago
20 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
20 years ago
20 years ago
20 years ago
20 years ago
18 years ago
18 years ago
20 years ago
20 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2009 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. | Authors: Timm Friebe <thekid@thekid.de> |
  16. | George Schlossnagle <george@omniti.com> |
  17. | Andrei Zmievski <andrei@gravitonic.com> |
  18. | Marcus Boerger <helly@php.net> |
  19. | Johannes Schlueter <johannes@php.net> |
  20. +----------------------------------------------------------------------+
  21. */
  22. /* $Id$ */
  23. #ifdef HAVE_CONFIG_H
  24. #include "config.h"
  25. #endif
  26. #include "php.h"
  27. #include "php_ini.h"
  28. #include "php_reflection.h"
  29. #include "ext/standard/info.h"
  30. #include "zend.h"
  31. #include "zend_API.h"
  32. #include "zend_exceptions.h"
  33. #include "zend_operators.h"
  34. #include "zend_constants.h"
  35. #include "zend_ini.h"
  36. #include "zend_interfaces.h"
  37. #include "zend_closures.h"
  38. /* Undefine "getParameters" macro defined in "main/php3_compat.h" */
  39. #ifdef getParameters
  40. # undef getParameters
  41. #endif
  42. /* Class entry pointers */
  43. PHPAPI zend_class_entry *reflector_ptr;
  44. PHPAPI zend_class_entry *reflection_exception_ptr;
  45. PHPAPI zend_class_entry *reflection_ptr;
  46. PHPAPI zend_class_entry *reflection_function_abstract_ptr;
  47. PHPAPI zend_class_entry *reflection_function_ptr;
  48. PHPAPI zend_class_entry *reflection_parameter_ptr;
  49. PHPAPI zend_class_entry *reflection_class_ptr;
  50. PHPAPI zend_class_entry *reflection_object_ptr;
  51. PHPAPI zend_class_entry *reflection_method_ptr;
  52. PHPAPI zend_class_entry *reflection_property_ptr;
  53. PHPAPI zend_class_entry *reflection_extension_ptr;
  54. #if MBO_0
  55. ZEND_BEGIN_MODULE_GLOBALS(reflection)
  56. int dummy;
  57. ZEND_END_MODULE_GLOBALS(reflection)
  58. #ifdef ZTS
  59. # define REFLECTION_G(v) \
  60. TSRMG(reflection_globals_id, zend_reflection_globals*, v)
  61. extern int reflection_globals_id;
  62. #else
  63. # define REFLECTION_G(v) (reflection_globals.v)
  64. extern zend_reflection_globals reflectionglobals;
  65. #endif
  66. ZEND_DECLARE_MODULE_GLOBALS(reflection)
  67. #endif /* MBO_0 */
  68. /* Method macros */
  69. #define METHOD_NOTSTATIC(ce) \
  70. if (!this_ptr || !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) { \
  71. zend_error(E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C)); \
  72. return; \
  73. } \
  74. /* Exception throwing macro */
  75. #define _DO_THROW(msg) \
  76. zend_throw_exception(reflection_exception_ptr, msg, 0 TSRMLS_CC); \
  77. return; \
  78. #define RETURN_ON_EXCEPTION \
  79. if (EG(exception) && Z_OBJCE_P(EG(exception)) == reflection_exception_ptr) { \
  80. return; \
  81. }
  82. #define GET_REFLECTION_OBJECT_PTR(target) \
  83. intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC); \
  84. if (intern == NULL || intern->ptr == NULL) { \
  85. RETURN_ON_EXCEPTION \
  86. zend_error(E_ERROR, "Internal error: Failed to retrieve the reflection object"); \
  87. } \
  88. target = intern->ptr; \
  89. /* Class constants */
  90. #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value) \
  91. zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
  92. /* {{{ Smart string functions */
  93. typedef struct _string {
  94. char *string;
  95. int len;
  96. int alloced;
  97. } string;
  98. static void string_init(string *str)
  99. {
  100. str->string = (char *) emalloc(1024);
  101. str->len = 1;
  102. str->alloced = 1024;
  103. *str->string = '\0';
  104. }
  105. static string *string_printf(string *str, const char *format, ...)
  106. {
  107. int len;
  108. va_list arg;
  109. char *s_tmp;
  110. va_start(arg, format);
  111. len = zend_vspprintf(&s_tmp, 0, format, arg);
  112. if (len) {
  113. register int nlen = (str->len + len + (1024 - 1)) & ~(1024 - 1);
  114. if (str->alloced < nlen) {
  115. str->alloced = nlen;
  116. str->string = erealloc(str->string, str->alloced);
  117. }
  118. memcpy(str->string + str->len - 1, s_tmp, len + 1);
  119. str->len += len;
  120. }
  121. efree(s_tmp);
  122. va_end(arg);
  123. return str;
  124. }
  125. static string *string_write(string *str, char *buf, int len)
  126. {
  127. register int nlen = (str->len + len + (1024 - 1)) & ~(1024 - 1);
  128. if (str->alloced < nlen) {
  129. str->alloced = nlen;
  130. str->string = erealloc(str->string, str->alloced);
  131. }
  132. memcpy(str->string + str->len - 1, buf, len);
  133. str->len += len;
  134. str->string[str->len - 1] = '\0';
  135. return str;
  136. }
  137. static string *string_append(string *str, string *append)
  138. {
  139. if (append->len > 1) {
  140. string_write(str, append->string, append->len - 1);
  141. }
  142. return str;
  143. }
  144. static void string_free(string *str)
  145. {
  146. efree(str->string);
  147. str->len = 0;
  148. str->alloced = 0;
  149. str->string = NULL;
  150. }
  151. /* }}} */
  152. /* Struct for properties */
  153. typedef struct _property_reference {
  154. zend_class_entry *ce;
  155. zend_property_info prop;
  156. unsigned int ignore_visibility:1;
  157. } property_reference;
  158. /* Struct for parameters */
  159. typedef struct _parameter_reference {
  160. zend_uint offset;
  161. zend_uint required;
  162. struct _zend_arg_info *arg_info;
  163. zend_function *fptr;
  164. } parameter_reference;
  165. typedef enum {
  166. REF_TYPE_OTHER, /* Must be 0 */
  167. REF_TYPE_FUNCTION,
  168. REF_TYPE_PARAMETER,
  169. REF_TYPE_PROPERTY
  170. } reflection_type_t;
  171. /* Struct for reflection objects */
  172. typedef struct {
  173. zend_object zo;
  174. void *ptr;
  175. reflection_type_t ref_type;
  176. zval *obj;
  177. zend_class_entry *ce;
  178. } reflection_object;
  179. static zend_object_handlers reflection_object_handlers;
  180. static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC)
  181. {
  182. zval **value;
  183. if (zend_hash_find(Z_OBJPROP_P(object), name, name_len, (void **) &value) == FAILURE) {
  184. RETURN_FALSE;
  185. }
  186. *return_value = **value;
  187. zval_copy_ctor(return_value);
  188. INIT_PZVAL(return_value);
  189. }
  190. #ifdef ilia_0
  191. static void _default_lookup_entry(zval *object, char *name, int name_len, zval **return_value TSRMLS_DC) /* {{{ */
  192. {
  193. zval **value;
  194. if (zend_hash_find(Z_OBJPROP_P(object), name, name_len, (void **) &value) == FAILURE) {
  195. *return_value = NULL;
  196. } else {
  197. *return_value = *value;
  198. }
  199. }
  200. /* }}} */
  201. #endif
  202. static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC)
  203. {
  204. zend_uint num_interfaces = ++class_entry->num_interfaces;
  205. class_entry->interfaces = (zend_class_entry **) realloc(class_entry->interfaces, sizeof(zend_class_entry *) * num_interfaces);
  206. class_entry->interfaces[num_interfaces - 1] = interface_entry;
  207. }
  208. static zend_function *_copy_function(zend_function *fptr TSRMLS_DC) /* {{{ */
  209. {
  210. if (fptr
  211. && fptr->type == ZEND_INTERNAL_FUNCTION
  212. && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
  213. {
  214. zend_function *copy_fptr;
  215. copy_fptr = emalloc(sizeof(zend_function));
  216. memcpy(copy_fptr, fptr, sizeof(zend_function));
  217. copy_fptr->internal_function.function_name = estrdup(fptr->internal_function.function_name);
  218. return copy_fptr;
  219. } else {
  220. /* no copy needed */
  221. return fptr;
  222. }
  223. }
  224. /* }}} */
  225. static void _free_function(zend_function *fptr TSRMLS_DC) /* {{{ */
  226. {
  227. if (fptr
  228. && fptr->type == ZEND_INTERNAL_FUNCTION
  229. && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
  230. {
  231. efree(fptr->internal_function.function_name);
  232. efree(fptr);
  233. }
  234. }
  235. /* }}} */
  236. static void reflection_free_objects_storage(void *object TSRMLS_DC)
  237. {
  238. reflection_object *intern = (reflection_object *) object;
  239. parameter_reference *reference;
  240. if (intern->ptr) {
  241. switch (intern->ref_type) {
  242. case REF_TYPE_PARAMETER:
  243. reference = (parameter_reference*)intern->ptr;
  244. _free_function(reference->fptr TSRMLS_CC);
  245. efree(intern->ptr);
  246. break;
  247. case REF_TYPE_FUNCTION:
  248. _free_function(intern->ptr TSRMLS_CC);
  249. break;
  250. case REF_TYPE_PROPERTY:
  251. efree(intern->ptr);
  252. break;
  253. case REF_TYPE_OTHER:
  254. break;
  255. }
  256. }
  257. intern->ptr = NULL;
  258. if (intern->obj) {
  259. zval_ptr_dtor(&intern->obj);
  260. }
  261. zend_objects_free_object_storage(object TSRMLS_CC);
  262. }
  263. static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC)
  264. {
  265. zval tmp;
  266. zend_object_value retval;
  267. reflection_object *intern;
  268. intern = ecalloc(1, sizeof(reflection_object));
  269. intern->zo.ce = class_type;
  270. zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
  271. zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
  272. retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);
  273. retval.handlers = &reflection_object_handlers;
  274. return retval;
  275. }
  276. static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC)
  277. {
  278. if (!object) {
  279. ALLOC_ZVAL(object);
  280. }
  281. Z_TYPE_P(object) = IS_OBJECT;
  282. object_init_ex(object, pce);
  283. Z_SET_REFCOUNT_P(object, 1);
  284. Z_SET_ISREF_P(object);
  285. return object;
  286. }
  287. static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC);
  288. static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char *indent TSRMLS_DC);
  289. static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC);
  290. static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC);
  291. static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC);
  292. /* {{{ _class_string */
  293. static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC)
  294. {
  295. int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
  296. string sub_indent;
  297. string_init(&sub_indent);
  298. string_printf(&sub_indent, "%s ", indent);
  299. /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
  300. if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
  301. string_printf(str, "%s%s", indent, ce->doc_comment);
  302. string_write(str, "\n", 1);
  303. }
  304. if (obj) {
  305. string_printf(str, "%sObject of class [ ", indent);
  306. } else {
  307. string_printf(str, "%s%s [ ", indent, (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : "Class");
  308. }
  309. string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
  310. if (ce->module) {
  311. string_printf(str, ":%s", ce->module->name);
  312. }
  313. string_printf(str, "> ");
  314. if (ce->get_iterator != NULL) {
  315. string_printf(str, "<iterateable> ");
  316. }
  317. if (ce->ce_flags & ZEND_ACC_INTERFACE) {
  318. string_printf(str, "interface ");
  319. } else {
  320. if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
  321. string_printf(str, "abstract ");
  322. }
  323. if (ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
  324. string_printf(str, "final ");
  325. }
  326. string_printf(str, "class ");
  327. }
  328. string_printf(str, "%s", ce->name);
  329. if (ce->parent) {
  330. string_printf(str, " extends %s", ce->parent->name);
  331. }
  332. if (ce->num_interfaces) {
  333. zend_uint i;
  334. if (ce->ce_flags & ZEND_ACC_INTERFACE) {
  335. string_printf(str, " extends %s", ce->interfaces[0]->name);
  336. } else {
  337. string_printf(str, " implements %s", ce->interfaces[0]->name);
  338. }
  339. for (i = 1; i < ce->num_interfaces; ++i) {
  340. string_printf(str, ", %s", ce->interfaces[i]->name);
  341. }
  342. }
  343. string_printf(str, " ] {\n");
  344. /* The information where a class is declared is only available for user classes */
  345. if (ce->type == ZEND_USER_CLASS) {
  346. string_printf(str, "%s @@ %s %d-%d\n", indent, ce->filename,
  347. ce->line_start, ce->line_end);
  348. }
  349. /* Constants */
  350. if (&ce->constants_table) {
  351. zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
  352. string_printf(str, "\n");
  353. count = zend_hash_num_elements(&ce->constants_table);
  354. string_printf(str, "%s - Constants [%d] {\n", indent, count);
  355. if (count > 0) {
  356. HashPosition pos;
  357. zval **value;
  358. char *key;
  359. uint key_len;
  360. ulong num_index;
  361. zend_hash_internal_pointer_reset_ex(&ce->constants_table, &pos);
  362. while (zend_hash_get_current_data_ex(&ce->constants_table, (void **) &value, &pos) == SUCCESS) {
  363. zend_hash_get_current_key_ex(&ce->constants_table, &key, &key_len, &num_index, 0, &pos);
  364. _const_string(str, key, *value, indent TSRMLS_CC);
  365. zend_hash_move_forward_ex(&ce->constants_table, &pos);
  366. }
  367. }
  368. string_printf(str, "%s }\n", indent);
  369. }
  370. /* Static properties */
  371. if (&ce->properties_info) {
  372. /* counting static properties */
  373. count = zend_hash_num_elements(&ce->properties_info);
  374. if (count > 0) {
  375. HashPosition pos;
  376. zend_property_info *prop;
  377. zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
  378. while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
  379. if(prop->flags & ZEND_ACC_SHADOW) {
  380. count_shadow_props++;
  381. } else if (prop->flags & ZEND_ACC_STATIC) {
  382. count_static_props++;
  383. }
  384. zend_hash_move_forward_ex(&ce->properties_info, &pos);
  385. }
  386. }
  387. /* static properties */
  388. string_printf(str, "\n%s - Static properties [%d] {\n", indent, count_static_props);
  389. if (count_static_props > 0) {
  390. HashPosition pos;
  391. zend_property_info *prop;
  392. zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
  393. while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
  394. if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
  395. _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
  396. }
  397. zend_hash_move_forward_ex(&ce->properties_info, &pos);
  398. }
  399. }
  400. string_printf(str, "%s }\n", indent);
  401. }
  402. /* Static methods */
  403. if (&ce->function_table) {
  404. /* counting static methods */
  405. count = zend_hash_num_elements(&ce->function_table);
  406. if (count > 0) {
  407. HashPosition pos;
  408. zend_function *mptr;
  409. zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
  410. while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
  411. if (mptr->common.fn_flags & ZEND_ACC_STATIC
  412. && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
  413. {
  414. count_static_funcs++;
  415. }
  416. zend_hash_move_forward_ex(&ce->function_table, &pos);
  417. }
  418. }
  419. /* static methods */
  420. string_printf(str, "\n%s - Static methods [%d] {", indent, count_static_funcs);
  421. if (count_static_funcs > 0) {
  422. HashPosition pos;
  423. zend_function *mptr;
  424. zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
  425. while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
  426. if (mptr->common.fn_flags & ZEND_ACC_STATIC
  427. && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
  428. {
  429. string_printf(str, "\n");
  430. _function_string(str, mptr, ce, sub_indent.string TSRMLS_CC);
  431. }
  432. zend_hash_move_forward_ex(&ce->function_table, &pos);
  433. }
  434. } else {
  435. string_printf(str, "\n");
  436. }
  437. string_printf(str, "%s }\n", indent);
  438. }
  439. /* Default/Implicit properties */
  440. if (&ce->properties_info) {
  441. count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
  442. string_printf(str, "\n%s - Properties [%d] {\n", indent, count);
  443. if (count > 0) {
  444. HashPosition pos;
  445. zend_property_info *prop;
  446. zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
  447. while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
  448. if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
  449. _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
  450. }
  451. zend_hash_move_forward_ex(&ce->properties_info, &pos);
  452. }
  453. }
  454. string_printf(str, "%s }\n", indent);
  455. }
  456. if (obj && Z_OBJ_HT_P(obj)->get_properties) {
  457. string dyn;
  458. HashTable *properties = Z_OBJ_HT_P(obj)->get_properties(obj TSRMLS_CC);
  459. HashPosition pos;
  460. zval **prop;
  461. string_init(&dyn);
  462. count = 0;
  463. if (properties && zend_hash_num_elements(properties)) {
  464. zend_hash_internal_pointer_reset_ex(properties, &pos);
  465. while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
  466. char *prop_name;
  467. uint prop_name_size;
  468. ulong index;
  469. if (zend_hash_get_current_key_ex(properties, &prop_name, &prop_name_size, &index, 1, &pos) == HASH_KEY_IS_STRING) {
  470. if (prop_name_size && prop_name[0]) { /* skip all private and protected properties */
  471. if (!zend_hash_quick_exists(&ce->properties_info, prop_name, prop_name_size, zend_get_hash_value(prop_name, prop_name_size))) {
  472. count++;
  473. _property_string(&dyn, NULL, prop_name, sub_indent.string TSRMLS_CC);
  474. }
  475. }
  476. efree(prop_name);
  477. }
  478. zend_hash_move_forward_ex(properties, &pos);
  479. }
  480. }
  481. string_printf(str, "\n%s - Dynamic properties [%d] {\n", indent, count);
  482. string_append(str, &dyn);
  483. string_printf(str, "%s }\n", indent);
  484. string_free(&dyn);
  485. }
  486. /* Non static methods */
  487. if (&ce->function_table) {
  488. count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
  489. if (count > 0) {
  490. HashPosition pos;
  491. zend_function *mptr;
  492. string dyn;
  493. count = 0;
  494. string_init(&dyn);
  495. zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
  496. while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
  497. if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
  498. && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
  499. {
  500. char *key;
  501. uint key_len;
  502. ulong num_index;
  503. uint len = strlen(mptr->common.function_name);
  504. /* Do not display old-style inherited constructors */
  505. if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0
  506. || mptr->common.scope == ce
  507. || zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING
  508. || zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0)
  509. {
  510. zend_function *closure;
  511. /* see if this is a closure */
  512. if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
  513. && memcmp(mptr->common.function_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  514. && (closure = zend_get_closure_invoke_method(obj TSRMLS_CC)) != NULL)
  515. {
  516. mptr = closure;
  517. } else {
  518. closure = NULL;
  519. }
  520. string_printf(&dyn, "\n");
  521. _function_string(&dyn, mptr, ce, sub_indent.string TSRMLS_CC);
  522. count++;
  523. _free_function(closure TSRMLS_CC);
  524. }
  525. }
  526. zend_hash_move_forward_ex(&ce->function_table, &pos);
  527. }
  528. string_printf(str, "\n%s - Methods [%d] {", indent, count);
  529. if (!count) {
  530. string_printf(str, "\n");
  531. }
  532. string_append(str, &dyn);
  533. string_free(&dyn);
  534. } else {
  535. string_printf(str, "\n%s - Methods [0] {\n", indent);
  536. }
  537. string_printf(str, "%s }\n", indent);
  538. }
  539. string_printf(str, "%s}\n", indent);
  540. string_free(&sub_indent);
  541. }
  542. /* }}} */
  543. /* {{{ _const_string */
  544. static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC)
  545. {
  546. char *type;
  547. zval value_copy;
  548. int use_copy;
  549. type = zend_zval_type_name(value);
  550. zend_make_printable_zval(value, &value_copy, &use_copy);
  551. if (use_copy) {
  552. value = &value_copy;
  553. }
  554. string_printf(str, "%s Constant [ %s %s ] { %s }\n",
  555. indent, type, name, Z_STRVAL_P(value));
  556. if (use_copy) {
  557. zval_dtor(value);
  558. }
  559. }
  560. /* }}} */
  561. /* {{{ _get_recv_opcode */
  562. static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset)
  563. {
  564. zend_op *op = op_array->opcodes;
  565. zend_op *end = op + op_array->last;
  566. ++offset;
  567. while (op < end) {
  568. if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
  569. && op->op1.u.constant.value.lval == (long)offset)
  570. {
  571. return op;
  572. }
  573. ++op;
  574. }
  575. return NULL;
  576. }
  577. /* }}} */
  578. /* {{{ _parameter_string */
  579. static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC)
  580. {
  581. string_printf(str, "Parameter #%d [ ", offset);
  582. if (offset >= required) {
  583. string_printf(str, "<optional> ");
  584. } else {
  585. string_printf(str, "<required> ");
  586. }
  587. if (arg_info->class_name) {
  588. string_printf(str, "%s ", arg_info->class_name);
  589. if (arg_info->allow_null) {
  590. string_printf(str, "or NULL ");
  591. }
  592. } else if (arg_info->array_type_hint) {
  593. string_printf(str, "array ");
  594. if (arg_info->allow_null) {
  595. string_printf(str, "or NULL ");
  596. }
  597. }
  598. if (arg_info->pass_by_reference) {
  599. string_write(str, "&", sizeof("&")-1);
  600. }
  601. if (arg_info->name) {
  602. string_printf(str, "$%s", arg_info->name);
  603. } else {
  604. string_printf(str, "$param%d", offset);
  605. }
  606. if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
  607. zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
  608. if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
  609. zval *zv, zv_copy;
  610. int use_copy;
  611. string_write(str, " = ", sizeof(" = ")-1);
  612. ALLOC_ZVAL(zv);
  613. *zv = precv->op2.u.constant;
  614. zval_copy_ctor(zv);
  615. INIT_PZVAL(zv);
  616. zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
  617. if (Z_TYPE_P(zv) == IS_BOOL) {
  618. if (Z_LVAL_P(zv)) {
  619. string_write(str, "true", sizeof("true")-1);
  620. } else {
  621. string_write(str, "false", sizeof("false")-1);
  622. }
  623. } else if (Z_TYPE_P(zv) == IS_NULL) {
  624. string_write(str, "NULL", sizeof("NULL")-1);
  625. } else if (Z_TYPE_P(zv) == IS_STRING) {
  626. string_write(str, "'", sizeof("'")-1);
  627. string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15));
  628. if (Z_STRLEN_P(zv) > 15) {
  629. string_write(str, "...", sizeof("...")-1);
  630. }
  631. string_write(str, "'", sizeof("'")-1);
  632. } else {
  633. zend_make_printable_zval(zv, &zv_copy, &use_copy);
  634. string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
  635. if (use_copy) {
  636. zval_dtor(&zv_copy);
  637. }
  638. }
  639. zval_ptr_dtor(&zv);
  640. }
  641. }
  642. string_write(str, " ]", sizeof(" ]")-1);
  643. }
  644. /* }}} */
  645. /* {{{ _function_parameter_string */
  646. static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
  647. {
  648. struct _zend_arg_info *arg_info = fptr->common.arg_info;
  649. zend_uint i, required = fptr->common.required_num_args;
  650. if (!arg_info) {
  651. return;
  652. }
  653. string_printf(str, "\n");
  654. string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
  655. for (i = 0; i < fptr->common.num_args; i++) {
  656. string_printf(str, "%s ", indent);
  657. _parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC);
  658. string_write(str, "\n", sizeof("\n")-1);
  659. arg_info++;
  660. }
  661. string_printf(str, "%s}\n", indent);
  662. }
  663. /* }}} */
  664. /* {{{ _function_closure_string */
  665. static void _function_closure_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
  666. {
  667. zend_uint i, count;
  668. ulong num_index;
  669. char *key;
  670. uint key_len;
  671. HashTable *static_variables;
  672. HashPosition pos;
  673. if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
  674. return;
  675. }
  676. static_variables = fptr->op_array.static_variables;
  677. count = zend_hash_num_elements(static_variables);
  678. if (!count) {
  679. return;
  680. }
  681. string_printf(str, "\n");
  682. string_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
  683. zend_hash_internal_pointer_reset_ex(static_variables, &pos);
  684. i = 0;
  685. while (i < count) {
  686. zend_hash_get_current_key_ex(static_variables, &key, &key_len, &num_index, 0, &pos);
  687. string_printf(str, "%s Variable #%d [ $%s ]\n", indent, i++, key);
  688. zend_hash_move_forward_ex(static_variables, &pos);
  689. }
  690. string_printf(str, "%s}\n", indent);
  691. }
  692. /* }}} */
  693. /* {{{ _function_string */
  694. static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent TSRMLS_DC)
  695. {
  696. string param_indent;
  697. zend_function *overwrites;
  698. char *lc_name;
  699. unsigned int lc_name_len;
  700. /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
  701. * What's "wrong" is that any whitespace before the doc comment start is
  702. * swallowed, leading to an unaligned comment.
  703. */
  704. if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
  705. string_printf(str, "%s%s\n", indent, fptr->op_array.doc_comment);
  706. }
  707. string_write(str, indent, strlen(indent));
  708. string_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
  709. string_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
  710. if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
  711. string_printf(str, ", deprecated");
  712. }
  713. if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
  714. string_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
  715. }
  716. if (scope && fptr->common.scope) {
  717. if (fptr->common.scope != scope) {
  718. string_printf(str, ", inherits %s", fptr->common.scope->name);
  719. } else if (fptr->common.scope->parent) {
  720. lc_name_len = strlen(fptr->common.function_name);
  721. lc_name = zend_str_tolower_dup(fptr->common.function_name, lc_name_len);
  722. if (zend_hash_find(&fptr->common.scope->parent->function_table, lc_name, lc_name_len + 1, (void**) &overwrites) == SUCCESS) {
  723. if (fptr->common.scope != overwrites->common.scope) {
  724. string_printf(str, ", overwrites %s", overwrites->common.scope->name);
  725. }
  726. }
  727. efree(lc_name);
  728. }
  729. }
  730. if (fptr->common.prototype && fptr->common.prototype->common.scope) {
  731. string_printf(str, ", prototype %s", fptr->common.prototype->common.scope->name);
  732. }
  733. if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
  734. string_printf(str, ", ctor");
  735. }
  736. if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
  737. string_printf(str, ", dtor");
  738. }
  739. string_printf(str, "> ");
  740. if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
  741. string_printf(str, "abstract ");
  742. }
  743. if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
  744. string_printf(str, "final ");
  745. }
  746. if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
  747. string_printf(str, "static ");
  748. }
  749. if (fptr->common.scope) {
  750. /* These are mutually exclusive */
  751. switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
  752. case ZEND_ACC_PUBLIC:
  753. string_printf(str, "public ");
  754. break;
  755. case ZEND_ACC_PRIVATE:
  756. string_printf(str, "private ");
  757. break;
  758. case ZEND_ACC_PROTECTED:
  759. string_printf(str, "protected ");
  760. break;
  761. default:
  762. string_printf(str, "<visibility error> ");
  763. break;
  764. }
  765. string_printf(str, "method ");
  766. } else {
  767. string_printf(str, "function ");
  768. }
  769. if (fptr->op_array.return_reference) {
  770. string_printf(str, "&");
  771. }
  772. string_printf(str, "%s ] {\n", fptr->common.function_name);
  773. /* The information where a function is declared is only available for user classes */
  774. if (fptr->type == ZEND_USER_FUNCTION) {
  775. string_printf(str, "%s @@ %s %d - %d\n", indent,
  776. fptr->op_array.filename,
  777. fptr->op_array.line_start,
  778. fptr->op_array.line_end);
  779. }
  780. string_init(&param_indent);
  781. string_printf(&param_indent, "%s ", indent);
  782. if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
  783. _function_closure_string(str, fptr, param_indent.string TSRMLS_CC);
  784. }
  785. _function_parameter_string(str, fptr, param_indent.string TSRMLS_CC);
  786. string_free(&param_indent);
  787. string_printf(str, "%s}\n", indent);
  788. }
  789. /* }}} */
  790. /* {{{ _property_string */
  791. static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC)
  792. {
  793. char *class_name;
  794. string_printf(str, "%sProperty [ ", indent);
  795. if (!prop) {
  796. string_printf(str, "<dynamic> public $%s", prop_name);
  797. } else {
  798. if (!(prop->flags & ZEND_ACC_STATIC)) {
  799. if (prop->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
  800. string_write(str, "<implicit> ", sizeof("<implicit> ") - 1);
  801. } else {
  802. string_write(str, "<default> ", sizeof("<default> ") - 1);
  803. }
  804. }
  805. /* These are mutually exclusive */
  806. switch (prop->flags & ZEND_ACC_PPP_MASK) {
  807. case ZEND_ACC_PUBLIC:
  808. string_printf(str, "public ");
  809. break;
  810. case ZEND_ACC_PRIVATE:
  811. string_printf(str, "private ");
  812. break;
  813. case ZEND_ACC_PROTECTED:
  814. string_printf(str, "protected ");
  815. break;
  816. }
  817. if(prop->flags & ZEND_ACC_STATIC) {
  818. string_printf(str, "static ");
  819. }
  820. zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
  821. string_printf(str, "$%s", prop_name);
  822. }
  823. string_printf(str, " ]\n");
  824. }
  825. /* }}} */
  826. static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  827. {
  828. string *str = va_arg(args, string *);
  829. char *indent = va_arg(args, char *);
  830. int number = va_arg(args, int);
  831. char *comma = "";
  832. if (number == ini_entry->module_number) {
  833. string_printf(str, " %sEntry [ %s <", indent, ini_entry->name);
  834. if (ini_entry->modifiable == ZEND_INI_ALL) {
  835. string_printf(str, "ALL");
  836. } else {
  837. if (ini_entry->modifiable & ZEND_INI_USER) {
  838. string_printf(str, "USER");
  839. comma = ",";
  840. }
  841. if (ini_entry->modifiable & ZEND_INI_PERDIR) {
  842. string_printf(str, "%sPERDIR", comma);
  843. comma = ",";
  844. }
  845. if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
  846. string_printf(str, "%sSYSTEM", comma);
  847. }
  848. }
  849. string_printf(str, "> ]\n");
  850. string_printf(str, " %s Current = '%s'\n", indent, ini_entry->value ? ini_entry->value : "");
  851. if (ini_entry->modified) {
  852. string_printf(str, " %s Default = '%s'\n", indent, ini_entry->orig_value ? ini_entry->orig_value : "");
  853. }
  854. string_printf(str, " %s}\n", indent);
  855. }
  856. return ZEND_HASH_APPLY_KEEP;
  857. }
  858. static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  859. {
  860. string *str = va_arg(args, string *);
  861. char *indent = va_arg(args, char *);
  862. struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
  863. int *num_classes = va_arg(args, int*);
  864. if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
  865. string_printf(str, "\n");
  866. _class_string(str, *pce, NULL, indent TSRMLS_CC);
  867. (*num_classes)++;
  868. }
  869. return ZEND_HASH_APPLY_KEEP;
  870. }
  871. static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  872. {
  873. string *str = va_arg(args, string *);
  874. char *indent = va_arg(args, char *);
  875. struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
  876. int *num_classes = va_arg(args, int*);
  877. if (constant->module_number == module->module_number) {
  878. _const_string(str, constant->name, &constant->value, indent TSRMLS_CC);
  879. (*num_classes)++;
  880. }
  881. return ZEND_HASH_APPLY_KEEP;
  882. }
  883. /* {{{ _extension_string */
  884. static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC)
  885. {
  886. string_printf(str, "%sExtension [ ", indent);
  887. if (module->type == MODULE_PERSISTENT) {
  888. string_printf(str, "<persistent>");
  889. }
  890. if (module->type == MODULE_TEMPORARY) {
  891. string_printf(str, "<temporary>" );
  892. }
  893. string_printf(str, " extension #%d %s version %s ] {\n",
  894. module->module_number, module->name,
  895. (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
  896. if (module->deps) {
  897. const zend_module_dep* dep = module->deps;
  898. string_printf(str, "\n - Dependencies {\n");
  899. while(dep->name) {
  900. string_printf(str, "%s Dependency [ %s (", indent, dep->name);
  901. switch(dep->type) {
  902. case MODULE_DEP_REQUIRED:
  903. string_write(str, "Required", sizeof("Required") - 1);
  904. break;
  905. case MODULE_DEP_CONFLICTS:
  906. string_write(str, "Conflicts", sizeof("Conflicts") - 1);
  907. break;
  908. case MODULE_DEP_OPTIONAL:
  909. string_write(str, "Optional", sizeof("Optional") - 1);
  910. break;
  911. default:
  912. string_write(str, "Error", sizeof("Error") - 1); /* shouldn't happen */
  913. break;
  914. }
  915. if (dep->rel) {
  916. string_printf(str, " %s", dep->rel);
  917. }
  918. if (dep->version) {
  919. string_printf(str, " %s", dep->version);
  920. }
  921. string_write(str, ") ]\n", sizeof(") ]\n") - 1);
  922. dep++;
  923. }
  924. string_printf(str, "%s }\n", indent);
  925. }
  926. {
  927. string str_ini;
  928. string_init(&str_ini);
  929. zend_hash_apply_with_arguments(EG(ini_directives) TSRMLS_CC, (apply_func_args_t) _extension_ini_string, 3, &str_ini, indent, module->module_number);
  930. if (str_ini.len > 1) {
  931. string_printf(str, "\n - INI {\n");
  932. string_append(str, &str_ini);
  933. string_printf(str, "%s }\n", indent);
  934. }
  935. string_free(&str_ini);
  936. }
  937. {
  938. string str_constants;
  939. int num_constants = 0;
  940. string_init(&str_constants);
  941. zend_hash_apply_with_arguments(EG(zend_constants) TSRMLS_CC, (apply_func_args_t) _extension_const_string, 4, &str_constants, indent, module, &num_constants);
  942. if (num_constants) {
  943. string_printf(str, "\n - Constants [%d] {\n", num_constants);
  944. string_append(str, &str_constants);
  945. string_printf(str, "%s }\n", indent);
  946. }
  947. string_free(&str_constants);
  948. }
  949. if (module->functions && module->functions->fname) {
  950. zend_function *fptr;
  951. const zend_function_entry *func = module->functions;
  952. string_printf(str, "\n - Functions {\n");
  953. /* Is there a better way of doing this? */
  954. while (func->fname) {
  955. if (zend_hash_find(EG(function_table), func->fname, strlen(func->fname) + 1, (void**) &fptr) == FAILURE) {
  956. zend_error(E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
  957. func++;
  958. continue;
  959. }
  960. _function_string(str, fptr, NULL, " " TSRMLS_CC);
  961. func++;
  962. }
  963. string_printf(str, "%s }\n", indent);
  964. }
  965. {
  966. string str_classes;
  967. string sub_indent;
  968. int num_classes = 0;
  969. string_init(&sub_indent);
  970. string_printf(&sub_indent, "%s ", indent);
  971. string_init(&str_classes);
  972. zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) _extension_class_string, 4, &str_classes, sub_indent.string, module, &num_classes);
  973. if (num_classes) {
  974. string_printf(str, "\n - Classes [%d] {", num_classes);
  975. string_append(str, &str_classes);
  976. string_printf(str, "%s }\n", indent);
  977. }
  978. string_free(&str_classes);
  979. string_free(&sub_indent);
  980. }
  981. string_printf(str, "%s}\n", indent);
  982. }
  983. /* }}} */
  984. /* {{{ _function_check_flag */
  985. static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
  986. {
  987. reflection_object *intern;
  988. zend_function *mptr;
  989. if (zend_parse_parameters_none() == FAILURE) {
  990. return;
  991. }
  992. GET_REFLECTION_OBJECT_PTR(mptr);
  993. RETURN_BOOL(mptr->common.fn_flags & mask);
  994. }
  995. /* }}} */
  996. /* {{{ zend_reflection_class_factory */
  997. PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC)
  998. {
  999. reflection_object *intern;
  1000. zval *name;
  1001. MAKE_STD_ZVAL(name);
  1002. ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
  1003. reflection_instantiate(reflection_class_ptr, object TSRMLS_CC);
  1004. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1005. intern->ptr = ce;
  1006. intern->ref_type = REF_TYPE_OTHER;
  1007. intern->ce = ce;
  1008. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1009. }
  1010. /* }}} */
  1011. /* {{{ reflection_extension_factory */
  1012. static void reflection_extension_factory(zval *object, const char *name_str TSRMLS_DC)
  1013. {
  1014. reflection_object *intern;
  1015. zval *name;
  1016. int name_len = strlen(name_str);
  1017. char *lcname;
  1018. struct _zend_module_entry *module;
  1019. ALLOCA_FLAG(use_heap)
  1020. lcname = do_alloca(name_len + 1, use_heap);
  1021. zend_str_tolower_copy(lcname, name_str, name_len);
  1022. if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
  1023. free_alloca(lcname, use_heap);
  1024. return;
  1025. }
  1026. free_alloca(lcname, use_heap);
  1027. reflection_instantiate(reflection_extension_ptr, object TSRMLS_CC);
  1028. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1029. MAKE_STD_ZVAL(name);
  1030. ZVAL_STRINGL(name, module->name, name_len, 1);
  1031. intern->ptr = module;
  1032. intern->ref_type = REF_TYPE_OTHER;
  1033. intern->ce = NULL;
  1034. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1035. }
  1036. /* }}} */
  1037. /* {{{ reflection_parameter_factory */
  1038. static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC)
  1039. {
  1040. reflection_object *intern;
  1041. parameter_reference *reference;
  1042. zval *name;
  1043. if (closure_object) {
  1044. Z_ADDREF_P(closure_object);
  1045. }
  1046. MAKE_STD_ZVAL(name);
  1047. if (arg_info->name) {
  1048. ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
  1049. } else {
  1050. ZVAL_NULL(name);
  1051. }
  1052. reflection_instantiate(reflection_parameter_ptr, object TSRMLS_CC);
  1053. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1054. reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
  1055. reference->arg_info = arg_info;
  1056. reference->offset = offset;
  1057. reference->required = required;
  1058. reference->fptr = fptr;
  1059. intern->ptr = reference;
  1060. intern->ref_type = REF_TYPE_PARAMETER;
  1061. intern->ce = fptr->common.scope;
  1062. intern->obj = closure_object;
  1063. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1064. }
  1065. /* }}} */
  1066. /* {{{ reflection_function_factory */
  1067. static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object TSRMLS_DC)
  1068. {
  1069. reflection_object *intern;
  1070. zval *name;
  1071. if (closure_object) {
  1072. Z_ADDREF_P(closure_object);
  1073. }
  1074. MAKE_STD_ZVAL(name);
  1075. ZVAL_STRING(name, function->common.function_name, 1);
  1076. reflection_instantiate(reflection_function_ptr, object TSRMLS_CC);
  1077. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1078. intern->ptr = function;
  1079. intern->ref_type = REF_TYPE_FUNCTION;
  1080. intern->ce = NULL;
  1081. intern->obj = closure_object;
  1082. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1083. }
  1084. /* }}} */
  1085. /* {{{ reflection_method_factory */
  1086. static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object TSRMLS_DC)
  1087. {
  1088. reflection_object *intern;
  1089. zval *name;
  1090. zval *classname;
  1091. if (closure_object) {
  1092. Z_ADDREF_P(closure_object);
  1093. }
  1094. MAKE_STD_ZVAL(name);
  1095. MAKE_STD_ZVAL(classname);
  1096. ZVAL_STRING(name, method->common.function_name, 1);
  1097. ZVAL_STRINGL(classname, method->common.scope->name, method->common.scope->name_length, 1);
  1098. reflection_instantiate(reflection_method_ptr, object TSRMLS_CC);
  1099. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1100. intern->ptr = method;
  1101. intern->ref_type = REF_TYPE_FUNCTION;
  1102. intern->ce = ce;
  1103. intern->obj = closure_object;
  1104. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1105. zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
  1106. }
  1107. /* }}} */
  1108. /* {{{ reflection_property_factory */
  1109. static void reflection_property_factory(zend_class_entry *ce, zend_property_info *prop, zval *object TSRMLS_DC)
  1110. {
  1111. reflection_object *intern;
  1112. zval *name;
  1113. zval *classname;
  1114. property_reference *reference;
  1115. char *class_name, *prop_name;
  1116. zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
  1117. if (!(prop->flags & ZEND_ACC_PRIVATE)) {
  1118. /* we have to search the class hierarchy for this (implicit) public or protected property */
  1119. zend_class_entry *tmp_ce = ce, *store_ce = ce;
  1120. zend_property_info *tmp_info = NULL;
  1121. while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, prop_name, strlen(prop_name) + 1, (void **) &tmp_info) != SUCCESS) {
  1122. ce = tmp_ce;
  1123. tmp_ce = tmp_ce->parent;
  1124. }
  1125. if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */
  1126. prop = tmp_info;
  1127. } else { /* not found, use initial value */
  1128. ce = store_ce;
  1129. }
  1130. }
  1131. MAKE_STD_ZVAL(name);
  1132. MAKE_STD_ZVAL(classname);
  1133. ZVAL_STRING(name, prop_name, 1);
  1134. ZVAL_STRINGL(classname, prop->ce->name, prop->ce->name_length, 1);
  1135. reflection_instantiate(reflection_property_ptr, object TSRMLS_CC);
  1136. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1137. reference = (property_reference*) emalloc(sizeof(property_reference));
  1138. reference->ce = ce;
  1139. reference->prop = *prop;
  1140. reference->ignore_visibility = 0;
  1141. intern->ptr = reference;
  1142. intern->ref_type = REF_TYPE_PROPERTY;
  1143. intern->ce = ce;
  1144. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1145. zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
  1146. }
  1147. /* }}} */
  1148. /* {{{ _reflection_export */
  1149. static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
  1150. {
  1151. zval *reflector_ptr;
  1152. zval output, *output_ptr = &output;
  1153. zval *argument_ptr, *argument2_ptr;
  1154. zval *retval_ptr, **params[2];
  1155. int result;
  1156. int return_output = 0;
  1157. zend_fcall_info fci;
  1158. zend_fcall_info_cache fcc;
  1159. zval fname;
  1160. if (ctor_argc == 1) {
  1161. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &argument_ptr, &return_output) == FAILURE) {
  1162. return;
  1163. }
  1164. } else {
  1165. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|b", &argument_ptr, &argument2_ptr, &return_output) == FAILURE) {
  1166. return;
  1167. }
  1168. }
  1169. INIT_PZVAL(&output);
  1170. /* Create object */
  1171. MAKE_STD_ZVAL(reflector_ptr);
  1172. if (object_and_properties_init(reflector_ptr, ce_ptr, NULL) == FAILURE) {
  1173. _DO_THROW("Could not create reflector");
  1174. }
  1175. /* Call __construct() */
  1176. params[0] = &argument_ptr;
  1177. params[1] = &argument2_ptr;
  1178. fci.size = sizeof(fci);
  1179. fci.function_table = NULL;
  1180. fci.function_name = NULL;
  1181. fci.symbol_table = NULL;
  1182. fci.object_ptr = reflector_ptr;
  1183. fci.retval_ptr_ptr = &retval_ptr;
  1184. fci.param_count = ctor_argc;
  1185. fci.params = params;
  1186. fci.no_separation = 1;
  1187. fcc.initialized = 1;
  1188. fcc.function_handler = ce_ptr->constructor;
  1189. fcc.calling_scope = ce_ptr;
  1190. fcc.called_scope = Z_OBJCE_P(reflector_ptr);
  1191. fcc.object_ptr = reflector_ptr;
  1192. result = zend_call_function(&fci, &fcc TSRMLS_CC);
  1193. if (retval_ptr) {
  1194. zval_ptr_dtor(&retval_ptr);
  1195. }
  1196. if (EG(exception)) {
  1197. zval_ptr_dtor(&reflector_ptr);
  1198. return;
  1199. }
  1200. if (result == FAILURE) {
  1201. zval_ptr_dtor(&reflector_ptr);
  1202. _DO_THROW("Could not create reflector");
  1203. }
  1204. /* Call static reflection::export */
  1205. ZVAL_BOOL(&output, return_output);
  1206. params[0] = &reflector_ptr;
  1207. params[1] = &output_ptr;
  1208. ZVAL_STRINGL(&fname, "reflection::export", sizeof("reflection::export") - 1, 0);
  1209. fci.function_table = &reflection_ptr->function_table;
  1210. fci.function_name = &fname;
  1211. fci.object_ptr = NULL;
  1212. fci.retval_ptr_ptr = &retval_ptr;
  1213. fci.param_count = 2;
  1214. fci.params = params;
  1215. fci.no_separation = 1;
  1216. result = zend_call_function(&fci, NULL TSRMLS_CC);
  1217. if (result == FAILURE && EG(exception) == NULL) {
  1218. zval_ptr_dtor(&reflector_ptr);
  1219. zval_ptr_dtor(&retval_ptr);
  1220. _DO_THROW("Could not execute reflection::export()");
  1221. }
  1222. if (return_output) {
  1223. COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
  1224. } else {
  1225. zval_ptr_dtor(&retval_ptr);
  1226. }
  1227. /* Destruct reflector which is no longer needed */
  1228. zval_ptr_dtor(&reflector_ptr);
  1229. }
  1230. /* }}} */
  1231. /* {{{ Preventing __clone from being called */
  1232. ZEND_METHOD(reflection, __clone)
  1233. {
  1234. /* Should never be executable */
  1235. _DO_THROW("Cannot clone object using __clone()");
  1236. }
  1237. /* }}} */
  1238. /* {{{ proto public static mixed Reflection::export(Reflector r [, bool return])
  1239. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  1240. ZEND_METHOD(reflection, export)
  1241. {
  1242. zval *object, fname, *retval_ptr;
  1243. int result;
  1244. zend_bool return_output = 0;
  1245. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &object, reflector_ptr, &return_output) == FAILURE) {
  1246. return;
  1247. }
  1248. /* Invoke the __toString() method */
  1249. ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring") - 1, 1);
  1250. result= call_user_function_ex(NULL, &object, &fname, &retval_ptr, 0, NULL, 0, NULL TSRMLS_CC);
  1251. zval_dtor(&fname);
  1252. if (result == FAILURE) {
  1253. _DO_THROW("Invocation of method __toString() failed");
  1254. /* Returns from this function */
  1255. }
  1256. if (!retval_ptr) {
  1257. zend_error(E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name);
  1258. RETURN_FALSE;
  1259. }
  1260. if (return_output) {
  1261. COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
  1262. } else {
  1263. /* No need for _r variant, return of __toString should always be a string */
  1264. zend_print_zval(retval_ptr, 0);
  1265. zend_printf("\n");
  1266. zval_ptr_dtor(&retval_ptr);
  1267. }
  1268. }
  1269. /* }}} */
  1270. /* {{{ proto public static array Reflection::getModifierNames(int modifiers)
  1271. Returns an array of modifier names */
  1272. ZEND_METHOD(reflection, getModifierNames)
  1273. {
  1274. long modifiers;
  1275. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &modifiers) == FAILURE) {
  1276. return;
  1277. }
  1278. array_init(return_value);
  1279. if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
  1280. add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1, 1);
  1281. }
  1282. if (modifiers & (ZEND_ACC_FINAL | ZEND_ACC_FINAL_CLASS)) {
  1283. add_next_index_stringl(return_value, "final", sizeof("final")-1, 1);
  1284. }
  1285. if (modifiers & ZEND_ACC_IMPLICIT_PUBLIC) {
  1286. add_next_index_stringl(return_value, "public", sizeof("public")-1, 1);
  1287. }
  1288. /* These are mutually exclusive */
  1289. switch (modifiers & ZEND_ACC_PPP_MASK) {
  1290. case ZEND_ACC_PUBLIC:
  1291. add_next_index_stringl(return_value, "public", sizeof("public")-1, 1);
  1292. break;
  1293. case ZEND_ACC_PRIVATE:
  1294. add_next_index_stringl(return_value, "private", sizeof("private")-1, 1);
  1295. break;
  1296. case ZEND_ACC_PROTECTED:
  1297. add_next_index_stringl(return_value, "protected", sizeof("protected")-1, 1);
  1298. break;
  1299. }
  1300. if (modifiers & ZEND_ACC_STATIC) {
  1301. add_next_index_stringl(return_value, "static", sizeof("static")-1, 1);
  1302. }
  1303. }
  1304. /* }}} */
  1305. /* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return])
  1306. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  1307. ZEND_METHOD(reflection_function, export)
  1308. {
  1309. _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_function_ptr, 1);
  1310. }
  1311. /* }}} */
  1312. /* {{{ proto public void ReflectionFunction::__construct(string name)
  1313. Constructor. Throws an Exception in case the given function does not exist */
  1314. ZEND_METHOD(reflection_function, __construct)
  1315. {
  1316. zval *name;
  1317. zval *object;
  1318. zval *closure = NULL;
  1319. char *lcname;
  1320. reflection_object *intern;
  1321. zend_function *fptr;
  1322. char *name_str;
  1323. int name_len;
  1324. object = getThis();
  1325. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1326. if (intern == NULL) {
  1327. return;
  1328. }
  1329. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "O", &closure, zend_ce_closure) == SUCCESS) {
  1330. fptr = (zend_function*)zend_get_closure_method_def(closure TSRMLS_CC);
  1331. Z_ADDREF_P(closure);
  1332. } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == SUCCESS) {
  1333. char *nsname;
  1334. lcname = zend_str_tolower_dup(name_str, name_len);
  1335. /* Ignore leading "\" */
  1336. nsname = lcname;
  1337. if (lcname[0] == '\\') {
  1338. nsname = &lcname[1];
  1339. name_len--;
  1340. }
  1341. if (zend_hash_find(EG(function_table), nsname, name_len + 1, (void **)&fptr) == FAILURE) {
  1342. efree(lcname);
  1343. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1344. "Function %s() does not exist", name_str);
  1345. return;
  1346. }
  1347. efree(lcname);
  1348. } else {
  1349. return;
  1350. }
  1351. MAKE_STD_ZVAL(name);
  1352. ZVAL_STRING(name, fptr->common.function_name, 1);
  1353. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1354. intern->ptr = fptr;
  1355. intern->ref_type = REF_TYPE_FUNCTION;
  1356. intern->obj = closure;
  1357. intern->ce = NULL;
  1358. }
  1359. /* }}} */
  1360. /* {{{ proto public string ReflectionFunction::__toString()
  1361. Returns a string representation */
  1362. ZEND_METHOD(reflection_function, __toString)
  1363. {
  1364. reflection_object *intern;
  1365. zend_function *fptr;
  1366. string str;
  1367. if (zend_parse_parameters_none() == FAILURE) {
  1368. return;
  1369. }
  1370. GET_REFLECTION_OBJECT_PTR(fptr);
  1371. string_init(&str);
  1372. _function_string(&str, fptr, intern->ce, "" TSRMLS_CC);
  1373. RETURN_STRINGL(str.string, str.len - 1, 0);
  1374. }
  1375. /* }}} */
  1376. /* {{{ proto public string ReflectionFunction::getName()
  1377. Returns this function's name */
  1378. ZEND_METHOD(reflection_function, getName)
  1379. {
  1380. if (zend_parse_parameters_none() == FAILURE) {
  1381. return;
  1382. }
  1383. _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
  1384. }
  1385. /* }}} */
  1386. /* {{{ proto public bool ReflectionFunction::isClosure()
  1387. Returns whether this is a closure */
  1388. ZEND_METHOD(reflection_function, isClosure)
  1389. {
  1390. reflection_object *intern;
  1391. zend_function *fptr;
  1392. if (zend_parse_parameters_none() == FAILURE) {
  1393. return;
  1394. }
  1395. GET_REFLECTION_OBJECT_PTR(fptr);
  1396. RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
  1397. }
  1398. /* }}} */
  1399. /* {{{ proto public bool ReflectionFunction::isInternal()
  1400. Returns whether this is an internal function */
  1401. ZEND_METHOD(reflection_function, isInternal)
  1402. {
  1403. reflection_object *intern;
  1404. zend_function *fptr;
  1405. if (zend_parse_parameters_none() == FAILURE) {
  1406. return;
  1407. }
  1408. GET_REFLECTION_OBJECT_PTR(fptr);
  1409. RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
  1410. }
  1411. /* }}} */
  1412. /* {{{ proto public bool ReflectionFunction::isUserDefined()
  1413. Returns whether this is an user-defined function */
  1414. ZEND_METHOD(reflection_function, isUserDefined)
  1415. {
  1416. reflection_object *intern;
  1417. zend_function *fptr;
  1418. if (zend_parse_parameters_none() == FAILURE) {
  1419. return;
  1420. }
  1421. GET_REFLECTION_OBJECT_PTR(fptr);
  1422. RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
  1423. }
  1424. /* }}} */
  1425. /* {{{ proto public bool ReflectionFunction::isDisabled()
  1426. Returns whether this function has been disabled or not */
  1427. ZEND_METHOD(reflection_function, isDisabled)
  1428. {
  1429. reflection_object *intern;
  1430. zend_function *fptr;
  1431. METHOD_NOTSTATIC(reflection_function_ptr);
  1432. GET_REFLECTION_OBJECT_PTR(fptr);
  1433. RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
  1434. }
  1435. /* }}} */
  1436. /* {{{ proto public string ReflectionFunction::getFileName()
  1437. Returns the filename of the file this function was declared in */
  1438. ZEND_METHOD(reflection_function, getFileName)
  1439. {
  1440. reflection_object *intern;
  1441. zend_function *fptr;
  1442. if (zend_parse_parameters_none() == FAILURE) {
  1443. return;
  1444. }
  1445. GET_REFLECTION_OBJECT_PTR(fptr);
  1446. if (fptr->type == ZEND_USER_FUNCTION) {
  1447. RETURN_STRING(fptr->op_array.filename, 1);
  1448. }
  1449. RETURN_FALSE;
  1450. }
  1451. /* }}} */
  1452. /* {{{ proto public int ReflectionFunction::getStartLine()
  1453. Returns the line this function's declaration starts at */
  1454. ZEND_METHOD(reflection_function, getStartLine)
  1455. {
  1456. reflection_object *intern;
  1457. zend_function *fptr;
  1458. if (zend_parse_parameters_none() == FAILURE) {
  1459. return;
  1460. }
  1461. GET_REFLECTION_OBJECT_PTR(fptr);
  1462. if (fptr->type == ZEND_USER_FUNCTION) {
  1463. RETURN_LONG(fptr->op_array.line_start);
  1464. }
  1465. RETURN_FALSE;
  1466. }
  1467. /* }}} */
  1468. /* {{{ proto public int ReflectionFunction::getEndLine()
  1469. Returns the line this function's declaration ends at */
  1470. ZEND_METHOD(reflection_function, getEndLine)
  1471. {
  1472. reflection_object *intern;
  1473. zend_function *fptr;
  1474. if (zend_parse_parameters_none() == FAILURE) {
  1475. return;
  1476. }
  1477. GET_REFLECTION_OBJECT_PTR(fptr);
  1478. if (fptr->type == ZEND_USER_FUNCTION) {
  1479. RETURN_LONG(fptr->op_array.line_end);
  1480. }
  1481. RETURN_FALSE;
  1482. }
  1483. /* }}} */
  1484. /* {{{ proto public string ReflectionFunction::getDocComment()
  1485. Returns the doc comment for this function */
  1486. ZEND_METHOD(reflection_function, getDocComment)
  1487. {
  1488. reflection_object *intern;
  1489. zend_function *fptr;
  1490. if (zend_parse_parameters_none() == FAILURE) {
  1491. return;
  1492. }
  1493. GET_REFLECTION_OBJECT_PTR(fptr);
  1494. if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
  1495. RETURN_STRINGL(fptr->op_array.doc_comment, fptr->op_array.doc_comment_len, 1);
  1496. }
  1497. RETURN_FALSE;
  1498. }
  1499. /* }}} */
  1500. /* {{{ proto public array ReflectionFunction::getStaticVariables()
  1501. Returns an associative array containing this function's static variables and their values */
  1502. ZEND_METHOD(reflection_function, getStaticVariables)
  1503. {
  1504. zval *tmp_copy;
  1505. reflection_object *intern;
  1506. zend_function *fptr;
  1507. if (zend_parse_parameters_none() == FAILURE) {
  1508. return;
  1509. }
  1510. GET_REFLECTION_OBJECT_PTR(fptr);
  1511. /* Return an empty array in case no static variables exist */
  1512. array_init(return_value);
  1513. if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
  1514. zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
  1515. zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
  1516. }
  1517. }
  1518. /* }}} */
  1519. /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args])
  1520. Invokes the function */
  1521. ZEND_METHOD(reflection_function, invoke)
  1522. {
  1523. zval *retval_ptr;
  1524. zval ***params = NULL;
  1525. int result, num_args = 0;
  1526. zend_fcall_info fci;
  1527. zend_fcall_info_cache fcc;
  1528. reflection_object *intern;
  1529. zend_function *fptr;
  1530. METHOD_NOTSTATIC(reflection_function_ptr);
  1531. GET_REFLECTION_OBJECT_PTR(fptr);
  1532. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &params, &num_args) == FAILURE) {
  1533. return;
  1534. }
  1535. fci.size = sizeof(fci);
  1536. fci.function_table = NULL;
  1537. fci.function_name = NULL;
  1538. fci.symbol_table = NULL;
  1539. fci.object_ptr = NULL;
  1540. fci.retval_ptr_ptr = &retval_ptr;
  1541. fci.param_count = num_args;
  1542. fci.params = params;
  1543. fci.no_separation = 1;
  1544. fcc.initialized = 1;
  1545. fcc.function_handler = fptr;
  1546. fcc.calling_scope = EG(scope);
  1547. fcc.called_scope = NULL;
  1548. fcc.object_ptr = NULL;
  1549. result = zend_call_function(&fci, &fcc TSRMLS_CC);
  1550. if (num_args) {
  1551. efree(params);
  1552. }
  1553. if (result == FAILURE) {
  1554. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1555. "Invocation of function %s() failed", fptr->common.function_name);
  1556. return;
  1557. }
  1558. if (retval_ptr) {
  1559. COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
  1560. }
  1561. }
  1562. /* }}} */
  1563. static int _zval_array_to_c_array(zval **arg, zval ****params TSRMLS_DC) /* {{{ */
  1564. {
  1565. *(*params)++ = arg;
  1566. return ZEND_HASH_APPLY_KEEP;
  1567. } /* }}} */
  1568. /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args)
  1569. Invokes the function and pass its arguments as array. */
  1570. ZEND_METHOD(reflection_function, invokeArgs)
  1571. {
  1572. zval *retval_ptr;
  1573. zval ***params;
  1574. int result;
  1575. int argc;
  1576. zend_fcall_info fci;
  1577. zend_fcall_info_cache fcc;
  1578. reflection_object *intern;
  1579. zend_function *fptr;
  1580. zval *param_array;
  1581. METHOD_NOTSTATIC(reflection_function_ptr);
  1582. GET_REFLECTION_OBJECT_PTR(fptr);
  1583. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &param_array) == FAILURE) {
  1584. return;
  1585. }
  1586. argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
  1587. params = safe_emalloc(sizeof(zval **), argc, 0);
  1588. zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
  1589. params -= argc;
  1590. fci.size = sizeof(fci);
  1591. fci.function_table = NULL;
  1592. fci.function_name = NULL;
  1593. fci.symbol_table = NULL;
  1594. fci.object_ptr = NULL;
  1595. fci.retval_ptr_ptr = &retval_ptr;
  1596. fci.param_count = argc;
  1597. fci.params = params;
  1598. fci.no_separation = 1;
  1599. fcc.initialized = 1;
  1600. fcc.function_handler = fptr;
  1601. fcc.calling_scope = EG(scope);
  1602. fcc.called_scope = NULL;
  1603. fcc.object_ptr = NULL;
  1604. result = zend_call_function(&fci, &fcc TSRMLS_CC);
  1605. efree(params);
  1606. if (result == FAILURE) {
  1607. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1608. "Invocation of function %s() failed", fptr->common.function_name);
  1609. return;
  1610. }
  1611. if (retval_ptr) {
  1612. COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
  1613. }
  1614. }
  1615. /* }}} */
  1616. /* {{{ proto public bool ReflectionFunction::returnsReference()
  1617. Gets whether this function returns a reference */
  1618. ZEND_METHOD(reflection_function, returnsReference)
  1619. {
  1620. reflection_object *intern;
  1621. zend_function *fptr;
  1622. METHOD_NOTSTATIC(reflection_function_abstract_ptr);
  1623. GET_REFLECTION_OBJECT_PTR(fptr);
  1624. RETURN_BOOL(fptr->op_array.return_reference);
  1625. }
  1626. /* }}} */
  1627. /* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
  1628. Gets the number of required parameters */
  1629. ZEND_METHOD(reflection_function, getNumberOfParameters)
  1630. {
  1631. reflection_object *intern;
  1632. zend_function *fptr;
  1633. METHOD_NOTSTATIC(reflection_function_abstract_ptr);
  1634. GET_REFLECTION_OBJECT_PTR(fptr);
  1635. RETURN_LONG(fptr->common.num_args);
  1636. }
  1637. /* }}} */
  1638. /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
  1639. Gets the number of required parameters */
  1640. ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
  1641. {
  1642. reflection_object *intern;
  1643. zend_function *fptr;
  1644. METHOD_NOTSTATIC(reflection_function_abstract_ptr);
  1645. GET_REFLECTION_OBJECT_PTR(fptr);
  1646. RETURN_LONG(fptr->common.required_num_args);
  1647. }
  1648. /* }}} */
  1649. /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
  1650. Returns an array of parameter objects for this function */
  1651. ZEND_METHOD(reflection_function, getParameters)
  1652. {
  1653. reflection_object *intern;
  1654. zend_function *fptr;
  1655. zend_uint i;
  1656. struct _zend_arg_info *arg_info;
  1657. METHOD_NOTSTATIC(reflection_function_abstract_ptr);
  1658. GET_REFLECTION_OBJECT_PTR(fptr);
  1659. arg_info= fptr->common.arg_info;
  1660. array_init(return_value);
  1661. for (i = 0; i < fptr->common.num_args; i++) {
  1662. zval *parameter;
  1663. ALLOC_ZVAL(parameter);
  1664. reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), intern->obj, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
  1665. add_next_index_zval(return_value, parameter);
  1666. arg_info++;
  1667. }
  1668. }
  1669. /* }}} */
  1670. /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension()
  1671. Returns NULL or the extension the function belongs to */
  1672. ZEND_METHOD(reflection_function, getExtension)
  1673. {
  1674. reflection_object *intern;
  1675. zend_function *fptr;
  1676. zend_internal_function *internal;
  1677. METHOD_NOTSTATIC(reflection_function_abstract_ptr);
  1678. GET_REFLECTION_OBJECT_PTR(fptr);
  1679. if (fptr->type != ZEND_INTERNAL_FUNCTION) {
  1680. RETURN_NULL();
  1681. }
  1682. internal = (zend_internal_function *)fptr;
  1683. if (internal->module) {
  1684. reflection_extension_factory(return_value, internal->module->name TSRMLS_CC);
  1685. } else {
  1686. RETURN_NULL();
  1687. }
  1688. }
  1689. /* }}} */
  1690. /* {{{ proto public string|false ReflectionFunction::getExtensionName()
  1691. Returns false or the name of the extension the function belongs to */
  1692. ZEND_METHOD(reflection_function, getExtensionName)
  1693. {
  1694. reflection_object *intern;
  1695. zend_function *fptr;
  1696. zend_internal_function *internal;
  1697. METHOD_NOTSTATIC(reflection_function_abstract_ptr);
  1698. GET_REFLECTION_OBJECT_PTR(fptr);
  1699. if (fptr->type != ZEND_INTERNAL_FUNCTION) {
  1700. RETURN_FALSE;
  1701. }
  1702. internal = (zend_internal_function *)fptr;
  1703. if (internal->module) {
  1704. RETURN_STRING(internal->module->name, 1);
  1705. } else {
  1706. RETURN_FALSE;
  1707. }
  1708. }
  1709. /* }}} */
  1710. /* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException
  1711. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  1712. ZEND_METHOD(reflection_parameter, export)
  1713. {
  1714. _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_parameter_ptr, 2);
  1715. }
  1716. /* }}} */
  1717. /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter)
  1718. Constructor. Throws an Exception in case the given method does not exist */
  1719. ZEND_METHOD(reflection_parameter, __construct)
  1720. {
  1721. parameter_reference *ref;
  1722. zval *reference, **parameter;
  1723. zval *object;
  1724. zval *name;
  1725. reflection_object *intern;
  1726. zend_function *fptr;
  1727. struct _zend_arg_info *arg_info;
  1728. int position;
  1729. zend_class_entry *ce = NULL;
  1730. zend_bool is_closure = 0;
  1731. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zZ", &reference, &parameter) == FAILURE) {
  1732. return;
  1733. }
  1734. object = getThis();
  1735. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  1736. if (intern == NULL) {
  1737. return;
  1738. }
  1739. /* First, find the function */
  1740. switch (Z_TYPE_P(reference)) {
  1741. case IS_STRING: {
  1742. unsigned int lcname_len;
  1743. char *lcname;
  1744. lcname_len = Z_STRLEN_P(reference);
  1745. lcname = zend_str_tolower_dup(Z_STRVAL_P(reference), lcname_len);
  1746. if (zend_hash_find(EG(function_table), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
  1747. efree(lcname);
  1748. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1749. "Function %s() does not exist", Z_STRVAL_P(reference));
  1750. return;
  1751. }
  1752. efree(lcname);
  1753. }
  1754. ce = fptr->common.scope;
  1755. break;
  1756. case IS_ARRAY: {
  1757. zval **classref;
  1758. zval **method;
  1759. zend_class_entry **pce;
  1760. unsigned int lcname_len;
  1761. char *lcname;
  1762. if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
  1763. || (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE))
  1764. {
  1765. _DO_THROW("Expected array($object, $method) or array($classname, $method)");
  1766. /* returns out of this function */
  1767. }
  1768. if (Z_TYPE_PP(classref) == IS_OBJECT) {
  1769. ce = Z_OBJCE_PP(classref);
  1770. } else {
  1771. convert_to_string_ex(classref);
  1772. if (zend_lookup_class(Z_STRVAL_PP(classref), Z_STRLEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
  1773. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1774. "Class %s does not exist", Z_STRVAL_PP(classref));
  1775. return;
  1776. }
  1777. ce = *pce;
  1778. }
  1779. convert_to_string_ex(method);
  1780. lcname_len = Z_STRLEN_PP(method);
  1781. lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), lcname_len);
  1782. if (ce == zend_ce_closure && Z_TYPE_PP(classref) == IS_OBJECT
  1783. && (lcname_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
  1784. && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  1785. && (fptr = zend_get_closure_invoke_method(*classref TSRMLS_CC)) != NULL)
  1786. {
  1787. /* nothign to do. don't set is_closure since is the invoke handler,
  1788. not the closure itself */
  1789. } else if (zend_hash_find(&ce->function_table, lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
  1790. efree(lcname);
  1791. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1792. "Method %s::%s() does not exist", ce->name, Z_STRVAL_PP(method));
  1793. return;
  1794. }
  1795. efree(lcname);
  1796. }
  1797. break;
  1798. case IS_OBJECT: {
  1799. ce = Z_OBJCE_P(reference);
  1800. if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
  1801. fptr = (zend_function *)zend_get_closure_method_def(reference TSRMLS_CC);
  1802. Z_ADDREF_P(reference);
  1803. is_closure = 1;
  1804. } else if (zend_hash_find(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME), (void **)&fptr) == FAILURE) {
  1805. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1806. "Method %s::%s() does not exist", ce->name, ZEND_INVOKE_FUNC_NAME);
  1807. return;
  1808. }
  1809. }
  1810. break;
  1811. default:
  1812. _DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
  1813. /* returns out of this function */
  1814. }
  1815. /* Now, search for the parameter */
  1816. arg_info = fptr->common.arg_info;
  1817. if (Z_TYPE_PP(parameter) == IS_LONG) {
  1818. position= Z_LVAL_PP(parameter);
  1819. if (position < 0 || (zend_uint)position >= fptr->common.num_args) {
  1820. if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
  1821. if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
  1822. efree(fptr->common.function_name);
  1823. }
  1824. efree(fptr);
  1825. }
  1826. if (is_closure) {
  1827. zval_ptr_dtor(&reference);
  1828. }
  1829. _DO_THROW("The parameter specified by its offset could not be found");
  1830. /* returns out of this function */
  1831. }
  1832. } else {
  1833. zend_uint i;
  1834. position= -1;
  1835. convert_to_string_ex(parameter);
  1836. for (i = 0; i < fptr->common.num_args; i++) {
  1837. if (arg_info[i].name && strcmp(arg_info[i].name, Z_STRVAL_PP(parameter)) == 0) {
  1838. position= i;
  1839. break;
  1840. }
  1841. }
  1842. if (position == -1) {
  1843. if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
  1844. if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
  1845. efree(fptr->common.function_name);
  1846. }
  1847. efree(fptr);
  1848. }
  1849. if (is_closure) {
  1850. zval_ptr_dtor(&reference);
  1851. }
  1852. _DO_THROW("The parameter specified by its name could not be found");
  1853. /* returns out of this function */
  1854. }
  1855. }
  1856. MAKE_STD_ZVAL(name);
  1857. if (arg_info[position].name) {
  1858. ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
  1859. } else {
  1860. ZVAL_NULL(name);
  1861. }
  1862. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  1863. ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
  1864. ref->arg_info = &arg_info[position];
  1865. ref->offset = (zend_uint)position;
  1866. ref->required = fptr->common.required_num_args;
  1867. ref->fptr = fptr;
  1868. /* TODO: copy fptr */
  1869. intern->ptr = ref;
  1870. intern->ref_type = REF_TYPE_PARAMETER;
  1871. intern->ce = ce;
  1872. if (reference && is_closure) {
  1873. intern->obj = reference;
  1874. }
  1875. }
  1876. /* }}} */
  1877. /* {{{ proto public string ReflectionParameter::__toString()
  1878. Returns a string representation */
  1879. ZEND_METHOD(reflection_parameter, __toString)
  1880. {
  1881. reflection_object *intern;
  1882. parameter_reference *param;
  1883. string str;
  1884. if (zend_parse_parameters_none() == FAILURE) {
  1885. return;
  1886. }
  1887. GET_REFLECTION_OBJECT_PTR(param);
  1888. string_init(&str);
  1889. _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC);
  1890. RETURN_STRINGL(str.string, str.len - 1, 0);
  1891. }
  1892. /* }}} */
  1893. /* {{{ proto public string ReflectionParameter::getName()
  1894. Returns this parameters's name */
  1895. ZEND_METHOD(reflection_parameter, getName)
  1896. {
  1897. if (zend_parse_parameters_none() == FAILURE) {
  1898. return;
  1899. }
  1900. _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
  1901. }
  1902. /* }}} */
  1903. /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction()
  1904. Returns the ReflectionFunction for the function of this parameter */
  1905. ZEND_METHOD(reflection_parameter, getDeclaringFunction)
  1906. {
  1907. reflection_object *intern;
  1908. parameter_reference *param;
  1909. if (zend_parse_parameters_none() == FAILURE) {
  1910. return;
  1911. }
  1912. GET_REFLECTION_OBJECT_PTR(param);
  1913. if (!param->fptr->common.scope) {
  1914. reflection_function_factory(_copy_function(param->fptr TSRMLS_CC), intern->obj, return_value TSRMLS_CC);
  1915. } else {
  1916. reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr TSRMLS_CC), intern->obj, return_value TSRMLS_CC);
  1917. }
  1918. }
  1919. /* }}} */
  1920. /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
  1921. Returns in which class this parameter is defined (not the typehint of the parameter) */
  1922. ZEND_METHOD(reflection_parameter, getDeclaringClass)
  1923. {
  1924. reflection_object *intern;
  1925. parameter_reference *param;
  1926. if (zend_parse_parameters_none() == FAILURE) {
  1927. return;
  1928. }
  1929. GET_REFLECTION_OBJECT_PTR(param);
  1930. if (param->fptr->common.scope) {
  1931. zend_reflection_class_factory(param->fptr->common.scope, return_value TSRMLS_CC);
  1932. }
  1933. }
  1934. /* }}} */
  1935. /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass()
  1936. Returns this parameters's class hint or NULL if there is none */
  1937. ZEND_METHOD(reflection_parameter, getClass)
  1938. {
  1939. reflection_object *intern;
  1940. parameter_reference *param;
  1941. zend_class_entry **pce, *ce;
  1942. if (zend_parse_parameters_none() == FAILURE) {
  1943. return;
  1944. }
  1945. GET_REFLECTION_OBJECT_PTR(param);
  1946. if (param->arg_info->class_name) {
  1947. /* Class name is stored as a string, we might also get "self" or "parent"
  1948. * - For "self", simply use the function scope. If scope is NULL then
  1949. * the function is global and thus self does not make any sense
  1950. *
  1951. * - For "parent", use the function scope's parent. If scope is NULL then
  1952. * the function is global and thus parent does not make any sense.
  1953. * If the parent is NULL then the class does not extend anything and
  1954. * thus parent does not make any sense, either.
  1955. *
  1956. * TODO: Think about moving these checks to the compiler or some sort of
  1957. * lint-mode.
  1958. */
  1959. if (0 == strncmp(param->arg_info->class_name, "self", sizeof("self")- 1)) {
  1960. ce = param->fptr->common.scope;
  1961. if (!ce) {
  1962. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1963. "Parameter uses 'self' as type hint but function is not a class member!");
  1964. return;
  1965. }
  1966. pce= &ce;
  1967. } else if (0 == strncmp(param->arg_info->class_name, "parent", sizeof("parent")- 1)) {
  1968. ce = param->fptr->common.scope;
  1969. if (!ce) {
  1970. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1971. "Parameter uses 'parent' as type hint but function is not a class member!");
  1972. return;
  1973. }
  1974. if (!ce->parent) {
  1975. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1976. "Parameter uses 'parent' as type hint although class does not have a parent!");
  1977. return;
  1978. }
  1979. pce= &ce->parent;
  1980. } else if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) {
  1981. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  1982. "Class %s does not exist", param->arg_info->class_name);
  1983. return;
  1984. }
  1985. zend_reflection_class_factory(*pce, return_value TSRMLS_CC);
  1986. }
  1987. }
  1988. /* }}} */
  1989. /* {{{ proto public bool ReflectionParameter::isArray()
  1990. Returns whether parameter MUST be an array */
  1991. ZEND_METHOD(reflection_parameter, isArray)
  1992. {
  1993. reflection_object *intern;
  1994. parameter_reference *param;
  1995. if (zend_parse_parameters_none() == FAILURE) {
  1996. return;
  1997. }
  1998. GET_REFLECTION_OBJECT_PTR(param);
  1999. RETVAL_BOOL(param->arg_info->array_type_hint);
  2000. }
  2001. /* }}} */
  2002. /* {{{ proto public bool ReflectionParameter::allowsNull()
  2003. Returns whether NULL is allowed as this parameters's value */
  2004. ZEND_METHOD(reflection_parameter, allowsNull)
  2005. {
  2006. reflection_object *intern;
  2007. parameter_reference *param;
  2008. if (zend_parse_parameters_none() == FAILURE) {
  2009. return;
  2010. }
  2011. GET_REFLECTION_OBJECT_PTR(param);
  2012. RETVAL_BOOL(param->arg_info->allow_null);
  2013. }
  2014. /* }}} */
  2015. /* {{{ proto public bool ReflectionParameter::isPassedByReference()
  2016. Returns whether this parameters is passed to by reference */
  2017. ZEND_METHOD(reflection_parameter, isPassedByReference)
  2018. {
  2019. reflection_object *intern;
  2020. parameter_reference *param;
  2021. if (zend_parse_parameters_none() == FAILURE) {
  2022. return;
  2023. }
  2024. GET_REFLECTION_OBJECT_PTR(param);
  2025. RETVAL_BOOL(param->arg_info->pass_by_reference);
  2026. }
  2027. /* }}} */
  2028. /* {{{ proto public bool ReflectionParameter::getPosition()
  2029. Returns whether this parameter is an optional parameter */
  2030. ZEND_METHOD(reflection_parameter, getPosition)
  2031. {
  2032. reflection_object *intern;
  2033. parameter_reference *param;
  2034. if (zend_parse_parameters_none() == FAILURE) {
  2035. return;
  2036. }
  2037. GET_REFLECTION_OBJECT_PTR(param);
  2038. RETVAL_LONG(param->offset);
  2039. }
  2040. /* }}} */
  2041. /* {{{ proto public bool ReflectionParameter::isOptional()
  2042. Returns whether this parameter is an optional parameter */
  2043. ZEND_METHOD(reflection_parameter, isOptional)
  2044. {
  2045. reflection_object *intern;
  2046. parameter_reference *param;
  2047. if (zend_parse_parameters_none() == FAILURE) {
  2048. return;
  2049. }
  2050. GET_REFLECTION_OBJECT_PTR(param);
  2051. RETVAL_BOOL(param->offset >= param->required);
  2052. }
  2053. /* }}} */
  2054. /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
  2055. Returns whether the default value of this parameter is available */
  2056. ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
  2057. {
  2058. reflection_object *intern;
  2059. parameter_reference *param;
  2060. zend_op *precv;
  2061. if (zend_parse_parameters_none() == FAILURE) {
  2062. return;
  2063. }
  2064. GET_REFLECTION_OBJECT_PTR(param);
  2065. if (param->fptr->type != ZEND_USER_FUNCTION)
  2066. {
  2067. RETURN_FALSE;
  2068. }
  2069. if (param->offset < param->required) {
  2070. RETURN_FALSE;
  2071. }
  2072. precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
  2073. if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
  2074. RETURN_FALSE;
  2075. }
  2076. RETURN_TRUE;
  2077. }
  2078. /* }}} */
  2079. /* {{{ proto public bool ReflectionParameter::getDefaultValue()
  2080. Returns the default value of this parameter or throws an exception */
  2081. ZEND_METHOD(reflection_parameter, getDefaultValue)
  2082. {
  2083. reflection_object *intern;
  2084. parameter_reference *param;
  2085. zend_op *precv;
  2086. if (zend_parse_parameters_none() == FAILURE) {
  2087. return;
  2088. }
  2089. GET_REFLECTION_OBJECT_PTR(param);
  2090. if (param->fptr->type != ZEND_USER_FUNCTION)
  2091. {
  2092. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
  2093. return;
  2094. }
  2095. if (param->offset < param->required) {
  2096. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional");
  2097. return;
  2098. }
  2099. precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
  2100. if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
  2101. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error");
  2102. return;
  2103. }
  2104. *return_value = precv->op2.u.constant;
  2105. INIT_PZVAL(return_value);
  2106. if (Z_TYPE_P(return_value) != IS_CONSTANT) {
  2107. zval_copy_ctor(return_value);
  2108. }
  2109. zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC);
  2110. }
  2111. /* }}} */
  2112. /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
  2113. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  2114. ZEND_METHOD(reflection_method, export)
  2115. {
  2116. _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_method_ptr, 2);
  2117. }
  2118. /* }}} */
  2119. /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name])
  2120. Constructor. Throws an Exception in case the given method does not exist */
  2121. ZEND_METHOD(reflection_method, __construct)
  2122. {
  2123. zval *name, *classname;
  2124. zval *object, *orig_obj;
  2125. reflection_object *intern;
  2126. char *lcname;
  2127. zend_class_entry **pce;
  2128. zend_class_entry *ce;
  2129. zend_function *mptr;
  2130. char *name_str, *tmp;
  2131. int name_len, tmp_len;
  2132. zval ztmp;
  2133. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
  2134. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
  2135. return;
  2136. }
  2137. if ((tmp = strstr(name_str, "::")) == NULL) {
  2138. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Invalid method name %s", name_str);
  2139. return;
  2140. }
  2141. classname = &ztmp;
  2142. tmp_len = tmp - name_str;
  2143. ZVAL_STRINGL(classname, name_str, tmp_len, 1);
  2144. name_len = name_len - (tmp_len + 2);
  2145. name_str = tmp + 2;
  2146. orig_obj = NULL;
  2147. } else if (Z_TYPE_P(classname) == IS_OBJECT) {
  2148. orig_obj = classname;
  2149. } else {
  2150. orig_obj = NULL;
  2151. }
  2152. object = getThis();
  2153. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  2154. if (intern == NULL) {
  2155. return;
  2156. }
  2157. /* Find the class entry */
  2158. switch (Z_TYPE_P(classname)) {
  2159. case IS_STRING:
  2160. if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
  2161. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2162. "Class %s does not exist", Z_STRVAL_P(classname));
  2163. if (classname == &ztmp) {
  2164. zval_dtor(&ztmp);
  2165. }
  2166. return;
  2167. }
  2168. ce = *pce;
  2169. break;
  2170. case IS_OBJECT:
  2171. ce = Z_OBJCE_P(classname);
  2172. break;
  2173. default:
  2174. if (classname == &ztmp) {
  2175. zval_dtor(&ztmp);
  2176. }
  2177. _DO_THROW("The parameter class is expected to be either a string or an object");
  2178. /* returns out of this function */
  2179. }
  2180. if (classname == &ztmp) {
  2181. zval_dtor(&ztmp);
  2182. }
  2183. lcname = zend_str_tolower_dup(name_str, name_len);
  2184. if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
  2185. && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  2186. && (mptr = zend_get_closure_invoke_method(orig_obj TSRMLS_CC)) != NULL)
  2187. {
  2188. /* do nothing, mptr already set */
  2189. } else if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
  2190. efree(lcname);
  2191. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2192. "Method %s::%s() does not exist", ce->name, name_str);
  2193. return;
  2194. }
  2195. efree(lcname);
  2196. MAKE_STD_ZVAL(classname);
  2197. ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1);
  2198. zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
  2199. MAKE_STD_ZVAL(name);
  2200. ZVAL_STRING(name, mptr->common.function_name, 1);
  2201. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  2202. intern->ptr = mptr;
  2203. intern->ref_type = REF_TYPE_FUNCTION;
  2204. intern->ce = ce;
  2205. }
  2206. /* }}} */
  2207. /* {{{ proto public string ReflectionMethod::__toString()
  2208. Returns a string representation */
  2209. ZEND_METHOD(reflection_method, __toString)
  2210. {
  2211. reflection_object *intern;
  2212. zend_function *mptr;
  2213. string str;
  2214. if (zend_parse_parameters_none() == FAILURE) {
  2215. return;
  2216. }
  2217. GET_REFLECTION_OBJECT_PTR(mptr);
  2218. string_init(&str);
  2219. _function_string(&str, mptr, intern->ce, "" TSRMLS_CC);
  2220. RETURN_STRINGL(str.string, str.len - 1, 0);
  2221. }
  2222. /* }}} */
  2223. /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
  2224. Invokes the method. */
  2225. ZEND_METHOD(reflection_method, invoke)
  2226. {
  2227. zval *retval_ptr;
  2228. zval ***params = NULL;
  2229. zval *object_ptr;
  2230. reflection_object *intern;
  2231. zend_function *mptr;
  2232. int result, num_args = 0;
  2233. zend_fcall_info fci;
  2234. zend_fcall_info_cache fcc;
  2235. zend_class_entry *obj_ce;
  2236. METHOD_NOTSTATIC(reflection_method_ptr);
  2237. GET_REFLECTION_OBJECT_PTR(mptr);
  2238. if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
  2239. || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
  2240. {
  2241. if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
  2242. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2243. "Trying to invoke abstract method %s::%s()",
  2244. mptr->common.scope->name, mptr->common.function_name);
  2245. } else {
  2246. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2247. "Trying to invoke %s method %s::%s() from scope %s",
  2248. mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
  2249. mptr->common.scope->name, mptr->common.function_name,
  2250. Z_OBJCE_P(getThis())->name);
  2251. }
  2252. return;
  2253. }
  2254. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &params, &num_args) == FAILURE) {
  2255. return;
  2256. }
  2257. /* In case this is a static method, we should'nt pass an object_ptr
  2258. * (which is used as calling context aka $this). We can thus ignore the
  2259. * first parameter.
  2260. *
  2261. * Else, we verify that the given object is an instance of the class.
  2262. */
  2263. if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
  2264. object_ptr = NULL;
  2265. obj_ce = mptr->common.scope;
  2266. } else {
  2267. if (Z_TYPE_PP(params[0]) != IS_OBJECT) {
  2268. efree(params);
  2269. _DO_THROW("Non-object passed to Invoke()");
  2270. /* Returns from this function */
  2271. }
  2272. obj_ce = Z_OBJCE_PP(params[0]);
  2273. if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
  2274. if (params) {
  2275. efree(params);
  2276. }
  2277. _DO_THROW("Given object is not an instance of the class this method was declared in");
  2278. /* Returns from this function */
  2279. }
  2280. object_ptr = *params[0];
  2281. }
  2282. fci.size = sizeof(fci);
  2283. fci.function_table = NULL;
  2284. fci.function_name = NULL;
  2285. fci.symbol_table = NULL;
  2286. fci.object_ptr = object_ptr;
  2287. fci.retval_ptr_ptr = &retval_ptr;
  2288. fci.param_count = num_args - 1;
  2289. fci.params = params + 1;
  2290. fci.no_separation = 1;
  2291. fcc.initialized = 1;
  2292. fcc.function_handler = mptr;
  2293. fcc.calling_scope = obj_ce;
  2294. fcc.called_scope = obj_ce;
  2295. fcc.object_ptr = object_ptr;
  2296. result = zend_call_function(&fci, &fcc TSRMLS_CC);
  2297. if (params) {
  2298. efree(params);
  2299. }
  2300. if (result == FAILURE) {
  2301. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2302. "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
  2303. return;
  2304. }
  2305. if (retval_ptr) {
  2306. COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
  2307. }
  2308. }
  2309. /* }}} */
  2310. /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
  2311. Invokes the function and pass its arguments as array. */
  2312. ZEND_METHOD(reflection_method, invokeArgs)
  2313. {
  2314. zval *retval_ptr;
  2315. zval ***params;
  2316. zval *object;
  2317. reflection_object *intern;
  2318. zend_function *mptr;
  2319. int argc;
  2320. int result;
  2321. zend_fcall_info fci;
  2322. zend_fcall_info_cache fcc;
  2323. zend_class_entry *obj_ce;
  2324. zval *param_array;
  2325. METHOD_NOTSTATIC(reflection_method_ptr);
  2326. GET_REFLECTION_OBJECT_PTR(mptr);
  2327. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a", &object, &param_array) == FAILURE) {
  2328. return;
  2329. }
  2330. if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
  2331. || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
  2332. {
  2333. if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
  2334. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2335. "Trying to invoke abstract method %s::%s",
  2336. mptr->common.scope->name, mptr->common.function_name);
  2337. } else {
  2338. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2339. "Trying to invoke %s method %s::%s from scope %s",
  2340. mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
  2341. mptr->common.scope->name, mptr->common.function_name,
  2342. Z_OBJCE_P(getThis())->name);
  2343. }
  2344. return;
  2345. }
  2346. argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
  2347. params = safe_emalloc(sizeof(zval **), argc, 0);
  2348. zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
  2349. params -= argc;
  2350. /* In case this is a static method, we should'nt pass an object_ptr
  2351. * (which is used as calling context aka $this). We can thus ignore the
  2352. * first parameter.
  2353. *
  2354. * Else, we verify that the given object is an instance of the class.
  2355. */
  2356. if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
  2357. object = NULL;
  2358. obj_ce = mptr->common.scope;
  2359. } else {
  2360. if (!object) {
  2361. efree(params);
  2362. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2363. "Trying to invoke non static method %s::%s without an object",
  2364. mptr->common.scope->name, mptr->common.function_name);
  2365. return;
  2366. }
  2367. obj_ce = Z_OBJCE_P(object);
  2368. if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
  2369. efree(params);
  2370. _DO_THROW("Given object is not an instance of the class this method was declared in");
  2371. /* Returns from this function */
  2372. }
  2373. }
  2374. fci.size = sizeof(fci);
  2375. fci.function_table = NULL;
  2376. fci.function_name = NULL;
  2377. fci.symbol_table = NULL;
  2378. fci.object_ptr = object;
  2379. fci.retval_ptr_ptr = &retval_ptr;
  2380. fci.param_count = argc;
  2381. fci.params = params;
  2382. fci.no_separation = 1;
  2383. fcc.initialized = 1;
  2384. fcc.function_handler = mptr;
  2385. fcc.calling_scope = obj_ce;
  2386. fcc.called_scope = obj_ce;
  2387. fcc.object_ptr = object;
  2388. result = zend_call_function(&fci, &fcc TSRMLS_CC);
  2389. efree(params);
  2390. if (result == FAILURE) {
  2391. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2392. "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
  2393. return;
  2394. }
  2395. if (retval_ptr) {
  2396. COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
  2397. }
  2398. }
  2399. /* }}} */
  2400. /* {{{ proto public bool ReflectionMethod::isFinal()
  2401. Returns whether this method is final */
  2402. ZEND_METHOD(reflection_method, isFinal)
  2403. {
  2404. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
  2405. }
  2406. /* }}} */
  2407. /* {{{ proto public bool ReflectionMethod::isAbstract()
  2408. Returns whether this method is abstract */
  2409. ZEND_METHOD(reflection_method, isAbstract)
  2410. {
  2411. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
  2412. }
  2413. /* }}} */
  2414. /* {{{ proto public bool ReflectionMethod::isPublic()
  2415. Returns whether this method is public */
  2416. ZEND_METHOD(reflection_method, isPublic)
  2417. {
  2418. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
  2419. }
  2420. /* }}} */
  2421. /* {{{ proto public bool ReflectionMethod::isPrivate()
  2422. Returns whether this method is private */
  2423. ZEND_METHOD(reflection_method, isPrivate)
  2424. {
  2425. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
  2426. }
  2427. /* }}} */
  2428. /* {{{ proto public bool ReflectionMethod::isProtected()
  2429. Returns whether this method is protected */
  2430. ZEND_METHOD(reflection_method, isProtected)
  2431. {
  2432. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
  2433. }
  2434. /* }}} */
  2435. /* {{{ proto public bool ReflectionMethod::isStatic()
  2436. Returns whether this method is static */
  2437. ZEND_METHOD(reflection_method, isStatic)
  2438. {
  2439. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
  2440. }
  2441. /* }}} */
  2442. /* {{{ proto public bool ReflectionFunction::isDeprecated()
  2443. Returns whether this function is deprecated */
  2444. ZEND_METHOD(reflection_function, isDeprecated)
  2445. {
  2446. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
  2447. }
  2448. /* }}} */
  2449. /* {{{ proto public bool ReflectionFunction::inNamespace()
  2450. Returns whether this function is defined in namespace */
  2451. ZEND_METHOD(reflection_function, inNamespace)
  2452. {
  2453. zval **name;
  2454. char *colon;
  2455. if (zend_parse_parameters_none() == FAILURE) {
  2456. return;
  2457. }
  2458. if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
  2459. RETURN_FALSE;
  2460. }
  2461. if (Z_TYPE_PP(name) == IS_STRING
  2462. && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
  2463. && colon > Z_STRVAL_PP(name))
  2464. {
  2465. RETURN_TRUE;
  2466. }
  2467. RETURN_FALSE;
  2468. }
  2469. /* }}} */
  2470. /* {{{ proto public string ReflectionFunction::getNamespaceName()
  2471. Returns the name of namespace where this function is defined */
  2472. ZEND_METHOD(reflection_function, getNamespaceName)
  2473. {
  2474. zval **name;
  2475. char *backslash;
  2476. if (zend_parse_parameters_none() == FAILURE) {
  2477. return;
  2478. }
  2479. if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
  2480. RETURN_FALSE;
  2481. }
  2482. if (Z_TYPE_PP(name) == IS_STRING
  2483. && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
  2484. && backslash > Z_STRVAL_PP(name))
  2485. {
  2486. RETURN_STRINGL(Z_STRVAL_PP(name), backslash - Z_STRVAL_PP(name), 1);
  2487. }
  2488. RETURN_EMPTY_STRING();
  2489. }
  2490. /* }}} */
  2491. /* {{{ proto public string ReflectionFunction::getShortName()
  2492. Returns the short name of the function (without namespace part) */
  2493. ZEND_METHOD(reflection_function, getShortName)
  2494. {
  2495. zval **name;
  2496. char *backslash;
  2497. if (zend_parse_parameters_none() == FAILURE) {
  2498. return;
  2499. }
  2500. if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
  2501. RETURN_FALSE;
  2502. }
  2503. if (Z_TYPE_PP(name) == IS_STRING
  2504. && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
  2505. && backslash > Z_STRVAL_PP(name))
  2506. {
  2507. RETURN_STRINGL(backslash + 1, Z_STRLEN_PP(name) - (backslash - Z_STRVAL_PP(name) + 1), 1);
  2508. }
  2509. RETURN_ZVAL(*name, 1, 0);
  2510. }
  2511. /* }}} */
  2512. /* {{{ proto public bool ReflectionMethod::isConstructor()
  2513. Returns whether this method is the constructor */
  2514. ZEND_METHOD(reflection_method, isConstructor)
  2515. {
  2516. reflection_object *intern;
  2517. zend_function *mptr;
  2518. if (zend_parse_parameters_none() == FAILURE) {
  2519. return;
  2520. }
  2521. GET_REFLECTION_OBJECT_PTR(mptr);
  2522. /* we need to check if the ctor is the ctor of the class level we we
  2523. * looking at since we might be looking at an inherited old style ctor
  2524. * defined in base class. */
  2525. RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
  2526. }
  2527. /* }}} */
  2528. /* {{{ proto public bool ReflectionMethod::isDestructor()
  2529. Returns whether this method is static */
  2530. ZEND_METHOD(reflection_method, isDestructor)
  2531. {
  2532. reflection_object *intern;
  2533. zend_function *mptr;
  2534. if (zend_parse_parameters_none() == FAILURE) {
  2535. return;
  2536. }
  2537. GET_REFLECTION_OBJECT_PTR(mptr);
  2538. RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR);
  2539. }
  2540. /* }}} */
  2541. /* {{{ proto public int ReflectionMethod::getModifiers()
  2542. Returns a bitfield of the access modifiers for this method */
  2543. ZEND_METHOD(reflection_method, getModifiers)
  2544. {
  2545. reflection_object *intern;
  2546. zend_function *mptr;
  2547. if (zend_parse_parameters_none() == FAILURE) {
  2548. return;
  2549. }
  2550. GET_REFLECTION_OBJECT_PTR(mptr);
  2551. RETURN_LONG(mptr->common.fn_flags);
  2552. }
  2553. /* }}} */
  2554. /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
  2555. Get the declaring class */
  2556. ZEND_METHOD(reflection_method, getDeclaringClass)
  2557. {
  2558. reflection_object *intern;
  2559. zend_function *mptr;
  2560. METHOD_NOTSTATIC(reflection_method_ptr);
  2561. GET_REFLECTION_OBJECT_PTR(mptr);
  2562. zend_reflection_class_factory(mptr->common.scope, return_value TSRMLS_CC);
  2563. }
  2564. /* }}} */
  2565. /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype()
  2566. Get the prototype */
  2567. ZEND_METHOD(reflection_method, getPrototype)
  2568. {
  2569. reflection_object *intern;
  2570. zend_function *mptr;
  2571. METHOD_NOTSTATIC(reflection_method_ptr);
  2572. GET_REFLECTION_OBJECT_PTR(mptr);
  2573. if (!mptr->common.prototype) {
  2574. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2575. "Method %s::%s does not have a prototype", intern->ce->name, mptr->common.function_name);
  2576. return;
  2577. }
  2578. reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value TSRMLS_CC);
  2579. }
  2580. /* }}} */
  2581. /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
  2582. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  2583. ZEND_METHOD(reflection_class, export)
  2584. {
  2585. _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_ptr, 1);
  2586. }
  2587. /* }}} */
  2588. /* {{{ reflection_class_object_ctor */
  2589. static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
  2590. {
  2591. zval *argument;
  2592. zval *object;
  2593. zval *classname;
  2594. reflection_object *intern;
  2595. zend_class_entry **ce;
  2596. if (is_object) {
  2597. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &argument) == FAILURE) {
  2598. return;
  2599. }
  2600. } else {
  2601. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &argument) == FAILURE) {
  2602. return;
  2603. }
  2604. }
  2605. object = getThis();
  2606. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  2607. if (intern == NULL) {
  2608. return;
  2609. }
  2610. if (Z_TYPE_P(argument) == IS_OBJECT) {
  2611. MAKE_STD_ZVAL(classname);
  2612. ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
  2613. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
  2614. intern->ptr = Z_OBJCE_P(argument);
  2615. if (is_object) {
  2616. intern->obj = argument;
  2617. zval_add_ref(&argument);
  2618. }
  2619. } else {
  2620. convert_to_string_ex(&argument);
  2621. if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
  2622. if (!EG(exception)) {
  2623. zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", Z_STRVAL_P(argument));
  2624. }
  2625. return;
  2626. }
  2627. MAKE_STD_ZVAL(classname);
  2628. ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
  2629. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
  2630. intern->ptr = *ce;
  2631. }
  2632. intern->ref_type = REF_TYPE_OTHER;
  2633. }
  2634. /* }}} */
  2635. /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException
  2636. Constructor. Takes a string or an instance as an argument */
  2637. ZEND_METHOD(reflection_class, __construct)
  2638. {
  2639. reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2640. }
  2641. /* }}} */
  2642. /* {{{ proto public array ReflectionClass::getStaticProperties()
  2643. Returns an associative array containing all static property values of the class */
  2644. ZEND_METHOD(reflection_class, getStaticProperties)
  2645. {
  2646. reflection_object *intern;
  2647. zend_class_entry *ce;
  2648. HashPosition pos;
  2649. zval **value;
  2650. if (zend_parse_parameters_none() == FAILURE) {
  2651. return;
  2652. }
  2653. GET_REFLECTION_OBJECT_PTR(ce);
  2654. zend_update_class_constants(ce TSRMLS_CC);
  2655. array_init(return_value);
  2656. zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos);
  2657. while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) {
  2658. uint key_len;
  2659. char *key;
  2660. ulong num_index;
  2661. if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE && key) {
  2662. char *prop_name, *class_name;
  2663. zval *prop_copy;
  2664. zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
  2665. /* filter privates from base classes */
  2666. if (!(class_name && class_name[0] != '*' && strcmp(class_name, ce->name))) {
  2667. /* copy: enforce read only access */
  2668. ALLOC_ZVAL(prop_copy);
  2669. *prop_copy = **value;
  2670. zval_copy_ctor(prop_copy);
  2671. INIT_PZVAL(prop_copy);
  2672. add_assoc_zval(return_value, prop_name, prop_copy);
  2673. }
  2674. }
  2675. zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos);
  2676. }
  2677. }
  2678. /* }}} */
  2679. /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default])
  2680. Returns the value of a static property */
  2681. ZEND_METHOD(reflection_class, getStaticPropertyValue)
  2682. {
  2683. reflection_object *intern;
  2684. zend_class_entry *ce;
  2685. char *name;
  2686. int name_len;
  2687. zval **prop, *def_value = NULL;
  2688. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &name, &name_len, &def_value) == FAILURE) {
  2689. return;
  2690. }
  2691. GET_REFLECTION_OBJECT_PTR(ce);
  2692. zend_update_class_constants(ce TSRMLS_CC);
  2693. prop = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
  2694. if (!prop) {
  2695. if (def_value) {
  2696. RETURN_ZVAL(def_value, 1, 0);
  2697. } else {
  2698. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2699. "Class %s does not have a property named %s", ce->name, name);
  2700. }
  2701. return;
  2702. } else {
  2703. RETURN_ZVAL(*prop, 1, 0);
  2704. }
  2705. }
  2706. /* }}} */
  2707. /* {{{ proto public void ReflectionClass::setStaticPropertyValue($name, $value)
  2708. Sets the value of a static property */
  2709. ZEND_METHOD(reflection_class, setStaticPropertyValue)
  2710. {
  2711. reflection_object *intern;
  2712. zend_class_entry *ce;
  2713. char *name;
  2714. int name_len;
  2715. zval **variable_ptr, *value;
  2716. int refcount;
  2717. zend_uchar is_ref;
  2718. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &value) == FAILURE) {
  2719. return;
  2720. }
  2721. GET_REFLECTION_OBJECT_PTR(ce);
  2722. zend_update_class_constants(ce TSRMLS_CC);
  2723. variable_ptr = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
  2724. if (!variable_ptr) {
  2725. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2726. "Class %s does not have a property named %s", ce->name, name);
  2727. return;
  2728. }
  2729. refcount = Z_REFCOUNT_PP(variable_ptr);
  2730. is_ref = Z_ISREF_PP(variable_ptr);
  2731. zval_dtor(*variable_ptr);
  2732. **variable_ptr = *value;
  2733. zval_copy_ctor(*variable_ptr);
  2734. Z_SET_REFCOUNT_PP(variable_ptr, refcount);
  2735. Z_SET_ISREF_TO_PP(variable_ptr, is_ref);
  2736. }
  2737. /* }}} */
  2738. /* {{{ proto public array ReflectionClass::getDefaultProperties()
  2739. Returns an associative array containing copies of all default property values of the class */
  2740. ZEND_METHOD(reflection_class, getDefaultProperties)
  2741. {
  2742. reflection_object *intern;
  2743. zend_class_entry *ce;
  2744. int count, i;
  2745. HashTable *ht_list[3];
  2746. if (zend_parse_parameters_none() == FAILURE) {
  2747. return;
  2748. }
  2749. GET_REFLECTION_OBJECT_PTR(ce);
  2750. array_init(return_value);
  2751. zend_update_class_constants(ce TSRMLS_CC);
  2752. ht_list[0] = CE_STATIC_MEMBERS(ce);
  2753. ht_list[1] = &ce->default_properties;
  2754. ht_list[2] = NULL;
  2755. for (i = 0; ht_list[i] != NULL; i++) {
  2756. count = zend_hash_num_elements(ht_list[i]);
  2757. if (count > 0) {
  2758. HashPosition pos;
  2759. zval **prop;
  2760. zend_hash_internal_pointer_reset_ex(ht_list[i], &pos);
  2761. while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) {
  2762. char *key, *class_name, *prop_name;
  2763. uint key_len;
  2764. ulong num_index;
  2765. zval *prop_copy;
  2766. zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos);
  2767. zend_hash_move_forward_ex(ht_list[i], &pos);
  2768. zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
  2769. if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) {
  2770. /* filter privates from base classes */
  2771. continue;
  2772. }
  2773. /* copy: enforce read only access */
  2774. ALLOC_ZVAL(prop_copy);
  2775. *prop_copy = **prop;
  2776. zval_copy_ctor(prop_copy);
  2777. INIT_PZVAL(prop_copy);
  2778. add_assoc_zval(return_value, prop_name, prop_copy);
  2779. }
  2780. }
  2781. }
  2782. }
  2783. /* }}} */
  2784. /* {{{ proto public string ReflectionClass::__toString()
  2785. Returns a string representation */
  2786. ZEND_METHOD(reflection_class, __toString)
  2787. {
  2788. reflection_object *intern;
  2789. zend_class_entry *ce;
  2790. string str;
  2791. if (zend_parse_parameters_none() == FAILURE) {
  2792. return;
  2793. }
  2794. GET_REFLECTION_OBJECT_PTR(ce);
  2795. string_init(&str);
  2796. _class_string(&str, ce, intern->obj, "" TSRMLS_CC);
  2797. RETURN_STRINGL(str.string, str.len - 1, 0);
  2798. }
  2799. /* }}} */
  2800. /* {{{ proto public string ReflectionClass::getName()
  2801. Returns the class' name */
  2802. ZEND_METHOD(reflection_class, getName)
  2803. {
  2804. if (zend_parse_parameters_none() == FAILURE) {
  2805. return;
  2806. }
  2807. _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
  2808. }
  2809. /* }}} */
  2810. /* {{{ proto public bool ReflectionClass::isInternal()
  2811. Returns whether this class is an internal class */
  2812. ZEND_METHOD(reflection_class, isInternal)
  2813. {
  2814. reflection_object *intern;
  2815. zend_class_entry *ce;
  2816. if (zend_parse_parameters_none() == FAILURE) {
  2817. return;
  2818. }
  2819. GET_REFLECTION_OBJECT_PTR(ce);
  2820. RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
  2821. }
  2822. /* }}} */
  2823. /* {{{ proto public bool ReflectionClass::isUserDefined()
  2824. Returns whether this class is user-defined */
  2825. ZEND_METHOD(reflection_class, isUserDefined)
  2826. {
  2827. reflection_object *intern;
  2828. zend_class_entry *ce;
  2829. if (zend_parse_parameters_none() == FAILURE) {
  2830. return;
  2831. }
  2832. GET_REFLECTION_OBJECT_PTR(ce);
  2833. RETURN_BOOL(ce->type == ZEND_USER_CLASS);
  2834. }
  2835. /* }}} */
  2836. /* {{{ proto public string ReflectionClass::getFileName()
  2837. Returns the filename of the file this class was declared in */
  2838. ZEND_METHOD(reflection_class, getFileName)
  2839. {
  2840. reflection_object *intern;
  2841. zend_class_entry *ce;
  2842. if (zend_parse_parameters_none() == FAILURE) {
  2843. return;
  2844. }
  2845. GET_REFLECTION_OBJECT_PTR(ce);
  2846. if (ce->type == ZEND_USER_CLASS) {
  2847. RETURN_STRING(ce->filename, 1);
  2848. }
  2849. RETURN_FALSE;
  2850. }
  2851. /* }}} */
  2852. /* {{{ proto public int ReflectionClass::getStartLine()
  2853. Returns the line this class' declaration starts at */
  2854. ZEND_METHOD(reflection_class, getStartLine)
  2855. {
  2856. reflection_object *intern;
  2857. zend_class_entry *ce;
  2858. if (zend_parse_parameters_none() == FAILURE) {
  2859. return;
  2860. }
  2861. GET_REFLECTION_OBJECT_PTR(ce);
  2862. if (ce->type == ZEND_USER_FUNCTION) {
  2863. RETURN_LONG(ce->line_start);
  2864. }
  2865. RETURN_FALSE;
  2866. }
  2867. /* }}} */
  2868. /* {{{ proto public int ReflectionClass::getEndLine()
  2869. Returns the line this class' declaration ends at */
  2870. ZEND_METHOD(reflection_class, getEndLine)
  2871. {
  2872. reflection_object *intern;
  2873. zend_class_entry *ce;
  2874. if (zend_parse_parameters_none() == FAILURE) {
  2875. return;
  2876. }
  2877. GET_REFLECTION_OBJECT_PTR(ce);
  2878. if (ce->type == ZEND_USER_CLASS) {
  2879. RETURN_LONG(ce->line_end);
  2880. }
  2881. RETURN_FALSE;
  2882. }
  2883. /* }}} */
  2884. /* {{{ proto public string ReflectionClass::getDocComment()
  2885. Returns the doc comment for this class */
  2886. ZEND_METHOD(reflection_class, getDocComment)
  2887. {
  2888. reflection_object *intern;
  2889. zend_class_entry *ce;
  2890. if (zend_parse_parameters_none() == FAILURE) {
  2891. return;
  2892. }
  2893. GET_REFLECTION_OBJECT_PTR(ce);
  2894. if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
  2895. RETURN_STRINGL(ce->doc_comment, ce->doc_comment_len, 1);
  2896. }
  2897. RETURN_FALSE;
  2898. }
  2899. /* }}} */
  2900. /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
  2901. Returns the class' constructor if there is one, NULL otherwise */
  2902. ZEND_METHOD(reflection_class, getConstructor)
  2903. {
  2904. reflection_object *intern;
  2905. zend_class_entry *ce;
  2906. if (zend_parse_parameters_none() == FAILURE) {
  2907. return;
  2908. }
  2909. GET_REFLECTION_OBJECT_PTR(ce);
  2910. if (ce->constructor) {
  2911. reflection_method_factory(ce, ce->constructor, NULL, return_value TSRMLS_CC);
  2912. } else {
  2913. RETURN_NULL();
  2914. }
  2915. }
  2916. /* }}} */
  2917. /* {{{ proto public bool ReflectionClass::hasMethod(string name)
  2918. Returns whether a method exists or not */
  2919. ZEND_METHOD(reflection_class, hasMethod)
  2920. {
  2921. reflection_object *intern;
  2922. zend_class_entry *ce;
  2923. char *name, *lc_name;
  2924. int name_len;
  2925. METHOD_NOTSTATIC(reflection_class_ptr);
  2926. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
  2927. return;
  2928. }
  2929. GET_REFLECTION_OBJECT_PTR(ce);
  2930. lc_name = zend_str_tolower_dup(name, name_len);
  2931. if (zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
  2932. efree(lc_name);
  2933. RETURN_TRUE;
  2934. } else {
  2935. efree(lc_name);
  2936. RETURN_FALSE;
  2937. }
  2938. }
  2939. /* }}} */
  2940. /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
  2941. Returns the class' method specified by its name */
  2942. ZEND_METHOD(reflection_class, getMethod)
  2943. {
  2944. reflection_object *intern;
  2945. zend_class_entry *ce;
  2946. zend_function *mptr;
  2947. char *name, *lc_name;
  2948. int name_len;
  2949. METHOD_NOTSTATIC(reflection_class_ptr);
  2950. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
  2951. return;
  2952. }
  2953. GET_REFLECTION_OBJECT_PTR(ce);
  2954. lc_name = zend_str_tolower_dup(name, name_len);
  2955. if (ce == zend_ce_closure && intern->obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
  2956. && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  2957. && (mptr = zend_get_closure_invoke_method(intern->obj TSRMLS_CC)) != NULL)
  2958. {
  2959. /* don't assign closure_object since we only reflect the invoke handler
  2960. method and not the closure definition itself */
  2961. reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
  2962. efree(lc_name);
  2963. } else if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
  2964. reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
  2965. efree(lc_name);
  2966. } else {
  2967. efree(lc_name);
  2968. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  2969. "Method %s does not exist", name);
  2970. return;
  2971. }
  2972. }
  2973. /* }}} */
  2974. /* {{{ _addmethod */
  2975. static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, long filter, zval *obj TSRMLS_DC)
  2976. {
  2977. zval *method;
  2978. uint len = strlen(mptr->common.function_name);
  2979. zend_function *closure;
  2980. if (mptr->common.fn_flags & filter) {
  2981. ALLOC_ZVAL(method);
  2982. if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
  2983. && memcmp(mptr->common.function_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  2984. && (closure = zend_get_closure_invoke_method(obj TSRMLS_CC)) != NULL)
  2985. {
  2986. mptr = closure;
  2987. }
  2988. /* don't assign closure_object since we only reflect the invoke handler
  2989. method and not the closure definition itself, even if we have a
  2990. closure */
  2991. reflection_method_factory(ce, mptr, NULL, method TSRMLS_CC);
  2992. add_next_index_zval(retval, method);
  2993. }
  2994. }
  2995. /* }}} */
  2996. /* {{{ _addmethod */
  2997. static int _addmethod_va(zend_function *mptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  2998. {
  2999. zend_class_entry *ce = *va_arg(args, zend_class_entry**);
  3000. zval *retval = va_arg(args, zval*);
  3001. long filter = va_arg(args, long);
  3002. zval *obj = va_arg(args, zval *);
  3003. _addmethod(mptr, ce, retval, filter, obj TSRMLS_CC);
  3004. return ZEND_HASH_APPLY_KEEP;
  3005. }
  3006. /* }}} */
  3007. /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter])
  3008. Returns an array of this class' methods */
  3009. ZEND_METHOD(reflection_class, getMethods)
  3010. {
  3011. reflection_object *intern;
  3012. zend_class_entry *ce;
  3013. long filter = 0;
  3014. int argc = ZEND_NUM_ARGS();
  3015. METHOD_NOTSTATIC(reflection_class_ptr);
  3016. if (argc) {
  3017. if (zend_parse_parameters(argc TSRMLS_CC, "|l", &filter) == FAILURE) {
  3018. return;
  3019. }
  3020. } else {
  3021. /* No parameters given, default to "return all" */
  3022. filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
  3023. }
  3024. GET_REFLECTION_OBJECT_PTR(ce);
  3025. array_init(return_value);
  3026. zend_hash_apply_with_arguments(&ce->function_table TSRMLS_CC, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter, intern->obj);
  3027. if (intern->obj && instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
  3028. zend_function *closure = zend_get_closure_invoke_method(intern->obj TSRMLS_CC);
  3029. if (closure) {
  3030. _addmethod(closure, ce, return_value, filter, intern->obj TSRMLS_CC);
  3031. _free_function(closure TSRMLS_CC);
  3032. }
  3033. }
  3034. }
  3035. /* }}} */
  3036. /* {{{ proto public bool ReflectionClass::hasProperty(string name)
  3037. Returns whether a property exists or not */
  3038. ZEND_METHOD(reflection_class, hasProperty)
  3039. {
  3040. reflection_object *intern;
  3041. zend_class_entry *ce;
  3042. char *name;
  3043. int name_len;
  3044. zval *property;
  3045. METHOD_NOTSTATIC(reflection_class_ptr);
  3046. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
  3047. return;
  3048. }
  3049. GET_REFLECTION_OBJECT_PTR(ce);
  3050. if (zend_hash_exists(&ce->properties_info, name, name_len + 1)) {
  3051. RETURN_TRUE;
  3052. } else {
  3053. if (intern->obj && Z_OBJ_HANDLER_P(intern->obj, has_property))
  3054. {
  3055. MAKE_STD_ZVAL(property);
  3056. ZVAL_STRINGL(property, name, name_len, 1);
  3057. if (Z_OBJ_HANDLER_P(intern->obj, has_property)(intern->obj, property, 0 TSRMLS_CC)) {
  3058. zval_ptr_dtor(&property);
  3059. RETURN_TRUE;
  3060. }
  3061. zval_ptr_dtor(&property);
  3062. }
  3063. RETURN_FALSE;
  3064. }
  3065. }
  3066. /* }}} */
  3067. /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
  3068. Returns the class' property specified by its name */
  3069. ZEND_METHOD(reflection_class, getProperty)
  3070. {
  3071. reflection_object *intern;
  3072. zend_class_entry *ce, **pce;
  3073. zend_property_info *property_info;
  3074. char *name, *tmp, *classname;
  3075. int name_len, classname_len;
  3076. METHOD_NOTSTATIC(reflection_class_ptr);
  3077. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
  3078. return;
  3079. }
  3080. GET_REFLECTION_OBJECT_PTR(ce);
  3081. if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) {
  3082. if ((property_info->flags & ZEND_ACC_SHADOW) == 0) {
  3083. reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
  3084. return;
  3085. }
  3086. } else if (intern->obj) {
  3087. /* Check for dynamic properties */
  3088. if (zend_hash_exists(Z_OBJ_HT_P(intern->obj)->get_properties(intern->obj TSRMLS_CC), name, name_len+1)) {
  3089. zend_property_info property_info_tmp;
  3090. property_info_tmp.flags = ZEND_ACC_IMPLICIT_PUBLIC;
  3091. property_info_tmp.name = name;
  3092. property_info_tmp.name_length = name_len;
  3093. property_info_tmp.h = zend_get_hash_value(name, name_len+1);
  3094. property_info_tmp.doc_comment = NULL;
  3095. property_info_tmp.ce = ce;
  3096. reflection_property_factory(ce, &property_info_tmp, return_value TSRMLS_CC);
  3097. return;
  3098. }
  3099. }
  3100. if ((tmp = strstr(name, "::")) != NULL) {
  3101. classname_len = tmp - name;
  3102. classname = zend_str_tolower_dup(name, classname_len);
  3103. classname[classname_len] = '\0';
  3104. name_len = name_len - (classname_len + 2);
  3105. name = tmp + 2;
  3106. if (zend_lookup_class(classname, classname_len, &pce TSRMLS_CC) == FAILURE) {
  3107. if (!EG(exception)) {
  3108. zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", classname);
  3109. }
  3110. efree(classname);
  3111. return;
  3112. }
  3113. efree(classname);
  3114. if (!instanceof_function(ce, *pce TSRMLS_CC)) {
  3115. zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Fully qualified property name %s::%s does not specify a base class of %s", (*pce)->name, name, ce->name);
  3116. return;
  3117. }
  3118. ce = *pce;
  3119. if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
  3120. reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
  3121. return;
  3122. }
  3123. }
  3124. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3125. "Property %s does not exist", name);
  3126. }
  3127. /* }}} */
  3128. /* {{{ _addproperty */
  3129. static int _addproperty(zend_property_info *pptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  3130. {
  3131. zval *property;
  3132. zend_class_entry *ce = *va_arg(args, zend_class_entry**);
  3133. zval *retval = va_arg(args, zval*);
  3134. long filter = va_arg(args, long);
  3135. if (pptr->flags & ZEND_ACC_SHADOW) {
  3136. return 0;
  3137. }
  3138. if (pptr->flags & filter) {
  3139. ALLOC_ZVAL(property);
  3140. reflection_property_factory(ce, pptr, property TSRMLS_CC);
  3141. add_next_index_zval(retval, property);
  3142. }
  3143. return 0;
  3144. }
  3145. /* }}} */
  3146. /* {{{ _adddynproperty */
  3147. static int _adddynproperty(zval **pptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  3148. {
  3149. zval *property;
  3150. zend_class_entry *ce = *va_arg(args, zend_class_entry**);
  3151. zval *retval = va_arg(args, zval*), member;
  3152. if (hash_key->arKey[0] == '\0') {
  3153. return 0; /* non public cannot be dynamic */
  3154. }
  3155. ZVAL_STRINGL(&member, hash_key->arKey, hash_key->nKeyLength-1, 0);
  3156. if (zend_get_property_info(ce, &member, 1 TSRMLS_CC) == &EG(std_property_info)) {
  3157. MAKE_STD_ZVAL(property);
  3158. reflection_property_factory(ce, &EG(std_property_info), property TSRMLS_CC);
  3159. add_next_index_zval(retval, property);
  3160. }
  3161. return 0;
  3162. }
  3163. /* }}} */
  3164. /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter])
  3165. Returns an array of this class' properties */
  3166. ZEND_METHOD(reflection_class, getProperties)
  3167. {
  3168. reflection_object *intern;
  3169. zend_class_entry *ce;
  3170. long filter = 0;
  3171. int argc = ZEND_NUM_ARGS();
  3172. METHOD_NOTSTATIC(reflection_class_ptr);
  3173. if (argc) {
  3174. if (zend_parse_parameters(argc TSRMLS_CC, "|l", &filter) == FAILURE) {
  3175. return;
  3176. }
  3177. } else {
  3178. /* No parameters given, default to "return all" */
  3179. filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
  3180. }
  3181. GET_REFLECTION_OBJECT_PTR(ce);
  3182. array_init(return_value);
  3183. zend_hash_apply_with_arguments(&ce->properties_info TSRMLS_CC, (apply_func_args_t) _addproperty, 3, &ce, return_value, filter);
  3184. if (intern->obj && (filter & ZEND_ACC_PUBLIC) != 0 && Z_OBJ_HT_P(intern->obj)->get_properties) {
  3185. HashTable *properties = Z_OBJ_HT_P(intern->obj)->get_properties(intern->obj TSRMLS_CC);
  3186. zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t) _adddynproperty, 2, &ce, return_value);
  3187. }
  3188. }
  3189. /* }}} */
  3190. /* {{{ proto public bool ReflectionClass::hasConstant(string name)
  3191. Returns whether a constant exists or not */
  3192. ZEND_METHOD(reflection_class, hasConstant)
  3193. {
  3194. reflection_object *intern;
  3195. zend_class_entry *ce;
  3196. char *name;
  3197. int name_len;
  3198. METHOD_NOTSTATIC(reflection_class_ptr);
  3199. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
  3200. return;
  3201. }
  3202. GET_REFLECTION_OBJECT_PTR(ce);
  3203. if (zend_hash_exists(&ce->constants_table, name, name_len + 1)) {
  3204. RETURN_TRUE;
  3205. } else {
  3206. RETURN_FALSE;
  3207. }
  3208. }
  3209. /* }}} */
  3210. /* {{{ proto public array ReflectionClass::getConstants()
  3211. Returns an associative array containing this class' constants and their values */
  3212. ZEND_METHOD(reflection_class, getConstants)
  3213. {
  3214. zval *tmp_copy;
  3215. reflection_object *intern;
  3216. zend_class_entry *ce;
  3217. if (zend_parse_parameters_none() == FAILURE) {
  3218. return;
  3219. }
  3220. GET_REFLECTION_OBJECT_PTR(ce);
  3221. array_init(return_value);
  3222. zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
  3223. zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
  3224. }
  3225. /* }}} */
  3226. /* {{{ proto public mixed ReflectionClass::getConstant(string name)
  3227. Returns the class' constant specified by its name */
  3228. ZEND_METHOD(reflection_class, getConstant)
  3229. {
  3230. reflection_object *intern;
  3231. zend_class_entry *ce;
  3232. zval **value;
  3233. char *name;
  3234. int name_len;
  3235. METHOD_NOTSTATIC(reflection_class_ptr);
  3236. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
  3237. return;
  3238. }
  3239. GET_REFLECTION_OBJECT_PTR(ce);
  3240. zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
  3241. if (zend_hash_find(&ce->constants_table, name, name_len + 1, (void **) &value) == FAILURE) {
  3242. RETURN_FALSE;
  3243. }
  3244. *return_value = **value;
  3245. zval_copy_ctor(return_value);
  3246. INIT_PZVAL(return_value);
  3247. }
  3248. /* }}} */
  3249. /* {{{ _class_check_flag */
  3250. static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
  3251. {
  3252. reflection_object *intern;
  3253. zend_class_entry *ce;
  3254. if (zend_parse_parameters_none() == FAILURE) {
  3255. return;
  3256. }
  3257. GET_REFLECTION_OBJECT_PTR(ce);
  3258. RETVAL_BOOL(ce->ce_flags & mask);
  3259. }
  3260. /* }}} */
  3261. /* {{{ proto public bool ReflectionClass::isInstantiable()
  3262. Returns whether this class is instantiable */
  3263. ZEND_METHOD(reflection_class, isInstantiable)
  3264. {
  3265. reflection_object *intern;
  3266. zend_class_entry *ce;
  3267. if (zend_parse_parameters_none() == FAILURE) {
  3268. return;
  3269. }
  3270. GET_REFLECTION_OBJECT_PTR(ce);
  3271. if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
  3272. RETURN_FALSE;
  3273. }
  3274. /* Basically, the class is instantiable. Though, if there is a constructor
  3275. * and it is not publicly accessible, it isn't! */
  3276. if (!ce->constructor) {
  3277. RETURN_TRUE;
  3278. }
  3279. RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
  3280. }
  3281. /* }}} */
  3282. /* {{{ proto public bool ReflectionClass::isInterface()
  3283. Returns whether this is an interface or a class */
  3284. ZEND_METHOD(reflection_class, isInterface)
  3285. {
  3286. _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
  3287. }
  3288. /* }}} */
  3289. /* {{{ proto public bool ReflectionClass::isFinal()
  3290. Returns whether this class is final */
  3291. ZEND_METHOD(reflection_class, isFinal)
  3292. {
  3293. _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL_CLASS);
  3294. }
  3295. /* }}} */
  3296. /* {{{ proto public bool ReflectionClass::isAbstract()
  3297. Returns whether this class is abstract */
  3298. ZEND_METHOD(reflection_class, isAbstract)
  3299. {
  3300. _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
  3301. }
  3302. /* }}} */
  3303. /* {{{ proto public int ReflectionClass::getModifiers()
  3304. Returns a bitfield of the access modifiers for this class */
  3305. ZEND_METHOD(reflection_class, getModifiers)
  3306. {
  3307. reflection_object *intern;
  3308. zend_class_entry *ce;
  3309. if (zend_parse_parameters_none() == FAILURE) {
  3310. return;
  3311. }
  3312. GET_REFLECTION_OBJECT_PTR(ce);
  3313. RETURN_LONG(ce->ce_flags);
  3314. }
  3315. /* }}} */
  3316. /* {{{ proto public bool ReflectionClass::isInstance(stdclass object)
  3317. Returns whether the given object is an instance of this class */
  3318. ZEND_METHOD(reflection_class, isInstance)
  3319. {
  3320. reflection_object *intern;
  3321. zend_class_entry *ce;
  3322. zval *object;
  3323. METHOD_NOTSTATIC(reflection_class_ptr);
  3324. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
  3325. return;
  3326. }
  3327. GET_REFLECTION_OBJECT_PTR(ce);
  3328. RETURN_BOOL(HAS_CLASS_ENTRY(*object) && instanceof_function(Z_OBJCE_P(object), ce TSRMLS_CC));
  3329. }
  3330. /* }}} */
  3331. /* {{{ proto public stdclass ReflectionClass::newInstance(mixed* args, ...)
  3332. Returns an instance of this class */
  3333. ZEND_METHOD(reflection_class, newInstance)
  3334. {
  3335. zval *retval_ptr = NULL;
  3336. reflection_object *intern;
  3337. zend_class_entry *ce;
  3338. METHOD_NOTSTATIC(reflection_class_ptr);
  3339. GET_REFLECTION_OBJECT_PTR(ce);
  3340. /* Run the constructor if there is one */
  3341. if (ce->constructor) {
  3342. zval ***params = NULL;
  3343. int num_args = 0;
  3344. zend_fcall_info fci;
  3345. zend_fcall_info_cache fcc;
  3346. if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
  3347. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
  3348. return;
  3349. }
  3350. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &params, &num_args) == FAILURE) {
  3351. if (params) {
  3352. efree(params);
  3353. }
  3354. RETURN_FALSE;
  3355. }
  3356. object_init_ex(return_value, ce);
  3357. fci.size = sizeof(fci);
  3358. fci.function_table = EG(function_table);
  3359. fci.function_name = NULL;
  3360. fci.symbol_table = NULL;
  3361. fci.object_ptr = return_value;
  3362. fci.retval_ptr_ptr = &retval_ptr;
  3363. fci.param_count = num_args;
  3364. fci.params = params;
  3365. fci.no_separation = 1;
  3366. fcc.initialized = 1;
  3367. fcc.function_handler = ce->constructor;
  3368. fcc.calling_scope = EG(scope);
  3369. fcc.called_scope = Z_OBJCE_P(return_value);
  3370. fcc.object_ptr = return_value;
  3371. if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
  3372. if (params) {
  3373. efree(params);
  3374. }
  3375. if (retval_ptr) {
  3376. zval_ptr_dtor(&retval_ptr);
  3377. }
  3378. zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name);
  3379. RETURN_NULL();
  3380. }
  3381. if (retval_ptr) {
  3382. zval_ptr_dtor(&retval_ptr);
  3383. }
  3384. if (params) {
  3385. efree(params);
  3386. }
  3387. } else if (!ZEND_NUM_ARGS()) {
  3388. object_init_ex(return_value, ce);
  3389. } else {
  3390. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ce->name);
  3391. }
  3392. }
  3393. /* }}} */
  3394. /* {{{ proto public stdclass ReflectionClass::newInstanceArgs([array args])
  3395. Returns an instance of this class */
  3396. ZEND_METHOD(reflection_class, newInstanceArgs)
  3397. {
  3398. zval *retval_ptr = NULL;
  3399. reflection_object *intern;
  3400. zend_class_entry *ce;
  3401. int argc = 0;
  3402. HashTable *args;
  3403. METHOD_NOTSTATIC(reflection_class_ptr);
  3404. GET_REFLECTION_OBJECT_PTR(ce);
  3405. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|h", &args) == FAILURE) {
  3406. return;
  3407. }
  3408. if (ZEND_NUM_ARGS() > 0) {
  3409. argc = args->nNumOfElements;
  3410. }
  3411. /* Run the constructor if there is one */
  3412. if (ce->constructor) {
  3413. zval ***params = NULL;
  3414. zend_fcall_info fci;
  3415. zend_fcall_info_cache fcc;
  3416. if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
  3417. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
  3418. return;
  3419. }
  3420. if (argc) {
  3421. params = safe_emalloc(sizeof(zval **), argc, 0);
  3422. zend_hash_apply_with_argument(args, (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);
  3423. params -= argc;
  3424. }
  3425. object_init_ex(return_value, ce);
  3426. fci.size = sizeof(fci);
  3427. fci.function_table = EG(function_table);
  3428. fci.function_name = NULL;
  3429. fci.symbol_table = NULL;
  3430. fci.object_ptr = return_value;
  3431. fci.retval_ptr_ptr = &retval_ptr;
  3432. fci.param_count = argc;
  3433. fci.params = params;
  3434. fci.no_separation = 1;
  3435. fcc.initialized = 1;
  3436. fcc.function_handler = ce->constructor;
  3437. fcc.calling_scope = EG(scope);
  3438. fcc.called_scope = Z_OBJCE_P(return_value);
  3439. fcc.object_ptr = return_value;
  3440. if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
  3441. if (params) {
  3442. efree(params);
  3443. }
  3444. if (retval_ptr) {
  3445. zval_ptr_dtor(&retval_ptr);
  3446. }
  3447. zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name);
  3448. RETURN_NULL();
  3449. }
  3450. if (retval_ptr) {
  3451. zval_ptr_dtor(&retval_ptr);
  3452. }
  3453. if (params) {
  3454. efree(params);
  3455. }
  3456. } else if (!ZEND_NUM_ARGS()) {
  3457. object_init_ex(return_value, ce);
  3458. } else {
  3459. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ce->name);
  3460. }
  3461. }
  3462. /* }}} */
  3463. /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
  3464. Returns an array of interfaces this class implements */
  3465. ZEND_METHOD(reflection_class, getInterfaces)
  3466. {
  3467. reflection_object *intern;
  3468. zend_class_entry *ce;
  3469. if (zend_parse_parameters_none() == FAILURE) {
  3470. return;
  3471. }
  3472. GET_REFLECTION_OBJECT_PTR(ce);
  3473. /* Return an empty array if this class implements no interfaces */
  3474. array_init(return_value);
  3475. if (ce->num_interfaces) {
  3476. zend_uint i;
  3477. for (i=0; i < ce->num_interfaces; i++) {
  3478. zval *interface;
  3479. ALLOC_ZVAL(interface);
  3480. zend_reflection_class_factory(ce->interfaces[i], interface TSRMLS_CC);
  3481. add_assoc_zval_ex(return_value, ce->interfaces[i]->name, ce->interfaces[i]->name_length + 1, interface);
  3482. }
  3483. }
  3484. }
  3485. /* }}} */
  3486. /* {{{ proto public String[] ReflectionClass::getInterfaceNames()
  3487. Returns an array of names of interfaces this class implements */
  3488. ZEND_METHOD(reflection_class, getInterfaceNames)
  3489. {
  3490. reflection_object *intern;
  3491. zend_class_entry *ce;
  3492. zend_uint i;
  3493. if (zend_parse_parameters_none() == FAILURE) {
  3494. return;
  3495. }
  3496. GET_REFLECTION_OBJECT_PTR(ce);
  3497. /* Return an empty array if this class implements no interfaces */
  3498. array_init(return_value);
  3499. for (i=0; i < ce->num_interfaces; i++) {
  3500. add_next_index_stringl(return_value, ce->interfaces[i]->name, ce->interfaces[i]->name_length, 1);
  3501. }
  3502. }
  3503. /* }}} */
  3504. /* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
  3505. Returns the class' parent class, or, if none exists, FALSE */
  3506. ZEND_METHOD(reflection_class, getParentClass)
  3507. {
  3508. reflection_object *intern;
  3509. zend_class_entry *ce;
  3510. if (zend_parse_parameters_none() == FAILURE) {
  3511. return;
  3512. }
  3513. GET_REFLECTION_OBJECT_PTR(ce);
  3514. if (ce->parent) {
  3515. zend_reflection_class_factory(ce->parent, return_value TSRMLS_CC);
  3516. } else {
  3517. RETURN_FALSE;
  3518. }
  3519. }
  3520. /* }}} */
  3521. /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
  3522. Returns whether this class is a subclass of another class */
  3523. ZEND_METHOD(reflection_class, isSubclassOf)
  3524. {
  3525. reflection_object *intern, *argument;
  3526. zend_class_entry *ce, **pce, *class_ce;
  3527. zval *class_name;
  3528. METHOD_NOTSTATIC(reflection_class_ptr);
  3529. GET_REFLECTION_OBJECT_PTR(ce);
  3530. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &class_name) == FAILURE) {
  3531. return;
  3532. }
  3533. switch(class_name->type) {
  3534. case IS_STRING:
  3535. if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
  3536. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3537. "Class %s does not exist", Z_STRVAL_P(class_name));
  3538. return;
  3539. }
  3540. class_ce = *pce;
  3541. break;
  3542. case IS_OBJECT:
  3543. if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr TSRMLS_CC)) {
  3544. argument = (reflection_object *) zend_object_store_get_object(class_name TSRMLS_CC);
  3545. if (argument == NULL || argument->ptr == NULL) {
  3546. zend_error(E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
  3547. /* Bails out */
  3548. }
  3549. class_ce = argument->ptr;
  3550. break;
  3551. }
  3552. /* no break */
  3553. default:
  3554. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3555. "Parameter one must either be a string or a ReflectionClass object");
  3556. return;
  3557. }
  3558. RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce TSRMLS_CC)));
  3559. }
  3560. /* }}} */
  3561. /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
  3562. Returns whether this class is a subclass of another class */
  3563. ZEND_METHOD(reflection_class, implementsInterface)
  3564. {
  3565. reflection_object *intern, *argument;
  3566. zend_class_entry *ce, *interface_ce, **pce;
  3567. zval *interface;
  3568. METHOD_NOTSTATIC(reflection_class_ptr);
  3569. GET_REFLECTION_OBJECT_PTR(ce);
  3570. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &interface) == FAILURE) {
  3571. return;
  3572. }
  3573. switch(interface->type) {
  3574. case IS_STRING:
  3575. if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
  3576. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3577. "Interface %s does not exist", Z_STRVAL_P(interface));
  3578. return;
  3579. }
  3580. interface_ce = *pce;
  3581. break;
  3582. case IS_OBJECT:
  3583. if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr TSRMLS_CC)) {
  3584. argument = (reflection_object *) zend_object_store_get_object(interface TSRMLS_CC);
  3585. if (argument == NULL || argument->ptr == NULL) {
  3586. zend_error(E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
  3587. /* Bails out */
  3588. }
  3589. interface_ce = argument->ptr;
  3590. break;
  3591. }
  3592. /* no break */
  3593. default:
  3594. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3595. "Parameter one must either be a string or a ReflectionClass object");
  3596. return;
  3597. }
  3598. if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
  3599. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3600. "Interface %s is a Class", interface_ce->name);
  3601. return;
  3602. }
  3603. RETURN_BOOL(instanceof_function(ce, interface_ce TSRMLS_CC));
  3604. }
  3605. /* }}} */
  3606. /* {{{ proto public bool ReflectionClass::isIterateable()
  3607. Returns whether this class is iterateable (can be used inside foreach) */
  3608. ZEND_METHOD(reflection_class, isIterateable)
  3609. {
  3610. reflection_object *intern;
  3611. zend_class_entry *ce;
  3612. METHOD_NOTSTATIC(reflection_class_ptr);
  3613. GET_REFLECTION_OBJECT_PTR(ce);
  3614. RETURN_BOOL(ce->get_iterator != NULL);
  3615. }
  3616. /* }}} */
  3617. /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension()
  3618. Returns NULL or the extension the class belongs to */
  3619. ZEND_METHOD(reflection_class, getExtension)
  3620. {
  3621. reflection_object *intern;
  3622. zend_class_entry *ce;
  3623. METHOD_NOTSTATIC(reflection_class_ptr);
  3624. GET_REFLECTION_OBJECT_PTR(ce);
  3625. if (ce->module) {
  3626. reflection_extension_factory(return_value, ce->module->name TSRMLS_CC);
  3627. }
  3628. }
  3629. /* }}} */
  3630. /* {{{ proto public string|false ReflectionClass::getExtensionName()
  3631. Returns false or the name of the extension the class belongs to */
  3632. ZEND_METHOD(reflection_class, getExtensionName)
  3633. {
  3634. reflection_object *intern;
  3635. zend_class_entry *ce;
  3636. METHOD_NOTSTATIC(reflection_class_ptr);
  3637. GET_REFLECTION_OBJECT_PTR(ce);
  3638. if (ce->module) {
  3639. RETURN_STRING(ce->module->name, 1);
  3640. } else {
  3641. RETURN_FALSE;
  3642. }
  3643. }
  3644. /* }}} */
  3645. /* {{{ proto public bool ReflectionClass::inNamespace()
  3646. Returns whether this class is defined in namespace */
  3647. ZEND_METHOD(reflection_class, inNamespace)
  3648. {
  3649. zval **name;
  3650. char *colon;
  3651. if (zend_parse_parameters_none() == FAILURE) {
  3652. return;
  3653. }
  3654. if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
  3655. RETURN_FALSE;
  3656. }
  3657. if (Z_TYPE_PP(name) == IS_STRING
  3658. && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
  3659. && colon > Z_STRVAL_PP(name))
  3660. {
  3661. RETURN_TRUE;
  3662. }
  3663. RETURN_FALSE;
  3664. }
  3665. /* }}} */
  3666. /* {{{ proto public string ReflectionClass::getNamespaceName()
  3667. Returns the name of namespace where this class is defined */
  3668. ZEND_METHOD(reflection_class, getNamespaceName)
  3669. {
  3670. zval **name;
  3671. char *backslash;
  3672. if (zend_parse_parameters_none() == FAILURE) {
  3673. return;
  3674. }
  3675. if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
  3676. RETURN_FALSE;
  3677. }
  3678. if (Z_TYPE_PP(name) == IS_STRING
  3679. && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
  3680. && backslash > Z_STRVAL_PP(name))
  3681. {
  3682. RETURN_STRINGL(Z_STRVAL_PP(name), backslash - Z_STRVAL_PP(name), 1);
  3683. }
  3684. RETURN_EMPTY_STRING();
  3685. }
  3686. /* }}} */
  3687. /* {{{ proto public string ReflectionClass::getShortName()
  3688. Returns the short name of the class (without namespace part) */
  3689. ZEND_METHOD(reflection_class, getShortName)
  3690. {
  3691. zval **name;
  3692. char *backslash;
  3693. if (zend_parse_parameters_none() == FAILURE) {
  3694. return;
  3695. }
  3696. if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
  3697. RETURN_FALSE;
  3698. }
  3699. if (Z_TYPE_PP(name) == IS_STRING
  3700. && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
  3701. && backslash > Z_STRVAL_PP(name))
  3702. {
  3703. RETURN_STRINGL(backslash + 1, Z_STRLEN_PP(name) - (backslash - Z_STRVAL_PP(name) + 1), 1);
  3704. }
  3705. RETURN_ZVAL(*name, 1, 0);
  3706. }
  3707. /* }}} */
  3708. /* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException
  3709. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  3710. ZEND_METHOD(reflection_object, export)
  3711. {
  3712. _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_object_ptr, 1);
  3713. }
  3714. /* }}} */
  3715. /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException
  3716. Constructor. Takes an instance as an argument */
  3717. ZEND_METHOD(reflection_object, __construct)
  3718. {
  3719. reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  3720. }
  3721. /* }}} */
  3722. /* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException
  3723. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  3724. ZEND_METHOD(reflection_property, export)
  3725. {
  3726. _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_property_ptr, 2);
  3727. }
  3728. /* }}} */
  3729. /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
  3730. Constructor. Throws an Exception in case the given property does not exist */
  3731. ZEND_METHOD(reflection_property, __construct)
  3732. {
  3733. zval *propname, *classname;
  3734. char *name_str, *class_name, *prop_name;
  3735. int name_len, dynam_prop = 0;
  3736. zval *object;
  3737. reflection_object *intern;
  3738. zend_class_entry **pce;
  3739. zend_class_entry *ce;
  3740. zend_property_info *property_info = NULL;
  3741. property_reference *reference;
  3742. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
  3743. return;
  3744. }
  3745. object = getThis();
  3746. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  3747. if (intern == NULL) {
  3748. return;
  3749. }
  3750. /* Find the class entry */
  3751. switch (Z_TYPE_P(classname)) {
  3752. case IS_STRING:
  3753. if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
  3754. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3755. "Class %s does not exist", Z_STRVAL_P(classname));
  3756. return;
  3757. }
  3758. ce = *pce;
  3759. break;
  3760. case IS_OBJECT:
  3761. ce = Z_OBJCE_P(classname);
  3762. break;
  3763. default:
  3764. _DO_THROW("The parameter class is expected to be either a string or an object");
  3765. /* returns out of this function */
  3766. }
  3767. if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
  3768. /* Check for dynamic properties */
  3769. if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT && Z_OBJ_HT_P(classname)->get_properties) {
  3770. if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(classname TSRMLS_CC), name_str, name_len+1)) {
  3771. dynam_prop = 1;
  3772. }
  3773. }
  3774. if (dynam_prop == 0) {
  3775. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Property %s::$%s does not exist", ce->name, name_str);
  3776. return;
  3777. }
  3778. }
  3779. if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
  3780. /* we have to search the class hierarchy for this (implicit) public or protected property */
  3781. zend_class_entry *tmp_ce = ce;
  3782. zend_property_info *tmp_info;
  3783. while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, name_str, name_len + 1, (void **) &tmp_info) != SUCCESS) {
  3784. ce = tmp_ce;
  3785. property_info = tmp_info;
  3786. tmp_ce = tmp_ce->parent;
  3787. }
  3788. }
  3789. MAKE_STD_ZVAL(classname);
  3790. MAKE_STD_ZVAL(propname);
  3791. if (dynam_prop == 0) {
  3792. zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name);
  3793. ZVAL_STRINGL(classname, property_info->ce->name, property_info->ce->name_length, 1);
  3794. ZVAL_STRING(propname, prop_name, 1);
  3795. } else {
  3796. ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
  3797. ZVAL_STRINGL(propname, name_str, name_len, 1);
  3798. }
  3799. zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
  3800. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
  3801. reference = (property_reference*) emalloc(sizeof(property_reference));
  3802. if (dynam_prop) {
  3803. reference->prop.flags = ZEND_ACC_IMPLICIT_PUBLIC;
  3804. reference->prop.name = Z_STRVAL_P(propname);
  3805. reference->prop.name_length = Z_STRLEN_P(propname);
  3806. reference->prop.h = zend_get_hash_value(name_str, name_len+1);
  3807. reference->prop.doc_comment = NULL;
  3808. reference->prop.ce = ce;
  3809. } else {
  3810. reference->prop = *property_info;
  3811. }
  3812. reference->ce = ce;
  3813. reference->ignore_visibility = 0;
  3814. intern->ptr = reference;
  3815. intern->ref_type = REF_TYPE_PROPERTY;
  3816. intern->ce = ce;
  3817. }
  3818. /* }}} */
  3819. /* {{{ proto public string ReflectionProperty::__toString()
  3820. Returns a string representation */
  3821. ZEND_METHOD(reflection_property, __toString)
  3822. {
  3823. reflection_object *intern;
  3824. property_reference *ref;
  3825. string str;
  3826. if (zend_parse_parameters_none() == FAILURE) {
  3827. return;
  3828. }
  3829. GET_REFLECTION_OBJECT_PTR(ref);
  3830. string_init(&str);
  3831. _property_string(&str, &ref->prop, NULL, "" TSRMLS_CC);
  3832. RETURN_STRINGL(str.string, str.len - 1, 0);
  3833. }
  3834. /* }}} */
  3835. /* {{{ proto public string ReflectionProperty::getName()
  3836. Returns the class' name */
  3837. ZEND_METHOD(reflection_property, getName)
  3838. {
  3839. if (zend_parse_parameters_none() == FAILURE) {
  3840. return;
  3841. }
  3842. _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
  3843. }
  3844. /* }}} */
  3845. static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
  3846. {
  3847. reflection_object *intern;
  3848. property_reference *ref;
  3849. if (zend_parse_parameters_none() == FAILURE) {
  3850. return;
  3851. }
  3852. GET_REFLECTION_OBJECT_PTR(ref);
  3853. RETURN_BOOL(ref->prop.flags & mask);
  3854. }
  3855. /* {{{ proto public bool ReflectionProperty::isPublic()
  3856. Returns whether this property is public */
  3857. ZEND_METHOD(reflection_property, isPublic)
  3858. {
  3859. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
  3860. }
  3861. /* }}} */
  3862. /* {{{ proto public bool ReflectionProperty::isPrivate()
  3863. Returns whether this property is private */
  3864. ZEND_METHOD(reflection_property, isPrivate)
  3865. {
  3866. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
  3867. }
  3868. /* }}} */
  3869. /* {{{ proto public bool ReflectionProperty::isProtected()
  3870. Returns whether this property is protected */
  3871. ZEND_METHOD(reflection_property, isProtected)
  3872. {
  3873. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
  3874. }
  3875. /* }}} */
  3876. /* {{{ proto public bool ReflectionProperty::isStatic()
  3877. Returns whether this property is static */
  3878. ZEND_METHOD(reflection_property, isStatic)
  3879. {
  3880. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
  3881. }
  3882. /* }}} */
  3883. /* {{{ proto public bool ReflectionProperty::isDefault()
  3884. Returns whether this property is default (declared at compilation time). */
  3885. ZEND_METHOD(reflection_property, isDefault)
  3886. {
  3887. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ~ZEND_ACC_IMPLICIT_PUBLIC);
  3888. }
  3889. /* }}} */
  3890. /* {{{ proto public int ReflectionProperty::getModifiers()
  3891. Returns a bitfield of the access modifiers for this property */
  3892. ZEND_METHOD(reflection_property, getModifiers)
  3893. {
  3894. reflection_object *intern;
  3895. property_reference *ref;
  3896. if (zend_parse_parameters_none() == FAILURE) {
  3897. return;
  3898. }
  3899. GET_REFLECTION_OBJECT_PTR(ref);
  3900. RETURN_LONG(ref->prop.flags);
  3901. }
  3902. /* }}} */
  3903. /* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
  3904. Returns this property's value */
  3905. ZEND_METHOD(reflection_property, getValue)
  3906. {
  3907. reflection_object *intern;
  3908. property_reference *ref;
  3909. zval *object, name;
  3910. zval **member = NULL, *member_p = NULL;
  3911. METHOD_NOTSTATIC(reflection_property_ptr);
  3912. GET_REFLECTION_OBJECT_PTR(ref);
  3913. if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && ref->ignore_visibility == 0) {
  3914. _default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
  3915. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3916. "Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
  3917. zval_dtor(&name);
  3918. return;
  3919. }
  3920. if ((ref->prop.flags & ZEND_ACC_STATIC)) {
  3921. zend_update_class_constants(intern->ce TSRMLS_CC);
  3922. if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &member) == FAILURE) {
  3923. zend_error(E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
  3924. /* Bails out */
  3925. }
  3926. *return_value= **member;
  3927. zval_copy_ctor(return_value);
  3928. INIT_PZVAL(return_value);
  3929. } else {
  3930. char *class_name, *prop_name;
  3931. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
  3932. return;
  3933. }
  3934. zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name);
  3935. member_p = zend_read_property(ref->ce, object, prop_name, strlen(prop_name), 1 TSRMLS_CC);
  3936. *return_value= *member_p;
  3937. zval_copy_ctor(return_value);
  3938. INIT_PZVAL(return_value);
  3939. if (member_p != EG(uninitialized_zval_ptr)) {
  3940. zval_add_ref(&member_p);
  3941. zval_ptr_dtor(&member_p);
  3942. }
  3943. }
  3944. }
  3945. /* }}} */
  3946. /* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
  3947. Sets this property's value */
  3948. ZEND_METHOD(reflection_property, setValue)
  3949. {
  3950. reflection_object *intern;
  3951. property_reference *ref;
  3952. zval **variable_ptr;
  3953. zval *object, name;
  3954. zval *value;
  3955. int setter_done = 0;
  3956. zval *tmp;
  3957. HashTable *prop_table;
  3958. METHOD_NOTSTATIC(reflection_property_ptr);
  3959. GET_REFLECTION_OBJECT_PTR(ref);
  3960. if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && ref->ignore_visibility == 0) {
  3961. _default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
  3962. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  3963. "Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
  3964. zval_dtor(&name);
  3965. return;
  3966. }
  3967. if ((ref->prop.flags & ZEND_ACC_STATIC)) {
  3968. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
  3969. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &tmp, &value) == FAILURE) {
  3970. return;
  3971. }
  3972. }
  3973. zend_update_class_constants(intern->ce TSRMLS_CC);
  3974. prop_table = CE_STATIC_MEMBERS(intern->ce);
  3975. if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) {
  3976. zend_error(E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
  3977. /* Bails out */
  3978. }
  3979. if (*variable_ptr == value) {
  3980. setter_done = 1;
  3981. } else {
  3982. if (PZVAL_IS_REF(*variable_ptr)) {
  3983. zval_dtor(*variable_ptr);
  3984. (*variable_ptr)->type = value->type;
  3985. (*variable_ptr)->value = value->value;
  3986. if (Z_REFCOUNT_P(value) > 0) {
  3987. zval_copy_ctor(*variable_ptr);
  3988. }
  3989. setter_done = 1;
  3990. }
  3991. }
  3992. if (!setter_done) {
  3993. zval **foo;
  3994. Z_ADDREF_P(value);
  3995. if (PZVAL_IS_REF(value)) {
  3996. SEPARATE_ZVAL(&value);
  3997. }
  3998. zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);
  3999. }
  4000. } else {
  4001. char *class_name, *prop_name;
  4002. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
  4003. return;
  4004. }
  4005. zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name);
  4006. zend_update_property(ref->ce, object, prop_name, strlen(prop_name), value TSRMLS_CC);
  4007. }
  4008. }
  4009. /* }}} */
  4010. /* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
  4011. Get the declaring class */
  4012. ZEND_METHOD(reflection_property, getDeclaringClass)
  4013. {
  4014. reflection_object *intern;
  4015. property_reference *ref;
  4016. zend_class_entry *tmp_ce, *ce;
  4017. zend_property_info *tmp_info;
  4018. char *prop_name, *class_name;
  4019. int prop_name_len;
  4020. if (zend_parse_parameters_none() == FAILURE) {
  4021. return;
  4022. }
  4023. GET_REFLECTION_OBJECT_PTR(ref);
  4024. if (zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name) != SUCCESS) {
  4025. RETURN_FALSE;
  4026. }
  4027. prop_name_len = strlen(prop_name);
  4028. ce = tmp_ce = ref->ce;
  4029. while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, prop_name, prop_name_len + 1, (void **) &tmp_info) == SUCCESS) {
  4030. if (tmp_info->flags & ZEND_ACC_PRIVATE || tmp_info->flags & ZEND_ACC_SHADOW) {
  4031. /* it's a private property, so it can't be inherited */
  4032. break;
  4033. }
  4034. ce = tmp_ce;
  4035. if (tmp_ce == tmp_info->ce) {
  4036. /* declared in this class, done */
  4037. break;
  4038. }
  4039. tmp_ce = tmp_ce->parent;
  4040. }
  4041. zend_reflection_class_factory(ce, return_value TSRMLS_CC);
  4042. }
  4043. /* }}} */
  4044. /* {{{ proto public string ReflectionProperty::getDocComment()
  4045. Returns the doc comment for this property */
  4046. ZEND_METHOD(reflection_property, getDocComment)
  4047. {
  4048. reflection_object *intern;
  4049. property_reference *ref;
  4050. if (zend_parse_parameters_none() == FAILURE) {
  4051. return;
  4052. }
  4053. GET_REFLECTION_OBJECT_PTR(ref);
  4054. if (ref->prop.doc_comment) {
  4055. RETURN_STRINGL(ref->prop.doc_comment, ref->prop.doc_comment_len, 1);
  4056. }
  4057. RETURN_FALSE;
  4058. }
  4059. /* }}} */
  4060. /* {{{ proto public int ReflectionProperty::setAccessible()
  4061. Sets whether non-public properties can be requested */
  4062. ZEND_METHOD(reflection_property, setAccessible)
  4063. {
  4064. reflection_object *intern;
  4065. property_reference *ref;
  4066. zend_bool visible;
  4067. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &visible) == FAILURE) {
  4068. return;
  4069. }
  4070. GET_REFLECTION_OBJECT_PTR(ref);
  4071. ref->ignore_visibility = visible;
  4072. }
  4073. /* }}} */
  4074. /* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
  4075. Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
  4076. ZEND_METHOD(reflection_extension, export)
  4077. {
  4078. _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_extension_ptr, 1);
  4079. }
  4080. /* }}} */
  4081. /* {{{ proto public void ReflectionExtension::__construct(string name)
  4082. Constructor. Throws an Exception in case the given extension does not exist */
  4083. ZEND_METHOD(reflection_extension, __construct)
  4084. {
  4085. zval *name;
  4086. zval *object;
  4087. char *lcname;
  4088. reflection_object *intern;
  4089. zend_module_entry *module;
  4090. char *name_str;
  4091. int name_len;
  4092. ALLOCA_FLAG(use_heap)
  4093. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
  4094. return;
  4095. }
  4096. object = getThis();
  4097. intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
  4098. if (intern == NULL) {
  4099. return;
  4100. }
  4101. lcname = do_alloca(name_len + 1, use_heap);
  4102. zend_str_tolower_copy(lcname, name_str, name_len);
  4103. if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
  4104. free_alloca(lcname, use_heap);
  4105. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  4106. "Extension %s does not exist", name_str);
  4107. return;
  4108. }
  4109. free_alloca(lcname, use_heap);
  4110. MAKE_STD_ZVAL(name);
  4111. ZVAL_STRING(name, module->name, 1);
  4112. zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
  4113. intern->ptr = module;
  4114. intern->ref_type = REF_TYPE_OTHER;
  4115. intern->ce = NULL;
  4116. }
  4117. /* }}} */
  4118. /* {{{ proto public string ReflectionExtension::__toString()
  4119. Returns a string representation */
  4120. ZEND_METHOD(reflection_extension, __toString)
  4121. {
  4122. reflection_object *intern;
  4123. zend_module_entry *module;
  4124. string str;
  4125. if (zend_parse_parameters_none() == FAILURE) {
  4126. return;
  4127. }
  4128. GET_REFLECTION_OBJECT_PTR(module);
  4129. string_init(&str);
  4130. _extension_string(&str, module, "" TSRMLS_CC);
  4131. RETURN_STRINGL(str.string, str.len - 1, 0);
  4132. }
  4133. /* }}} */
  4134. /* {{{ proto public string ReflectionExtension::getName()
  4135. Returns this extension's name */
  4136. ZEND_METHOD(reflection_extension, getName)
  4137. {
  4138. if (zend_parse_parameters_none() == FAILURE) {
  4139. return;
  4140. }
  4141. _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
  4142. }
  4143. /* }}} */
  4144. /* {{{ proto public string ReflectionExtension::getVersion()
  4145. Returns this extension's version */
  4146. ZEND_METHOD(reflection_extension, getVersion)
  4147. {
  4148. reflection_object *intern;
  4149. zend_module_entry *module;
  4150. if (zend_parse_parameters_none() == FAILURE) {
  4151. return;
  4152. }
  4153. GET_REFLECTION_OBJECT_PTR(module);
  4154. /* An extension does not necessarily have a version number */
  4155. if (module->version == NO_VERSION_YET) {
  4156. RETURN_NULL();
  4157. } else {
  4158. RETURN_STRING(module->version, 1);
  4159. }
  4160. }
  4161. /* }}} */
  4162. /* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
  4163. Returns an array of this extension's fuctions */
  4164. ZEND_METHOD(reflection_extension, getFunctions)
  4165. {
  4166. reflection_object *intern;
  4167. zend_module_entry *module;
  4168. if (zend_parse_parameters_none() == FAILURE) {
  4169. return;
  4170. }
  4171. GET_REFLECTION_OBJECT_PTR(module);
  4172. array_init(return_value);
  4173. if (module->functions) {
  4174. zval *function;
  4175. zend_function *fptr;
  4176. const zend_function_entry *func = module->functions;
  4177. /* Is there a better way of doing this? */
  4178. while (func->fname) {
  4179. if (zend_hash_find(EG(function_table), func->fname, strlen(func->fname) + 1, (void**) &fptr) == FAILURE) {
  4180. zend_error(E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
  4181. func++;
  4182. continue;
  4183. }
  4184. ALLOC_ZVAL(function);
  4185. reflection_function_factory(fptr, NULL, function TSRMLS_CC);
  4186. add_assoc_zval_ex(return_value, func->fname, strlen(func->fname)+1, function);
  4187. func++;
  4188. }
  4189. }
  4190. }
  4191. /* }}} */
  4192. static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  4193. {
  4194. zval *const_val;
  4195. zval *retval = va_arg(args, zval*);
  4196. int number = va_arg(args, int);
  4197. if (number == constant->module_number) {
  4198. ALLOC_ZVAL(const_val);
  4199. *const_val = constant->value;
  4200. zval_copy_ctor(const_val);
  4201. INIT_PZVAL(const_val);
  4202. add_assoc_zval_ex(retval, constant->name, constant->name_len, const_val);
  4203. }
  4204. return 0;
  4205. }
  4206. /* {{{ proto public array ReflectionExtension::getConstants()
  4207. Returns an associative array containing this extension's constants and their values */
  4208. ZEND_METHOD(reflection_extension, getConstants)
  4209. {
  4210. reflection_object *intern;
  4211. zend_module_entry *module;
  4212. if (zend_parse_parameters_none() == FAILURE) {
  4213. return;
  4214. }
  4215. GET_REFLECTION_OBJECT_PTR(module);
  4216. array_init(return_value);
  4217. zend_hash_apply_with_arguments(EG(zend_constants) TSRMLS_CC, (apply_func_args_t) _addconstant, 2, return_value, module->module_number);
  4218. }
  4219. /* }}} */
  4220. /* {{{ _addinientry */
  4221. static int _addinientry(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  4222. {
  4223. zval *retval = va_arg(args, zval*);
  4224. int number = va_arg(args, int);
  4225. if (number == ini_entry->module_number) {
  4226. if (ini_entry->value) {
  4227. add_assoc_stringl(retval, ini_entry->name, ini_entry->value, ini_entry->value_length, 1);
  4228. } else {
  4229. add_assoc_null(retval, ini_entry->name);
  4230. }
  4231. }
  4232. return ZEND_HASH_APPLY_KEEP;
  4233. }
  4234. /* }}} */
  4235. /* {{{ proto public array ReflectionExtension::getINIEntries()
  4236. Returns an associative array containing this extension's INI entries and their values */
  4237. ZEND_METHOD(reflection_extension, getINIEntries)
  4238. {
  4239. reflection_object *intern;
  4240. zend_module_entry *module;
  4241. if (zend_parse_parameters_none() == FAILURE) {
  4242. return;
  4243. }
  4244. GET_REFLECTION_OBJECT_PTR(module);
  4245. array_init(return_value);
  4246. zend_hash_apply_with_arguments(EG(ini_directives) TSRMLS_CC, (apply_func_args_t) _addinientry, 2, return_value, module->module_number);
  4247. }
  4248. /* }}} */
  4249. /* {{{ add_extension_class */
  4250. static int add_extension_class(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
  4251. {
  4252. zval *class_array = va_arg(args, zval*), *zclass;
  4253. struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
  4254. int add_reflection_class = va_arg(args, int);
  4255. if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
  4256. if (add_reflection_class) {
  4257. ALLOC_ZVAL(zclass);
  4258. zend_reflection_class_factory(*pce, zclass TSRMLS_CC);
  4259. add_assoc_zval_ex(class_array, (*pce)->name, (*pce)->name_length + 1, zclass);
  4260. } else {
  4261. add_next_index_stringl(class_array, (*pce)->name, (*pce)->name_length, 1);
  4262. }
  4263. }
  4264. return ZEND_HASH_APPLY_KEEP;
  4265. }
  4266. /* }}} */
  4267. /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses()
  4268. Returns an array containing ReflectionClass objects for all classes of this extension */
  4269. ZEND_METHOD(reflection_extension, getClasses)
  4270. {
  4271. reflection_object *intern;
  4272. zend_module_entry *module;
  4273. if (zend_parse_parameters_none() == FAILURE) {
  4274. return;
  4275. }
  4276. GET_REFLECTION_OBJECT_PTR(module);
  4277. array_init(return_value);
  4278. zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) add_extension_class, 3, return_value, module, 1);
  4279. }
  4280. /* }}} */
  4281. /* {{{ proto public array ReflectionExtension::getClassNames()
  4282. Returns an array containing all names of all classes of this extension */
  4283. ZEND_METHOD(reflection_extension, getClassNames)
  4284. {
  4285. reflection_object *intern;
  4286. zend_module_entry *module;
  4287. if (zend_parse_parameters_none() == FAILURE) {
  4288. return;
  4289. }
  4290. GET_REFLECTION_OBJECT_PTR(module);
  4291. array_init(return_value);
  4292. zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) add_extension_class, 3, return_value, module, 0);
  4293. }
  4294. /* }}} */
  4295. /* {{{ proto public array ReflectionExtension::getDependencies()
  4296. Returns an array containing all names of all extensions this extension depends on */
  4297. ZEND_METHOD(reflection_extension, getDependencies)
  4298. {
  4299. reflection_object *intern;
  4300. zend_module_entry *module;
  4301. const zend_module_dep *dep;
  4302. if (zend_parse_parameters_none() == FAILURE) {
  4303. return;
  4304. }
  4305. GET_REFLECTION_OBJECT_PTR(module);
  4306. array_init(return_value);
  4307. dep = module->deps;
  4308. if (!dep)
  4309. {
  4310. return;
  4311. }
  4312. while(dep->name) {
  4313. char *relation;
  4314. char *rel_type;
  4315. int len;
  4316. switch(dep->type) {
  4317. case MODULE_DEP_REQUIRED:
  4318. rel_type = "Required";
  4319. break;
  4320. case MODULE_DEP_CONFLICTS:
  4321. rel_type = "Conflicts";
  4322. break;
  4323. case MODULE_DEP_OPTIONAL:
  4324. rel_type = "Optional";
  4325. break;
  4326. default:
  4327. rel_type = "Error"; /* shouldn't happen */
  4328. break;
  4329. }
  4330. len = spprintf(&relation, 0, "%s%s%s%s%s",
  4331. rel_type,
  4332. dep->rel ? " " : "",
  4333. dep->rel ? dep->rel : "",
  4334. dep->version ? " " : "",
  4335. dep->version ? dep->version : "");
  4336. add_assoc_stringl(return_value, dep->name, relation, len, 0);
  4337. dep++;
  4338. }
  4339. }
  4340. /* }}} */
  4341. /* {{{ proto public void ReflectionExtension::info() U
  4342. Prints phpinfo block for the extension */
  4343. ZEND_METHOD(reflection_extension, info)
  4344. {
  4345. reflection_object *intern;
  4346. zend_module_entry *module;
  4347. if (zend_parse_parameters_none() == FAILURE) {
  4348. return;
  4349. }
  4350. GET_REFLECTION_OBJECT_PTR(module);
  4351. php_info_print_module(module TSRMLS_CC);
  4352. }
  4353. /* }}} */
  4354. /* {{{ method tables */
  4355. static const zend_function_entry reflection_exception_functions[] = {
  4356. {NULL, NULL, NULL}
  4357. };
  4358. ZEND_BEGIN_ARG_INFO(arginfo_reflection_getModifierNames, 0)
  4359. ZEND_ARG_INFO(0, modifiers)
  4360. ZEND_END_ARG_INFO()
  4361. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_export, 0, 0, 1)
  4362. ZEND_ARG_OBJ_INFO(0, reflector, Reflector, 0)
  4363. ZEND_ARG_INFO(0, return)
  4364. ZEND_END_ARG_INFO()
  4365. static const zend_function_entry reflection_functions[] = {
  4366. ZEND_ME(reflection, getModifierNames, arginfo_reflection_getModifierNames, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
  4367. ZEND_ME(reflection, export, arginfo_reflection_export, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
  4368. {NULL, NULL, NULL}
  4369. };
  4370. static const zend_function_entry reflector_functions[] = {
  4371. ZEND_FENTRY(export, NULL, NULL, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)
  4372. ZEND_ABSTRACT_ME(reflector, __toString, NULL)
  4373. {NULL, NULL, NULL}
  4374. };
  4375. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_export, 0, 0, 1)
  4376. ZEND_ARG_INFO(0, name)
  4377. ZEND_ARG_INFO(0, return)
  4378. ZEND_END_ARG_INFO()
  4379. ZEND_BEGIN_ARG_INFO(arginfo_reflection_function___construct, 0)
  4380. ZEND_ARG_INFO(0, name)
  4381. ZEND_END_ARG_INFO()
  4382. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_invoke, 0, 0, 0)
  4383. ZEND_ARG_INFO(0, args)
  4384. ZEND_END_ARG_INFO()
  4385. ZEND_BEGIN_ARG_INFO(arginfo_reflection_function_invokeArgs, 0)
  4386. ZEND_ARG_ARRAY_INFO(0, args, 0)
  4387. ZEND_END_ARG_INFO()
  4388. static const zend_function_entry reflection_function_abstract_functions[] = {
  4389. ZEND_ME(reflection, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
  4390. PHP_ABSTRACT_ME(reflection_function, __toString, NULL)
  4391. ZEND_ME(reflection_function, inNamespace, NULL, 0)
  4392. ZEND_ME(reflection_function, isClosure, NULL, 0)
  4393. ZEND_ME(reflection_function, isDeprecated, NULL, 0)
  4394. ZEND_ME(reflection_function, isInternal, NULL, 0)
  4395. ZEND_ME(reflection_function, isUserDefined, NULL, 0)
  4396. ZEND_ME(reflection_function, getDocComment, NULL, 0)
  4397. ZEND_ME(reflection_function, getEndLine, NULL, 0)
  4398. ZEND_ME(reflection_function, getExtension, NULL, 0)
  4399. ZEND_ME(reflection_function, getExtensionName, NULL, 0)
  4400. ZEND_ME(reflection_function, getFileName, NULL, 0)
  4401. ZEND_ME(reflection_function, getName, NULL, 0)
  4402. ZEND_ME(reflection_function, getNamespaceName, NULL, 0)
  4403. ZEND_ME(reflection_function, getNumberOfParameters, NULL, 0)
  4404. ZEND_ME(reflection_function, getNumberOfRequiredParameters, NULL, 0)
  4405. ZEND_ME(reflection_function, getParameters, NULL, 0)
  4406. ZEND_ME(reflection_function, getShortName, NULL, 0)
  4407. ZEND_ME(reflection_function, getStartLine, NULL, 0)
  4408. ZEND_ME(reflection_function, getStaticVariables, NULL, 0)
  4409. ZEND_ME(reflection_function, returnsReference, NULL, 0)
  4410. {NULL, NULL, NULL}
  4411. };
  4412. static const zend_function_entry reflection_function_functions[] = {
  4413. ZEND_ME(reflection_function, __construct, arginfo_reflection_function___construct, 0)
  4414. ZEND_ME(reflection_function, __toString, NULL, 0)
  4415. ZEND_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
  4416. ZEND_ME(reflection_function, isDisabled, NULL, 0)
  4417. ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
  4418. ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
  4419. {NULL, NULL, NULL}
  4420. };
  4421. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_export, 0, 0, 2)
  4422. ZEND_ARG_INFO(0, class)
  4423. ZEND_ARG_INFO(0, name)
  4424. ZEND_ARG_INFO(0, return)
  4425. ZEND_END_ARG_INFO()
  4426. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method___construct, 0, 0, 1)
  4427. ZEND_ARG_INFO(0, class_or_method)
  4428. ZEND_ARG_INFO(0, name)
  4429. ZEND_END_ARG_INFO()
  4430. ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invoke, 0)
  4431. ZEND_ARG_INFO(0, object)
  4432. ZEND_ARG_INFO(0, args)
  4433. ZEND_END_ARG_INFO()
  4434. ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invokeArgs, 0)
  4435. ZEND_ARG_INFO(0, object)
  4436. ZEND_ARG_ARRAY_INFO(0, args, 0)
  4437. ZEND_END_ARG_INFO()
  4438. static const zend_function_entry reflection_method_functions[] = {
  4439. ZEND_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
  4440. ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
  4441. ZEND_ME(reflection_method, __toString, NULL, 0)
  4442. ZEND_ME(reflection_method, isPublic, NULL, 0)
  4443. ZEND_ME(reflection_method, isPrivate, NULL, 0)
  4444. ZEND_ME(reflection_method, isProtected, NULL, 0)
  4445. ZEND_ME(reflection_method, isAbstract, NULL, 0)
  4446. ZEND_ME(reflection_method, isFinal, NULL, 0)
  4447. ZEND_ME(reflection_method, isStatic, NULL, 0)
  4448. ZEND_ME(reflection_method, isConstructor, NULL, 0)
  4449. ZEND_ME(reflection_method, isDestructor, NULL, 0)
  4450. ZEND_ME(reflection_method, getModifiers, NULL, 0)
  4451. ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
  4452. ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
  4453. ZEND_ME(reflection_method, getDeclaringClass, NULL, 0)
  4454. ZEND_ME(reflection_method, getPrototype, NULL, 0)
  4455. {NULL, NULL, NULL}
  4456. };
  4457. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_export, 0, 0, 1)
  4458. ZEND_ARG_INFO(0, argument)
  4459. ZEND_ARG_INFO(0, return)
  4460. ZEND_END_ARG_INFO()
  4461. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class___construct, 0)
  4462. ZEND_ARG_INFO(0, argument)
  4463. ZEND_END_ARG_INFO()
  4464. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getStaticPropertyValue, 0, 0, 1)
  4465. ZEND_ARG_INFO(0, name)
  4466. ZEND_ARG_INFO(0, default)
  4467. ZEND_END_ARG_INFO()
  4468. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_setStaticPropertyValue, 0)
  4469. ZEND_ARG_INFO(0, name)
  4470. ZEND_ARG_INFO(0, value)
  4471. ZEND_END_ARG_INFO()
  4472. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasMethod, 0)
  4473. ZEND_ARG_INFO(0, name)
  4474. ZEND_END_ARG_INFO()
  4475. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getMethod, 0)
  4476. ZEND_ARG_INFO(0, name)
  4477. ZEND_END_ARG_INFO()
  4478. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getMethods, 0, 0, 0)
  4479. ZEND_ARG_INFO(0, filter)
  4480. ZEND_END_ARG_INFO()
  4481. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasProperty, 0)
  4482. ZEND_ARG_INFO(0, name)
  4483. ZEND_END_ARG_INFO()
  4484. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getProperty, 0)
  4485. ZEND_ARG_INFO(0, name)
  4486. ZEND_END_ARG_INFO()
  4487. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getProperties, 0, 0, 0)
  4488. ZEND_ARG_INFO(0, filter)
  4489. ZEND_END_ARG_INFO()
  4490. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasConstant, 0)
  4491. ZEND_ARG_INFO(0, name)
  4492. ZEND_END_ARG_INFO()
  4493. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getConstant, 0)
  4494. ZEND_ARG_INFO(0, name)
  4495. ZEND_END_ARG_INFO()
  4496. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isInstance, 0)
  4497. ZEND_ARG_INFO(0, object)
  4498. ZEND_END_ARG_INFO()
  4499. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
  4500. ZEND_ARG_INFO(0, args)
  4501. ZEND_END_ARG_INFO()
  4502. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
  4503. ZEND_ARG_ARRAY_INFO(0, args, 0)
  4504. ZEND_END_ARG_INFO()
  4505. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isSubclassOf, 0)
  4506. ZEND_ARG_INFO(0, class)
  4507. ZEND_END_ARG_INFO()
  4508. ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_implementsInterface, 0)
  4509. ZEND_ARG_INFO(0, interface)
  4510. ZEND_END_ARG_INFO()
  4511. static const zend_function_entry reflection_class_functions[] = {
  4512. ZEND_ME(reflection, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
  4513. ZEND_ME(reflection_class, export, arginfo_reflection_class_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
  4514. ZEND_ME(reflection_class, __construct, arginfo_reflection_class___construct, 0)
  4515. ZEND_ME(reflection_class, __toString, NULL, 0)
  4516. ZEND_ME(reflection_class, getName, NULL, 0)
  4517. ZEND_ME(reflection_class, isInternal, NULL, 0)
  4518. ZEND_ME(reflection_class, isUserDefined, NULL, 0)
  4519. ZEND_ME(reflection_class, isInstantiable, NULL, 0)
  4520. ZEND_ME(reflection_class, getFileName, NULL, 0)
  4521. ZEND_ME(reflection_class, getStartLine, NULL, 0)
  4522. ZEND_ME(reflection_class, getEndLine, NULL, 0)
  4523. ZEND_ME(reflection_class, getDocComment, NULL, 0)
  4524. ZEND_ME(reflection_class, getConstructor, NULL, 0)
  4525. ZEND_ME(reflection_class, hasMethod, arginfo_reflection_class_hasMethod, 0)
  4526. ZEND_ME(reflection_class, getMethod, arginfo_reflection_class_getMethod, 0)
  4527. ZEND_ME(reflection_class, getMethods, arginfo_reflection_class_getMethods, 0)
  4528. ZEND_ME(reflection_class, hasProperty, arginfo_reflection_class_hasProperty, 0)
  4529. ZEND_ME(reflection_class, getProperty, arginfo_reflection_class_getProperty, 0)
  4530. ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
  4531. ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
  4532. ZEND_ME(reflection_class, getConstants, NULL, 0)
  4533. ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
  4534. ZEND_ME(reflection_class, getInterfaces, NULL, 0)
  4535. ZEND_ME(reflection_class, getInterfaceNames, NULL, 0)
  4536. ZEND_ME(reflection_class, isInterface, NULL, 0)
  4537. ZEND_ME(reflection_class, isAbstract, NULL, 0)
  4538. ZEND_ME(reflection_class, isFinal, NULL, 0)
  4539. ZEND_ME(reflection_class, getModifiers, NULL, 0)
  4540. ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
  4541. ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
  4542. ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
  4543. ZEND_ME(reflection_class, getParentClass, NULL, 0)
  4544. ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
  4545. ZEND_ME(reflection_class, getStaticProperties, NULL, 0)
  4546. ZEND_ME(reflection_class, getStaticPropertyValue, arginfo_reflection_class_getStaticPropertyValue, 0)
  4547. ZEND_ME(reflection_class, setStaticPropertyValue, arginfo_reflection_class_setStaticPropertyValue, 0)
  4548. ZEND_ME(reflection_class, getDefaultProperties, NULL, 0)
  4549. ZEND_ME(reflection_class, isIterateable, NULL, 0)
  4550. ZEND_ME(reflection_class, implementsInterface, arginfo_reflection_class_implementsInterface, 0)
  4551. ZEND_ME(reflection_class, getExtension, NULL, 0)
  4552. ZEND_ME(reflection_class, getExtensionName, NULL, 0)
  4553. ZEND_ME(reflection_class, inNamespace, NULL, 0)
  4554. ZEND_ME(reflection_class, getNamespaceName, NULL, 0)
  4555. ZEND_ME(reflection_class, getShortName, NULL, 0)
  4556. {NULL, NULL, NULL}
  4557. };
  4558. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_object_export, 0, 0, 1)
  4559. ZEND_ARG_INFO(0, argument)
  4560. ZEND_ARG_INFO(0, return)
  4561. ZEND_END_ARG_INFO()
  4562. ZEND_BEGIN_ARG_INFO(arginfo_reflection_object___construct, 0)
  4563. ZEND_ARG_INFO(0, argument)
  4564. ZEND_END_ARG_INFO()
  4565. static const zend_function_entry reflection_object_functions[] = {
  4566. ZEND_ME(reflection_object, export, arginfo_reflection_object_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
  4567. ZEND_ME(reflection_object, __construct, arginfo_reflection_object___construct, 0)
  4568. {NULL, NULL, NULL}
  4569. };
  4570. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_export, 0, 0, 1)
  4571. ZEND_ARG_INFO(0, argument)
  4572. ZEND_ARG_INFO(0, return)
  4573. ZEND_END_ARG_INFO()
  4574. ZEND_BEGIN_ARG_INFO(arginfo_reflection_property___construct, 0)
  4575. ZEND_ARG_INFO(0, argument)
  4576. ZEND_END_ARG_INFO()
  4577. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_getValue, 0, 0, 0)
  4578. ZEND_ARG_INFO(0, object)
  4579. ZEND_END_ARG_INFO()
  4580. ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setValue, 0)
  4581. ZEND_ARG_INFO(0, object)
  4582. ZEND_ARG_INFO(0, value)
  4583. ZEND_END_ARG_INFO()
  4584. ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccessible, 0)
  4585. ZEND_ARG_INFO(0, value)
  4586. ZEND_END_ARG_INFO()
  4587. static const zend_function_entry reflection_property_functions[] = {
  4588. ZEND_ME(reflection, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
  4589. ZEND_ME(reflection_property, export, arginfo_reflection_property_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
  4590. ZEND_ME(reflection_property, __construct, arginfo_reflection_property___construct, 0)
  4591. ZEND_ME(reflection_property, __toString, NULL, 0)
  4592. ZEND_ME(reflection_property, getName, NULL, 0)
  4593. ZEND_ME(reflection_property, getValue, arginfo_reflection_property_getValue, 0)
  4594. ZEND_ME(reflection_property, setValue, arginfo_reflection_property_setValue, 0)
  4595. ZEND_ME(reflection_property, isPublic, NULL, 0)
  4596. ZEND_ME(reflection_property, isPrivate, NULL, 0)
  4597. ZEND_ME(reflection_property, isProtected, NULL, 0)
  4598. ZEND_ME(reflection_property, isStatic, NULL, 0)
  4599. ZEND_ME(reflection_property, isDefault, NULL, 0)
  4600. ZEND_ME(reflection_property, getModifiers, NULL, 0)
  4601. ZEND_ME(reflection_property, getDeclaringClass, NULL, 0)
  4602. ZEND_ME(reflection_property, getDocComment, NULL, 0)
  4603. ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0)
  4604. {NULL, NULL, NULL}
  4605. };
  4606. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
  4607. ZEND_ARG_INFO(0, function)
  4608. ZEND_ARG_INFO(0, parameter)
  4609. ZEND_ARG_INFO(0, return)
  4610. ZEND_END_ARG_INFO()
  4611. ZEND_BEGIN_ARG_INFO(arginfo_reflection_parameter___construct, 0)
  4612. ZEND_ARG_INFO(0, function)
  4613. ZEND_ARG_INFO(0, parameter)
  4614. ZEND_END_ARG_INFO()
  4615. static const zend_function_entry reflection_parameter_functions[] = {
  4616. ZEND_ME(reflection, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
  4617. ZEND_ME(reflection_parameter, export, arginfo_reflection_parameter_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
  4618. ZEND_ME(reflection_parameter, __construct, arginfo_reflection_parameter___construct, 0)
  4619. ZEND_ME(reflection_parameter, __toString, NULL, 0)
  4620. ZEND_ME(reflection_parameter, getName, NULL, 0)
  4621. ZEND_ME(reflection_parameter, isPassedByReference, NULL, 0)
  4622. ZEND_ME(reflection_parameter, getDeclaringFunction, NULL, 0)
  4623. ZEND_ME(reflection_parameter, getDeclaringClass, NULL, 0)
  4624. ZEND_ME(reflection_parameter, getClass, NULL, 0)
  4625. ZEND_ME(reflection_parameter, isArray, NULL, 0)
  4626. ZEND_ME(reflection_parameter, allowsNull, NULL, 0)
  4627. ZEND_ME(reflection_parameter, getPosition, NULL, 0)
  4628. ZEND_ME(reflection_parameter, isOptional, NULL, 0)
  4629. ZEND_ME(reflection_parameter, isDefaultValueAvailable, NULL, 0)
  4630. ZEND_ME(reflection_parameter, getDefaultValue, NULL, 0)
  4631. {NULL, NULL, NULL}
  4632. };
  4633. ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
  4634. ZEND_ARG_INFO(0, name)
  4635. ZEND_ARG_INFO(0, return)
  4636. ZEND_END_ARG_INFO()
  4637. ZEND_BEGIN_ARG_INFO(arginfo_reflection_extension___construct, 0)
  4638. ZEND_ARG_INFO(0, name)
  4639. ZEND_END_ARG_INFO()
  4640. static const zend_function_entry reflection_extension_functions[] = {
  4641. ZEND_ME(reflection, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
  4642. ZEND_ME(reflection_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
  4643. ZEND_ME(reflection_extension, __construct, arginfo_reflection_extension___construct, 0)
  4644. ZEND_ME(reflection_extension, __toString, NULL, 0)
  4645. ZEND_ME(reflection_extension, getName, NULL, 0)
  4646. ZEND_ME(reflection_extension, getVersion, NULL, 0)
  4647. ZEND_ME(reflection_extension, getFunctions, NULL, 0)
  4648. ZEND_ME(reflection_extension, getConstants, NULL, 0)
  4649. ZEND_ME(reflection_extension, getINIEntries, NULL, 0)
  4650. ZEND_ME(reflection_extension, getClasses, NULL, 0)
  4651. ZEND_ME(reflection_extension, getClassNames, NULL, 0)
  4652. ZEND_ME(reflection_extension, getDependencies, NULL, 0)
  4653. ZEND_ME(reflection_extension, info, NULL, 0)
  4654. {NULL, NULL, NULL}
  4655. };
  4656. /* }}} */
  4657. const zend_function_entry reflection_ext_functions[] = { /* {{{ */
  4658. {NULL, NULL, NULL}
  4659. }; /* }}} */
  4660. static zend_object_handlers *zend_std_obj_handlers;
  4661. /* {{{ _reflection_write_property */
  4662. static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
  4663. {
  4664. if ((Z_TYPE_P(member) == IS_STRING)
  4665. && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
  4666. && ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name")))
  4667. || (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
  4668. {
  4669. zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
  4670. "Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
  4671. }
  4672. else
  4673. {
  4674. zend_std_obj_handlers->write_property(object, member, value TSRMLS_CC);
  4675. }
  4676. }
  4677. /* }}} */
  4678. PHP_MINIT_FUNCTION(reflection) /* {{{ */
  4679. {
  4680. zend_class_entry _reflection_entry;
  4681. zend_std_obj_handlers = zend_get_std_object_handlers();
  4682. memcpy(&reflection_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
  4683. reflection_object_handlers.clone_obj = NULL;
  4684. reflection_object_handlers.write_property = _reflection_write_property;
  4685. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions);
  4686. reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
  4687. INIT_CLASS_ENTRY(_reflection_entry, "Reflection", reflection_functions);
  4688. reflection_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
  4689. INIT_CLASS_ENTRY(_reflection_entry, "Reflector", reflector_functions);
  4690. reflector_ptr = zend_register_internal_interface(&_reflection_entry TSRMLS_CC);
  4691. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions);
  4692. _reflection_entry.create_object = reflection_objects_new;
  4693. reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
  4694. reflection_register_implement(reflection_function_abstract_ptr, reflector_ptr TSRMLS_CC);
  4695. zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT TSRMLS_CC);
  4696. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", reflection_function_functions);
  4697. _reflection_entry.create_object = reflection_objects_new;
  4698. reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr, NULL TSRMLS_CC);
  4699. zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4700. REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
  4701. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions);
  4702. _reflection_entry.create_object = reflection_objects_new;
  4703. reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
  4704. reflection_register_implement(reflection_parameter_ptr, reflector_ptr TSRMLS_CC);
  4705. zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4706. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
  4707. _reflection_entry.create_object = reflection_objects_new;
  4708. reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr, NULL TSRMLS_CC);
  4709. zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4710. zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4711. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
  4712. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
  4713. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PROTECTED", ZEND_ACC_PROTECTED);
  4714. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PRIVATE", ZEND_ACC_PRIVATE);
  4715. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
  4716. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
  4717. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions);
  4718. _reflection_entry.create_object = reflection_objects_new;
  4719. reflection_class_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
  4720. reflection_register_implement(reflection_class_ptr, reflector_ptr TSRMLS_CC);
  4721. zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4722. REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
  4723. REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
  4724. REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL_CLASS);
  4725. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions);
  4726. _reflection_entry.create_object = reflection_objects_new;
  4727. reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr, NULL TSRMLS_CC);
  4728. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", reflection_property_functions);
  4729. _reflection_entry.create_object = reflection_objects_new;
  4730. reflection_property_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
  4731. reflection_register_implement(reflection_property_ptr, reflector_ptr TSRMLS_CC);
  4732. zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4733. zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4734. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
  4735. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
  4736. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
  4737. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
  4738. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions);
  4739. _reflection_entry.create_object = reflection_objects_new;
  4740. reflection_extension_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
  4741. reflection_register_implement(reflection_extension_ptr, reflector_ptr TSRMLS_CC);
  4742. zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
  4743. return SUCCESS;
  4744. } /* }}} */
  4745. PHP_MINFO_FUNCTION(reflection) /* {{{ */
  4746. {
  4747. php_info_print_table_start();
  4748. php_info_print_table_header(2, "Reflection", "enabled");
  4749. php_info_print_table_row(2, "Version", "$Revision$");
  4750. php_info_print_table_end();
  4751. } /* }}} */
  4752. zend_module_entry reflection_module_entry = { /* {{{ */
  4753. STANDARD_MODULE_HEADER,
  4754. "Reflection",
  4755. reflection_ext_functions,
  4756. PHP_MINIT(reflection),
  4757. NULL,
  4758. NULL,
  4759. NULL,
  4760. PHP_MINFO(reflection),
  4761. "$Revision$",
  4762. STANDARD_MODULE_PROPERTIES
  4763. }; /* }}} */
  4764. /*
  4765. * Local variables:
  4766. * tab-width: 4
  4767. * c-basic-offset: 4
  4768. * indent-tabs-mode: t
  4769. * End:
  4770. * vim600: noet sw=4 ts=4 fdm=marker
  4771. */