PageRenderTime 123ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 1ms

/ext/reflection/php_reflection.c

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