PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 2ms

/ext/reflection/php_reflection.c

http://github.com/php/php-src
C | 6370 lines | 4715 code | 900 blank | 755 comment | 1196 complexity | 65db7fe1e3d541645c5f50f6d0594b66 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | http://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Authors: Timm Friebe <thekid@thekid.de> |
  14. | George Schlossnagle <george@omniti.com> |
  15. | Andrei Zmievski <andrei@gravitonic.com> |
  16. | Marcus Boerger <helly@php.net> |
  17. | Johannes Schlueter <johannes@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "php.h"
  24. #include "php_ini.h"
  25. #include "php_reflection.h"
  26. #include "ext/standard/info.h"
  27. #include "ext/standard/sha1.h"
  28. #include "ext/standard/php_random.h"
  29. #include "zend.h"
  30. #include "zend_API.h"
  31. #include "zend_exceptions.h"
  32. #include "zend_operators.h"
  33. #include "zend_constants.h"
  34. #include "zend_ini.h"
  35. #include "zend_interfaces.h"
  36. #include "zend_closures.h"
  37. #include "zend_generators.h"
  38. #include "zend_extensions.h"
  39. #include "zend_builtin_functions.h"
  40. #include "zend_smart_str.h"
  41. #include "php_reflection_arginfo.h"
  42. /* Key used to avoid leaking addresses in ReflectionProperty::getId() */
  43. #define REFLECTION_KEY_LEN 16
  44. ZEND_BEGIN_MODULE_GLOBALS(reflection)
  45. zend_bool key_initialized;
  46. unsigned char key[REFLECTION_KEY_LEN];
  47. ZEND_END_MODULE_GLOBALS(reflection)
  48. ZEND_DECLARE_MODULE_GLOBALS(reflection)
  49. #define REFLECTION_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(reflection, v)
  50. static zend_always_inline zval *reflection_prop_name(zval *object) {
  51. /* $name is always in the first property slot. */
  52. ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 1);
  53. return &Z_OBJ_P(object)->properties_table[0];
  54. }
  55. static zend_always_inline zval *reflection_prop_class(zval *object) {
  56. /* $class is always in the second property slot. */
  57. ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 2);
  58. return &Z_OBJ_P(object)->properties_table[1];
  59. }
  60. /* Class entry pointers */
  61. PHPAPI zend_class_entry *reflector_ptr;
  62. PHPAPI zend_class_entry *reflection_exception_ptr;
  63. PHPAPI zend_class_entry *reflection_ptr;
  64. PHPAPI zend_class_entry *reflection_function_abstract_ptr;
  65. PHPAPI zend_class_entry *reflection_function_ptr;
  66. PHPAPI zend_class_entry *reflection_generator_ptr;
  67. PHPAPI zend_class_entry *reflection_parameter_ptr;
  68. PHPAPI zend_class_entry *reflection_type_ptr;
  69. PHPAPI zend_class_entry *reflection_named_type_ptr;
  70. PHPAPI zend_class_entry *reflection_union_type_ptr;
  71. PHPAPI zend_class_entry *reflection_class_ptr;
  72. PHPAPI zend_class_entry *reflection_object_ptr;
  73. PHPAPI zend_class_entry *reflection_method_ptr;
  74. PHPAPI zend_class_entry *reflection_property_ptr;
  75. PHPAPI zend_class_entry *reflection_class_constant_ptr;
  76. PHPAPI zend_class_entry *reflection_extension_ptr;
  77. PHPAPI zend_class_entry *reflection_zend_extension_ptr;
  78. PHPAPI zend_class_entry *reflection_reference_ptr;
  79. /* Exception throwing macro */
  80. #define _DO_THROW(msg) \
  81. zend_throw_exception(reflection_exception_ptr, msg, 0);
  82. #define GET_REFLECTION_OBJECT() do { \
  83. intern = Z_REFLECTION_P(ZEND_THIS); \
  84. if (intern->ptr == NULL) { \
  85. if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) { \
  86. RETURN_THROWS(); \
  87. } \
  88. zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object"); \
  89. RETURN_THROWS(); \
  90. } \
  91. } while (0)
  92. #define GET_REFLECTION_OBJECT_PTR(target) do { \
  93. GET_REFLECTION_OBJECT(); \
  94. target = intern->ptr; \
  95. } while (0)
  96. /* Class constants */
  97. #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value) \
  98. zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (zend_long)value);
  99. /* {{{ Object structure */
  100. /* Struct for properties */
  101. typedef struct _property_reference {
  102. zend_property_info *prop;
  103. zend_string *unmangled_name;
  104. } property_reference;
  105. /* Struct for parameters */
  106. typedef struct _parameter_reference {
  107. uint32_t offset;
  108. zend_bool required;
  109. struct _zend_arg_info *arg_info;
  110. zend_function *fptr;
  111. } parameter_reference;
  112. /* Struct for type hints */
  113. typedef struct _type_reference {
  114. zend_type type;
  115. /* Whether to use backwards compatible null representation */
  116. zend_bool legacy_behavior;
  117. } type_reference;
  118. typedef enum {
  119. REF_TYPE_OTHER, /* Must be 0 */
  120. REF_TYPE_FUNCTION,
  121. REF_TYPE_GENERATOR,
  122. REF_TYPE_PARAMETER,
  123. REF_TYPE_TYPE,
  124. REF_TYPE_PROPERTY,
  125. REF_TYPE_CLASS_CONSTANT
  126. } reflection_type_t;
  127. /* Struct for reflection objects */
  128. typedef struct {
  129. zval obj;
  130. void *ptr;
  131. zend_class_entry *ce;
  132. reflection_type_t ref_type;
  133. unsigned int ignore_visibility:1;
  134. zend_object zo;
  135. } reflection_object;
  136. static inline reflection_object *reflection_object_from_obj(zend_object *obj) {
  137. return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo));
  138. }
  139. #define Z_REFLECTION_P(zv) reflection_object_from_obj(Z_OBJ_P((zv)))
  140. /* }}} */
  141. static zend_object_handlers reflection_object_handlers;
  142. static zend_always_inline uint32_t prop_get_flags(property_reference *ref) {
  143. return ref->prop ? ref->prop->flags : ZEND_ACC_PUBLIC;
  144. }
  145. static inline zend_bool is_closure_invoke(zend_class_entry *ce, zend_string *lcname) {
  146. return ce == zend_ce_closure
  147. && zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME);
  148. }
  149. static void _default_get_name(zval *object, zval *return_value) /* {{{ */
  150. {
  151. zval *name = reflection_prop_name(object);
  152. if (Z_ISUNDEF_P(name)) {
  153. RETURN_FALSE;
  154. }
  155. ZVAL_COPY(return_value, name);
  156. }
  157. /* }}} */
  158. static zend_function *_copy_function(zend_function *fptr) /* {{{ */
  159. {
  160. if (fptr
  161. && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
  162. {
  163. zend_function *copy_fptr;
  164. copy_fptr = emalloc(sizeof(zend_function));
  165. memcpy(copy_fptr, fptr, sizeof(zend_function));
  166. copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name);
  167. return copy_fptr;
  168. } else {
  169. /* no copy needed */
  170. return fptr;
  171. }
  172. }
  173. /* }}} */
  174. static void _free_function(zend_function *fptr) /* {{{ */
  175. {
  176. if (fptr
  177. && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
  178. {
  179. zend_string_release_ex(fptr->internal_function.function_name, 0);
  180. zend_free_trampoline(fptr);
  181. }
  182. }
  183. /* }}} */
  184. static void reflection_free_objects_storage(zend_object *object) /* {{{ */
  185. {
  186. reflection_object *intern = reflection_object_from_obj(object);
  187. parameter_reference *reference;
  188. property_reference *prop_reference;
  189. if (intern->ptr) {
  190. switch (intern->ref_type) {
  191. case REF_TYPE_PARAMETER:
  192. reference = (parameter_reference*)intern->ptr;
  193. _free_function(reference->fptr);
  194. efree(intern->ptr);
  195. break;
  196. case REF_TYPE_TYPE:
  197. {
  198. type_reference *type_ref = intern->ptr;
  199. if (ZEND_TYPE_HAS_NAME(type_ref->type)) {
  200. zend_string_release(ZEND_TYPE_NAME(type_ref->type));
  201. }
  202. efree(type_ref);
  203. break;
  204. }
  205. case REF_TYPE_FUNCTION:
  206. _free_function(intern->ptr);
  207. break;
  208. case REF_TYPE_PROPERTY:
  209. prop_reference = (property_reference*)intern->ptr;
  210. zend_string_release_ex(prop_reference->unmangled_name, 0);
  211. efree(intern->ptr);
  212. break;
  213. case REF_TYPE_GENERATOR:
  214. case REF_TYPE_CLASS_CONSTANT:
  215. case REF_TYPE_OTHER:
  216. break;
  217. }
  218. }
  219. intern->ptr = NULL;
  220. zval_ptr_dtor(&intern->obj);
  221. zend_object_std_dtor(object);
  222. }
  223. /* }}} */
  224. static HashTable *reflection_get_gc(zend_object *obj, zval **gc_data, int *gc_data_count) /* {{{ */
  225. {
  226. reflection_object *intern = reflection_object_from_obj(obj);
  227. *gc_data = &intern->obj;
  228. *gc_data_count = 1;
  229. return zend_std_get_properties(obj);
  230. }
  231. /* }}} */
  232. static zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ */
  233. {
  234. reflection_object *intern = zend_object_alloc(sizeof(reflection_object), class_type);
  235. zend_object_std_init(&intern->zo, class_type);
  236. object_properties_init(&intern->zo, class_type);
  237. intern->zo.handlers = &reflection_object_handlers;
  238. return &intern->zo;
  239. }
  240. /* }}} */
  241. static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
  242. {
  243. object_init_ex(object, pce);
  244. return object;
  245. }
  246. /* }}} */
  247. static void _const_string(smart_str *str, char *name, zval *value, char *indent);
  248. static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent);
  249. static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent);
  250. static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char* indent);
  251. static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent);
  252. static void _extension_string(smart_str *str, zend_module_entry *module, char *indent);
  253. static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent);
  254. /* {{{ _class_string */
  255. static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent)
  256. {
  257. int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
  258. zend_string *sub_indent = strpprintf(0, "%s ", indent);
  259. /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
  260. if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
  261. smart_str_append_printf(str, "%s%s", indent, ZSTR_VAL(ce->info.user.doc_comment));
  262. smart_str_appendc(str, '\n');
  263. }
  264. if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
  265. smart_str_append_printf(str, "%sObject of class [ ", indent);
  266. } else {
  267. char *kind = "Class";
  268. if (ce->ce_flags & ZEND_ACC_INTERFACE) {
  269. kind = "Interface";
  270. } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
  271. kind = "Trait";
  272. }
  273. smart_str_append_printf(str, "%s%s [ ", indent, kind);
  274. }
  275. smart_str_append_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
  276. if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
  277. smart_str_append_printf(str, ":%s", ce->info.internal.module->name);
  278. }
  279. smart_str_append_printf(str, "> ");
  280. if (ce->get_iterator != NULL) {
  281. smart_str_append_printf(str, "<iterateable> ");
  282. }
  283. if (ce->ce_flags & ZEND_ACC_INTERFACE) {
  284. smart_str_append_printf(str, "interface ");
  285. } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
  286. smart_str_append_printf(str, "trait ");
  287. } else {
  288. if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
  289. smart_str_append_printf(str, "abstract ");
  290. }
  291. if (ce->ce_flags & ZEND_ACC_FINAL) {
  292. smart_str_append_printf(str, "final ");
  293. }
  294. smart_str_append_printf(str, "class ");
  295. }
  296. smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name));
  297. if (ce->parent) {
  298. smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
  299. }
  300. if (ce->num_interfaces) {
  301. uint32_t i;
  302. ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
  303. if (ce->ce_flags & ZEND_ACC_INTERFACE) {
  304. smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->interfaces[0]->name));
  305. } else {
  306. smart_str_append_printf(str, " implements %s", ZSTR_VAL(ce->interfaces[0]->name));
  307. }
  308. for (i = 1; i < ce->num_interfaces; ++i) {
  309. smart_str_append_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name));
  310. }
  311. }
  312. smart_str_append_printf(str, " ] {\n");
  313. /* The information where a class is declared is only available for user classes */
  314. if (ce->type == ZEND_USER_CLASS) {
  315. smart_str_append_printf(str, "%s @@ %s %d-%d\n", indent, ZSTR_VAL(ce->info.user.filename),
  316. ce->info.user.line_start, ce->info.user.line_end);
  317. }
  318. /* Constants */
  319. smart_str_append_printf(str, "\n");
  320. count = zend_hash_num_elements(&ce->constants_table);
  321. smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, count);
  322. if (count > 0) {
  323. zend_string *key;
  324. zend_class_constant *c;
  325. ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
  326. _class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent));
  327. if (UNEXPECTED(EG(exception))) {
  328. return;
  329. }
  330. } ZEND_HASH_FOREACH_END();
  331. }
  332. smart_str_append_printf(str, "%s }\n", indent);
  333. /* Static properties */
  334. /* counting static properties */
  335. count = zend_hash_num_elements(&ce->properties_info);
  336. if (count > 0) {
  337. zend_property_info *prop;
  338. ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
  339. if ((prop->flags & ZEND_ACC_PRIVATE) && prop->ce != ce) {
  340. count_shadow_props++;
  341. } else if (prop->flags & ZEND_ACC_STATIC) {
  342. count_static_props++;
  343. }
  344. } ZEND_HASH_FOREACH_END();
  345. }
  346. /* static properties */
  347. smart_str_append_printf(str, "\n%s - Static properties [%d] {\n", indent, count_static_props);
  348. if (count_static_props > 0) {
  349. zend_property_info *prop;
  350. ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
  351. if ((prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
  352. _property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
  353. }
  354. } ZEND_HASH_FOREACH_END();
  355. }
  356. smart_str_append_printf(str, "%s }\n", indent);
  357. /* Static methods */
  358. /* counting static methods */
  359. count = zend_hash_num_elements(&ce->function_table);
  360. if (count > 0) {
  361. zend_function *mptr;
  362. ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
  363. if (mptr->common.fn_flags & ZEND_ACC_STATIC
  364. && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
  365. {
  366. count_static_funcs++;
  367. }
  368. } ZEND_HASH_FOREACH_END();
  369. }
  370. /* static methods */
  371. smart_str_append_printf(str, "\n%s - Static methods [%d] {", indent, count_static_funcs);
  372. if (count_static_funcs > 0) {
  373. zend_function *mptr;
  374. ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
  375. if (mptr->common.fn_flags & ZEND_ACC_STATIC
  376. && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
  377. {
  378. smart_str_append_printf(str, "\n");
  379. _function_string(str, mptr, ce, ZSTR_VAL(sub_indent));
  380. }
  381. } ZEND_HASH_FOREACH_END();
  382. } else {
  383. smart_str_append_printf(str, "\n");
  384. }
  385. smart_str_append_printf(str, "%s }\n", indent);
  386. /* Default/Implicit properties */
  387. count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
  388. smart_str_append_printf(str, "\n%s - Properties [%d] {\n", indent, count);
  389. if (count > 0) {
  390. zend_property_info *prop;
  391. ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
  392. if (!(prop->flags & ZEND_ACC_STATIC)
  393. && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
  394. _property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
  395. }
  396. } ZEND_HASH_FOREACH_END();
  397. }
  398. smart_str_append_printf(str, "%s }\n", indent);
  399. if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
  400. HashTable *properties = Z_OBJ_HT_P(obj)->get_properties(Z_OBJ_P(obj));
  401. zend_string *prop_name;
  402. smart_str prop_str = {0};
  403. count = 0;
  404. if (properties && zend_hash_num_elements(properties)) {
  405. ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) {
  406. if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
  407. if (!zend_hash_exists(&ce->properties_info, prop_name)) {
  408. count++;
  409. _property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent));
  410. }
  411. }
  412. } ZEND_HASH_FOREACH_END();
  413. }
  414. smart_str_append_printf(str, "\n%s - Dynamic properties [%d] {\n", indent, count);
  415. smart_str_append_smart_str(str, &prop_str);
  416. smart_str_append_printf(str, "%s }\n", indent);
  417. smart_str_free(&prop_str);
  418. }
  419. /* Non static methods */
  420. count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
  421. if (count > 0) {
  422. zend_function *mptr;
  423. smart_str method_str = {0};
  424. count = 0;
  425. ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
  426. if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
  427. && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
  428. {
  429. zend_function *closure;
  430. /* see if this is a closure */
  431. if (obj && is_closure_invoke(ce, mptr->common.function_name)
  432. && (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
  433. {
  434. mptr = closure;
  435. } else {
  436. closure = NULL;
  437. }
  438. smart_str_appendc(&method_str, '\n');
  439. _function_string(&method_str, mptr, ce, ZSTR_VAL(sub_indent));
  440. count++;
  441. _free_function(closure);
  442. }
  443. } ZEND_HASH_FOREACH_END();
  444. smart_str_append_printf(str, "\n%s - Methods [%d] {", indent, count);
  445. smart_str_append_smart_str(str, &method_str);
  446. if (!count) {
  447. smart_str_append_printf(str, "\n");
  448. }
  449. smart_str_free(&method_str);
  450. } else {
  451. smart_str_append_printf(str, "\n%s - Methods [0] {\n", indent);
  452. }
  453. smart_str_append_printf(str, "%s }\n", indent);
  454. smart_str_append_printf(str, "%s}\n", indent);
  455. zend_string_release_ex(sub_indent, 0);
  456. }
  457. /* }}} */
  458. /* {{{ _const_string */
  459. static void _const_string(smart_str *str, char *name, zval *value, char *indent)
  460. {
  461. const char *type = zend_zval_type_name(value);
  462. if (Z_TYPE_P(value) == IS_ARRAY) {
  463. smart_str_append_printf(str, "%s Constant [ %s %s ] { Array }\n",
  464. indent, type, name);
  465. } else if (Z_TYPE_P(value) == IS_STRING) {
  466. smart_str_append_printf(str, "%s Constant [ %s %s ] { %s }\n",
  467. indent, type, name, Z_STRVAL_P(value));
  468. } else {
  469. zend_string *tmp_value_str;
  470. zend_string *value_str = zval_get_tmp_string(value, &tmp_value_str);
  471. smart_str_append_printf(str, "%s Constant [ %s %s ] { %s }\n",
  472. indent, type, name, ZSTR_VAL(value_str));
  473. zend_tmp_string_release(tmp_value_str);
  474. }
  475. }
  476. /* }}} */
  477. /* {{{ _class_const_string */
  478. static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char *indent)
  479. {
  480. char *visibility = zend_visibility_string(Z_ACCESS_FLAGS(c->value));
  481. const char *type;
  482. zval_update_constant_ex(&c->value, c->ce);
  483. type = zend_zval_type_name(&c->value);
  484. if (Z_TYPE(c->value) == IS_ARRAY) {
  485. smart_str_append_printf(str, "%sConstant [ %s %s %s ] { Array }\n",
  486. indent, visibility, type, name);
  487. } else {
  488. zend_string *tmp_value_str;
  489. zend_string *value_str = zval_get_tmp_string(&c->value, &tmp_value_str);
  490. smart_str_append_printf(str, "%sConstant [ %s %s %s ] { %s }\n",
  491. indent, visibility, type, name, ZSTR_VAL(value_str));
  492. zend_tmp_string_release(tmp_value_str);
  493. }
  494. }
  495. /* }}} */
  496. static zend_op *get_recv_op(zend_op_array *op_array, uint32_t offset)
  497. {
  498. zend_op *op = op_array->opcodes;
  499. zend_op *end = op + op_array->last;
  500. ++offset;
  501. while (op < end) {
  502. if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
  503. || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == offset)
  504. {
  505. return op;
  506. }
  507. ++op;
  508. }
  509. ZEND_ASSERT(0 && "Failed to find op");
  510. return NULL;
  511. }
  512. static zval *get_default_from_recv(zend_op_array *op_array, uint32_t offset) {
  513. zend_op *recv = get_recv_op(op_array, offset);
  514. if (!recv || recv->opcode != ZEND_RECV_INIT) {
  515. return NULL;
  516. }
  517. return RT_CONSTANT(recv, recv->op2);
  518. }
  519. static int format_default_value(smart_str *str, zval *value, zend_class_entry *scope) {
  520. zval zv;
  521. ZVAL_COPY(&zv, value);
  522. if (UNEXPECTED(zval_update_constant_ex(&zv, scope) == FAILURE)) {
  523. zval_ptr_dtor(&zv);
  524. return FAILURE;
  525. }
  526. if (Z_TYPE(zv) == IS_TRUE) {
  527. smart_str_appends(str, "true");
  528. } else if (Z_TYPE(zv) == IS_FALSE) {
  529. smart_str_appends(str, "false");
  530. } else if (Z_TYPE(zv) == IS_NULL) {
  531. smart_str_appends(str, "NULL");
  532. } else if (Z_TYPE(zv) == IS_STRING) {
  533. smart_str_appendc(str, '\'');
  534. smart_str_appendl(str, Z_STRVAL(zv), MIN(Z_STRLEN(zv), 15));
  535. if (Z_STRLEN(zv) > 15) {
  536. smart_str_appends(str, "...");
  537. }
  538. smart_str_appendc(str, '\'');
  539. } else if (Z_TYPE(zv) == IS_ARRAY) {
  540. smart_str_appends(str, "Array");
  541. } else {
  542. zend_string *tmp_zv_str;
  543. zend_string *zv_str = zval_get_tmp_string(&zv, &tmp_zv_str);
  544. smart_str_append(str, zv_str);
  545. zend_tmp_string_release(tmp_zv_str);
  546. }
  547. zval_ptr_dtor(&zv);
  548. return SUCCESS;
  549. }
  550. static inline zend_bool has_internal_arg_info(const zend_function *fptr) {
  551. return fptr->type == ZEND_INTERNAL_FUNCTION
  552. && !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO);
  553. }
  554. /* {{{ _parameter_string */
  555. static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, char* indent)
  556. {
  557. smart_str_append_printf(str, "Parameter #%d [ ", offset);
  558. if (!required) {
  559. smart_str_append_printf(str, "<optional> ");
  560. } else {
  561. smart_str_append_printf(str, "<required> ");
  562. }
  563. if (ZEND_TYPE_IS_SET(arg_info->type)) {
  564. zend_string *type_str = zend_type_to_string(arg_info->type);
  565. smart_str_append(str, type_str);
  566. smart_str_appendc(str, ' ');
  567. zend_string_release(type_str);
  568. }
  569. if (ZEND_ARG_SEND_MODE(arg_info)) {
  570. smart_str_appendc(str, '&');
  571. }
  572. if (ZEND_ARG_IS_VARIADIC(arg_info)) {
  573. smart_str_appends(str, "...");
  574. }
  575. smart_str_append_printf(str, "$%s", has_internal_arg_info(fptr)
  576. ? ((zend_internal_arg_info*)arg_info)->name : ZSTR_VAL(arg_info->name));
  577. if (!required) {
  578. if (fptr->type == ZEND_INTERNAL_FUNCTION) {
  579. smart_str_appends(str, " = ");
  580. if (((zend_internal_arg_info*)arg_info)->default_value) {
  581. smart_str_appends(str, ((zend_internal_arg_info*)arg_info)->default_value);
  582. } else {
  583. smart_str_appends(str, "<default>");
  584. }
  585. } else {
  586. zval *default_value = get_default_from_recv((zend_op_array*)fptr, offset);
  587. if (default_value) {
  588. smart_str_appends(str, " = ");
  589. if (format_default_value(str, default_value, fptr->common.scope) == FAILURE) {
  590. return;
  591. }
  592. }
  593. }
  594. }
  595. smart_str_appends(str, " ]");
  596. }
  597. /* }}} */
  598. /* {{{ _function_parameter_string */
  599. static void _function_parameter_string(smart_str *str, zend_function *fptr, char* indent)
  600. {
  601. struct _zend_arg_info *arg_info = fptr->common.arg_info;
  602. uint32_t i, num_args, num_required = fptr->common.required_num_args;
  603. if (!arg_info) {
  604. return;
  605. }
  606. num_args = fptr->common.num_args;
  607. if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
  608. num_args++;
  609. }
  610. smart_str_appendc(str, '\n');
  611. smart_str_append_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
  612. for (i = 0; i < num_args; i++) {
  613. smart_str_append_printf(str, "%s ", indent);
  614. _parameter_string(str, fptr, arg_info, i, i < num_required, indent);
  615. smart_str_appendc(str, '\n');
  616. arg_info++;
  617. }
  618. smart_str_append_printf(str, "%s}\n", indent);
  619. }
  620. /* }}} */
  621. /* {{{ _function_closure_string */
  622. static void _function_closure_string(smart_str *str, zend_function *fptr, char* indent)
  623. {
  624. uint32_t i, count;
  625. zend_string *key;
  626. HashTable *static_variables;
  627. if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
  628. return;
  629. }
  630. static_variables = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
  631. count = zend_hash_num_elements(static_variables);
  632. if (!count) {
  633. return;
  634. }
  635. smart_str_append_printf(str, "\n");
  636. smart_str_append_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
  637. i = 0;
  638. ZEND_HASH_FOREACH_STR_KEY(static_variables, key) {
  639. smart_str_append_printf(str, "%s Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key));
  640. } ZEND_HASH_FOREACH_END();
  641. smart_str_append_printf(str, "%s}\n", indent);
  642. }
  643. /* }}} */
  644. /* {{{ _function_string */
  645. static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent)
  646. {
  647. smart_str param_indent = {0};
  648. zend_function *overwrites;
  649. zend_string *lc_name;
  650. /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
  651. * What's "wrong" is that any whitespace before the doc comment start is
  652. * swallowed, leading to an unaligned comment.
  653. */
  654. if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
  655. smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->op_array.doc_comment));
  656. }
  657. smart_str_appendl(str, indent, strlen(indent));
  658. smart_str_append_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
  659. smart_str_append_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
  660. if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
  661. smart_str_appends(str, ", deprecated");
  662. }
  663. if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
  664. smart_str_append_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
  665. }
  666. if (scope && fptr->common.scope) {
  667. if (fptr->common.scope != scope) {
  668. smart_str_append_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
  669. } else if (fptr->common.scope->parent) {
  670. lc_name = zend_string_tolower(fptr->common.function_name);
  671. if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
  672. if (fptr->common.scope != overwrites->common.scope) {
  673. smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
  674. }
  675. }
  676. zend_string_release_ex(lc_name, 0);
  677. }
  678. }
  679. if (fptr->common.prototype && fptr->common.prototype->common.scope) {
  680. smart_str_append_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name));
  681. }
  682. if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
  683. smart_str_appends(str, ", ctor");
  684. }
  685. smart_str_appends(str, "> ");
  686. if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
  687. smart_str_appends(str, "abstract ");
  688. }
  689. if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
  690. smart_str_appends(str, "final ");
  691. }
  692. if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
  693. smart_str_appends(str, "static ");
  694. }
  695. if (fptr->common.scope) {
  696. /* These are mutually exclusive */
  697. switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
  698. case ZEND_ACC_PUBLIC:
  699. smart_str_appends(str, "public ");
  700. break;
  701. case ZEND_ACC_PRIVATE:
  702. smart_str_appends(str, "private ");
  703. break;
  704. case ZEND_ACC_PROTECTED:
  705. smart_str_appends(str, "protected ");
  706. break;
  707. default:
  708. smart_str_appends(str, "<visibility error> ");
  709. break;
  710. }
  711. smart_str_appends(str, "method ");
  712. } else {
  713. smart_str_appends(str, "function ");
  714. }
  715. if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
  716. smart_str_appendc(str, '&');
  717. }
  718. smart_str_append_printf(str, "%s ] {\n", ZSTR_VAL(fptr->common.function_name));
  719. /* The information where a function is declared is only available for user classes */
  720. if (fptr->type == ZEND_USER_FUNCTION) {
  721. smart_str_append_printf(str, "%s @@ %s %d - %d\n", indent,
  722. ZSTR_VAL(fptr->op_array.filename),
  723. fptr->op_array.line_start,
  724. fptr->op_array.line_end);
  725. }
  726. smart_str_append_printf(&param_indent, "%s ", indent);
  727. smart_str_0(&param_indent);
  728. if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
  729. _function_closure_string(str, fptr, ZSTR_VAL(param_indent.s));
  730. }
  731. _function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
  732. smart_str_free(&param_indent);
  733. if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  734. smart_str_append_printf(str, " %s- Return [ ", indent);
  735. if (ZEND_TYPE_IS_SET(fptr->common.arg_info[-1].type)) {
  736. zend_string *type_str = zend_type_to_string(fptr->common.arg_info[-1].type);
  737. smart_str_append_printf(str, "%s ", ZSTR_VAL(type_str));
  738. zend_string_release(type_str);
  739. }
  740. smart_str_appends(str, "]\n");
  741. }
  742. smart_str_append_printf(str, "%s}\n", indent);
  743. }
  744. /* }}} */
  745. static zval *property_get_default(zend_property_info *prop_info) {
  746. zend_class_entry *ce = prop_info->ce;
  747. if (prop_info->flags & ZEND_ACC_STATIC) {
  748. zval *prop = &ce->default_static_members_table[prop_info->offset];
  749. ZVAL_DEINDIRECT(prop);
  750. return prop;
  751. } else {
  752. return &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
  753. }
  754. }
  755. /* {{{ _property_string */
  756. static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent)
  757. {
  758. smart_str_append_printf(str, "%sProperty [ ", indent);
  759. if (!prop) {
  760. smart_str_append_printf(str, "<dynamic> public $%s", prop_name);
  761. } else {
  762. /* These are mutually exclusive */
  763. switch (prop->flags & ZEND_ACC_PPP_MASK) {
  764. case ZEND_ACC_PUBLIC:
  765. smart_str_appends(str, "public ");
  766. break;
  767. case ZEND_ACC_PRIVATE:
  768. smart_str_appends(str, "private ");
  769. break;
  770. case ZEND_ACC_PROTECTED:
  771. smart_str_appends(str, "protected ");
  772. break;
  773. }
  774. if (prop->flags & ZEND_ACC_STATIC) {
  775. smart_str_appends(str, "static ");
  776. }
  777. if (ZEND_TYPE_IS_SET(prop->type)) {
  778. zend_string *type_str = zend_type_to_string(prop->type);
  779. smart_str_append(str, type_str);
  780. smart_str_appendc(str, ' ');
  781. zend_string_release(type_str);
  782. }
  783. if (!prop_name) {
  784. const char *class_name;
  785. zend_unmangle_property_name(prop->name, &class_name, &prop_name);
  786. }
  787. smart_str_append_printf(str, "$%s", prop_name);
  788. zval *default_value = property_get_default(prop);
  789. if (!Z_ISUNDEF_P(default_value)) {
  790. smart_str_appends(str, " = ");
  791. if (format_default_value(str, default_value, prop->ce) == FAILURE) {
  792. return;
  793. }
  794. }
  795. }
  796. smart_str_appends(str, " ]\n");
  797. }
  798. /* }}} */
  799. static void _extension_ini_string(zend_ini_entry *ini_entry, smart_str *str, char *indent, int number) /* {{{ */
  800. {
  801. char *comma = "";
  802. if (number == ini_entry->module_number) {
  803. smart_str_append_printf(str, " %sEntry [ %s <", indent, ZSTR_VAL(ini_entry->name));
  804. if (ini_entry->modifiable == ZEND_INI_ALL) {
  805. smart_str_appends(str, "ALL");
  806. } else {
  807. if (ini_entry->modifiable & ZEND_INI_USER) {
  808. smart_str_appends(str, "USER");
  809. comma = ",";
  810. }
  811. if (ini_entry->modifiable & ZEND_INI_PERDIR) {
  812. smart_str_append_printf(str, "%sPERDIR", comma);
  813. comma = ",";
  814. }
  815. if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
  816. smart_str_append_printf(str, "%sSYSTEM", comma);
  817. }
  818. }
  819. smart_str_appends(str, "> ]\n");
  820. smart_str_append_printf(str, " %s Current = '%s'\n", indent, ini_entry->value ? ZSTR_VAL(ini_entry->value) : "");
  821. if (ini_entry->modified) {
  822. smart_str_append_printf(str, " %s Default = '%s'\n", indent, ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : "");
  823. }
  824. smart_str_append_printf(str, " %s}\n", indent);
  825. }
  826. }
  827. /* }}} */
  828. static void _extension_class_string(zend_class_entry *ce, zend_string *key, smart_str *str, char *indent, zend_module_entry *module, int *num_classes) /* {{{ */
  829. {
  830. if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
  831. /* dump class if it is not an alias */
  832. if (zend_string_equals_ci(ce->name, key)) {
  833. smart_str_append_printf(str, "\n");
  834. _class_string(str, ce, NULL, indent);
  835. (*num_classes)++;
  836. }
  837. }
  838. }
  839. /* }}} */
  840. static void _extension_string(smart_str *str, zend_module_entry *module, char *indent) /* {{{ */
  841. {
  842. smart_str_append_printf(str, "%sExtension [ ", indent);
  843. if (module->type == MODULE_PERSISTENT) {
  844. smart_str_appends(str, "<persistent>");
  845. }
  846. if (module->type == MODULE_TEMPORARY) {
  847. smart_str_appends(str, "<temporary>" );
  848. }
  849. smart_str_append_printf(str, " extension #%d %s version %s ] {\n",
  850. module->module_number, module->name,
  851. (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
  852. if (module->deps) {
  853. const zend_module_dep* dep = module->deps;
  854. smart_str_appends(str, "\n - Dependencies {\n");
  855. while(dep->name) {
  856. smart_str_append_printf(str, "%s Dependency [ %s (", indent, dep->name);
  857. switch(dep->type) {
  858. case MODULE_DEP_REQUIRED:
  859. smart_str_appends(str, "Required");
  860. break;
  861. case MODULE_DEP_CONFLICTS:
  862. smart_str_appends(str, "Conflicts");
  863. break;
  864. case MODULE_DEP_OPTIONAL:
  865. smart_str_appends(str, "Optional");
  866. break;
  867. default:
  868. smart_str_appends(str, "Error"); /* shouldn't happen */
  869. break;
  870. }
  871. if (dep->rel) {
  872. smart_str_append_printf(str, " %s", dep->rel);
  873. }
  874. if (dep->version) {
  875. smart_str_append_printf(str, " %s", dep->version);
  876. }
  877. smart_str_appends(str, ") ]\n");
  878. dep++;
  879. }
  880. smart_str_append_printf(str, "%s }\n", indent);
  881. }
  882. {
  883. smart_str str_ini = {0};
  884. zend_ini_entry *ini_entry;
  885. ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) {
  886. _extension_ini_string(ini_entry, &str_ini, indent, module->module_number);
  887. } ZEND_HASH_FOREACH_END();
  888. if (smart_str_get_len(&str_ini) > 0) {
  889. smart_str_append_printf(str, "\n - INI {\n");
  890. smart_str_append_smart_str(str, &str_ini);
  891. smart_str_append_printf(str, "%s }\n", indent);
  892. }
  893. smart_str_free(&str_ini);
  894. }
  895. {
  896. smart_str str_constants = {0};
  897. zend_constant *constant;
  898. int num_constants = 0;
  899. ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) {
  900. if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) {
  901. _const_string(&str_constants, ZSTR_VAL(constant->name), &constant->value, indent);
  902. num_constants++;
  903. }
  904. } ZEND_HASH_FOREACH_END();
  905. if (num_constants) {
  906. smart_str_append_printf(str, "\n - Constants [%d] {\n", num_constants);
  907. smart_str_append_smart_str(str, &str_constants);
  908. smart_str_append_printf(str, "%s }\n", indent);
  909. }
  910. smart_str_free(&str_constants);
  911. }
  912. {
  913. zend_function *fptr;
  914. int first = 1;
  915. ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
  916. if (fptr->common.type==ZEND_INTERNAL_FUNCTION
  917. && fptr->internal_function.module == module) {
  918. if (first) {
  919. smart_str_append_printf(str, "\n - Functions {\n");
  920. first = 0;
  921. }
  922. _function_string(str, fptr, NULL, " ");
  923. }
  924. } ZEND_HASH_FOREACH_END();
  925. if (!first) {
  926. smart_str_append_printf(str, "%s }\n", indent);
  927. }
  928. }
  929. {
  930. zend_string *sub_indent = strpprintf(0, "%s ", indent);
  931. smart_str str_classes = {0};
  932. zend_string *key;
  933. zend_class_entry *ce;
  934. int num_classes = 0;
  935. ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
  936. _extension_class_string(ce, key, &str_classes, ZSTR_VAL(sub_indent), module, &num_classes);
  937. } ZEND_HASH_FOREACH_END();
  938. if (num_classes) {
  939. smart_str_append_printf(str, "\n - Classes [%d] {", num_classes);
  940. smart_str_append_smart_str(str, &str_classes);
  941. smart_str_append_printf(str, "%s }\n", indent);
  942. }
  943. smart_str_free(&str_classes);
  944. zend_string_release_ex(sub_indent, 0);
  945. }
  946. smart_str_append_printf(str, "%s}\n", indent);
  947. }
  948. /* }}} */
  949. static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent) /* {{{ */
  950. {
  951. smart_str_append_printf(str, "%sZend Extension [ %s ", indent, extension->name);
  952. if (extension->version) {
  953. smart_str_append_printf(str, "%s ", extension->version);
  954. }
  955. if (extension->copyright) {
  956. smart_str_append_printf(str, "%s ", extension->copyright);
  957. }
  958. if (extension->author) {
  959. smart_str_append_printf(str, "by %s ", extension->author);
  960. }
  961. if (extension->URL) {
  962. smart_str_append_printf(str, "<%s> ", extension->URL);
  963. }
  964. smart_str_appends(str, "]\n");
  965. }
  966. /* }}} */
  967. /* {{{ _function_check_flag */
  968. static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
  969. {
  970. reflection_object *intern;
  971. zend_function *mptr;
  972. if (zend_parse_parameters_none() == FAILURE) {
  973. RETURN_THROWS();
  974. }
  975. GET_REFLECTION_OBJECT_PTR(mptr);
  976. RETURN_BOOL(mptr->common.fn_flags & mask);
  977. }
  978. /* }}} */
  979. /* {{{ zend_reflection_class_factory */
  980. PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object)
  981. {
  982. reflection_object *intern;
  983. reflection_instantiate(reflection_class_ptr, object);
  984. intern = Z_REFLECTION_P(object);
  985. intern->ptr = ce;
  986. intern->ref_type = REF_TYPE_OTHER;
  987. intern->ce = ce;
  988. ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
  989. }
  990. /* }}} */
  991. /* {{{ reflection_extension_factory */
  992. static void reflection_extension_factory(zval *object, const char *name_str)
  993. {
  994. reflection_object *intern;
  995. size_t name_len = strlen(name_str);
  996. zend_string *lcname;
  997. struct _zend_module_entry *module;
  998. lcname = zend_string_alloc(name_len, 0);
  999. zend_str_tolower_copy(ZSTR_VAL(lcname), name_str, name_len);
  1000. module = zend_hash_find_ptr(&module_registry, lcname);
  1001. zend_string_efree(lcname);
  1002. if (!module) {
  1003. return;
  1004. }
  1005. reflection_instantiate(reflection_extension_ptr, object);
  1006. intern = Z_REFLECTION_P(object);
  1007. intern->ptr = module;
  1008. intern->ref_type = REF_TYPE_OTHER;
  1009. intern->ce = NULL;
  1010. ZVAL_STRINGL(reflection_prop_name(object), module->name, name_len);
  1011. }
  1012. /* }}} */
  1013. /* {{{ reflection_parameter_factory */
  1014. static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, zval *object)
  1015. {
  1016. reflection_object *intern;
  1017. parameter_reference *reference;
  1018. zval *prop_name;
  1019. reflection_instantiate(reflection_parameter_ptr, object);
  1020. intern = Z_REFLECTION_P(object);
  1021. reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
  1022. reference->arg_info = arg_info;
  1023. reference->offset = offset;
  1024. reference->required = required;
  1025. reference->fptr = fptr;
  1026. intern->ptr = reference;
  1027. intern->ref_type = REF_TYPE_PARAMETER;
  1028. intern->ce = fptr->common.scope;
  1029. if (closure_object) {
  1030. Z_ADDREF_P(closure_object);
  1031. ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
  1032. }
  1033. prop_name = reflection_prop_name(object);
  1034. if (has_internal_arg_info(fptr)) {
  1035. ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)->name);
  1036. } else {
  1037. ZVAL_STR_COPY(prop_name, arg_info->name);
  1038. }
  1039. }
  1040. /* }}} */
  1041. /* For backwards compatibility reasons, we need to return T|null style unions
  1042. * as a ReflectionNamedType. Here we determine what counts as a union type and
  1043. * what doesn't. */
  1044. static zend_bool is_union_type(zend_type type) {
  1045. if (ZEND_TYPE_HAS_LIST(type)) {
  1046. return 1;
  1047. }
  1048. uint32_t type_mask_without_null = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type);
  1049. if (ZEND_TYPE_HAS_CLASS(type)) {
  1050. return type_mask_without_null != 0;
  1051. }
  1052. if (type_mask_without_null == MAY_BE_BOOL) {
  1053. return 0;
  1054. }
  1055. /* Check that only one bit is set. */
  1056. return (type_mask_without_null & (type_mask_without_null - 1)) != 0;
  1057. }
  1058. /* {{{ reflection_type_factory */
  1059. static void reflection_type_factory(zend_type type, zval *object, zend_bool legacy_behavior)
  1060. {
  1061. reflection_object *intern;
  1062. type_reference *reference;
  1063. zend_bool is_union = is_union_type(type);
  1064. reflection_instantiate(
  1065. is_union ? reflection_union_type_ptr : reflection_named_type_ptr, object);
  1066. intern = Z_REFLECTION_P(object);
  1067. reference = (type_reference*) emalloc(sizeof(type_reference));
  1068. reference->type = type;
  1069. reference->legacy_behavior = legacy_behavior && !is_union;
  1070. intern->ptr = reference;
  1071. intern->ref_type = REF_TYPE_TYPE;
  1072. /* Property types may be resolved during the lifetime of the ReflectionType.
  1073. * If we reference a string, make sure it doesn't get released. However, only
  1074. * do this for the top-level type, as resolutions inside type lists will be
  1075. * fully visible to us (we'd have to do a fully copy of the type if we wanted
  1076. * to prevent that). */
  1077. if (ZEND_TYPE_HAS_NAME(type)) {
  1078. zend_string_addref(ZEND_TYPE_NAME(type));
  1079. }
  1080. }
  1081. /* }}} */
  1082. /* {{{ reflection_function_factory */
  1083. static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
  1084. {
  1085. reflection_object *intern;
  1086. reflection_instantiate(reflection_function_ptr, object);
  1087. intern = Z_REFLECTION_P(object);
  1088. intern->ptr = function;
  1089. intern->ref_type = REF_TYPE_FUNCTION;
  1090. intern->ce = NULL;
  1091. if (closure_object) {
  1092. Z_ADDREF_P(closure_object);
  1093. ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
  1094. }
  1095. ZVAL_STR_COPY(reflection_prop_name(object), function->common.function_name);
  1096. }
  1097. /* }}} */
  1098. /* {{{ reflection_method_factory */
  1099. static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object)
  1100. {
  1101. reflection_object *intern;
  1102. reflection_instantiate(reflection_method_ptr, object);
  1103. intern = Z_REFLECTION_P(object);
  1104. intern->ptr = method;
  1105. intern->ref_type = REF_TYPE_FUNCTION;
  1106. intern->ce = ce;
  1107. if (closure_object) {
  1108. Z_ADDREF_P(closure_object);
  1109. ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
  1110. }
  1111. ZVAL_STR_COPY(reflection_prop_name(object), method->common.function_name);
  1112. ZVAL_STR_COPY(reflection_prop_class(object), method->common.scope->name);
  1113. }
  1114. /* }}} */
  1115. /* {{{ reflection_property_factory */
  1116. static void reflection_property_factory(zend_class_entry *ce, zend_string *name, zend_property_info *prop, zval *object)
  1117. {
  1118. reflection_object *intern;
  1119. property_reference *reference;
  1120. reflection_instantiate(reflection_property_ptr, object);
  1121. intern = Z_REFLECTION_P(object);
  1122. reference = (property_reference*) emalloc(sizeof(property_reference));
  1123. reference->prop = prop;
  1124. reference->unmangled_name = zend_string_copy(name);
  1125. intern->ptr = reference;
  1126. intern->ref_type = REF_TYPE_PROPERTY;
  1127. intern->ce = ce;
  1128. intern->ignore_visibility = 0;
  1129. ZVAL_STR_COPY(reflection_prop_name(object), name);
  1130. ZVAL_STR_COPY(reflection_prop_class(object), prop ? prop->ce->name : ce->name);
  1131. }
  1132. /* }}} */
  1133. static void reflection_property_factory_str(zend_class_entry *ce, const char *name_str, size_t name_len, zend_property_info *prop, zval *object)
  1134. {
  1135. zend_string *name = zend_string_init(name_str, name_len, 0);
  1136. reflection_property_factory(ce, name, prop, object);
  1137. zend_string_release(name);
  1138. }
  1139. /* {{{ reflection_class_constant_factory */
  1140. static void reflection_class_constant_factory(zend_string *name_str, zend_class_constant *constant, zval *object)
  1141. {
  1142. reflection_object *intern;
  1143. reflection_instantiate(reflection_class_constant_ptr, object);
  1144. intern = Z_REFLECTION_P(object);
  1145. intern->ptr = constant;
  1146. intern->ref_type = REF_TYPE_CLASS_CONSTANT;
  1147. intern->ce = constant->ce;
  1148. intern->ignore_visibility = 0;
  1149. ZVAL_STR_COPY(reflection_prop_name(object), name_str);
  1150. ZVAL_STR_COPY(reflection_prop_class(object), constant->ce->name);
  1151. }
  1152. /* }}} */
  1153. static int get_parameter_default(zval *result, parameter_reference *param) {
  1154. if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
  1155. return zend_get_default_from_internal_arg_info(
  1156. result, (zend_internal_arg_info *) param->arg_info);
  1157. } else {
  1158. zval *default_value = get_default_from_recv((zend_op_array *) param->fptr, param->offset);
  1159. if (!default_value) {
  1160. return FAILURE;
  1161. }
  1162. ZVAL_COPY(result, default_value);
  1163. return SUCCESS;
  1164. }
  1165. }
  1166. /* {{{ Preventing __clone from being called */
  1167. ZEND_METHOD(ReflectionClass, __clone)
  1168. {
  1169. /* Should never be executable */
  1170. _DO_THROW("Cannot clone object using __clone()");
  1171. }
  1172. /* }}} */
  1173. /* {{{ proto public static array Reflection::getModifierNames(int modifiers)
  1174. Returns an array of modifier names */
  1175. ZEND_METHOD(Reflection, getModifierNames)
  1176. {
  1177. zend_long modifiers;
  1178. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &modifiers) == FAILURE) {
  1179. RETURN_THROWS();
  1180. }
  1181. array_init(return_value);
  1182. if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
  1183. add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1);
  1184. }
  1185. if (modifiers & ZEND_ACC_FINAL) {
  1186. add_next_index_stringl(return_value, "final", sizeof("final")-1);
  1187. }
  1188. /* These are mutually exclusive */
  1189. switch (modifiers & ZEND_ACC_PPP_MASK) {
  1190. case ZEND_ACC_PUBLIC:
  1191. add_next_index_stringl(return_value, "public", sizeof("public")-1);
  1192. break;
  1193. case ZEND_ACC_PRIVATE:
  1194. add_next_index_stringl(return_value, "private", sizeof("private")-1);
  1195. break;
  1196. case ZEND_ACC_PROTECTED:
  1197. add_next_index_stringl(return_value, "protected", sizeof("protected")-1);
  1198. break;
  1199. }
  1200. if (modifiers & ZEND_ACC_STATIC) {
  1201. add_next_index_stringl(return_value, "static", sizeof("static")-1);
  1202. }
  1203. }
  1204. /* }}} */
  1205. /* {{{ proto public void ReflectionFunction::__construct(string name)
  1206. Constructor. Throws an Exception in case the given function does not exist */
  1207. ZEND_METHOD(ReflectionFunction, __construct)
  1208. {
  1209. zval *object;
  1210. zval *closure = NULL;
  1211. reflection_object *intern;
  1212. zend_function *fptr;
  1213. zend_string *fname, *lcname;
  1214. object = ZEND_THIS;
  1215. intern = Z_REFLECTION_P(object);
  1216. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &closure, zend_ce_closure) == SUCCESS) {
  1217. fptr = (zend_function*)zend_get_closure_method_def(closure);
  1218. Z_ADDREF_P(closure);
  1219. } else {
  1220. ALLOCA_FLAG(use_heap)
  1221. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &fname) == FAILURE) {
  1222. RETURN_THROWS();
  1223. }
  1224. if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
  1225. /* Ignore leading "\" */
  1226. ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
  1227. zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
  1228. fptr = zend_fetch_function(lcname);
  1229. ZSTR_ALLOCA_FREE(lcname, use_heap);
  1230. } else {
  1231. lcname = zend_string_tolower(fname);
  1232. fptr = zend_fetch_function(lcname);
  1233. zend_string_release(lcname);
  1234. }
  1235. if (fptr == NULL) {
  1236. zend_throw_exception_ex(reflection_exception_ptr, 0,
  1237. "Function %s() does not exist", ZSTR_VAL(fname));
  1238. RETURN_THROWS();
  1239. }
  1240. }
  1241. ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name);
  1242. intern->ptr = fptr;
  1243. intern->ref_type = REF_TYPE_FUNCTION;
  1244. if (closure) {
  1245. ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure));
  1246. } else {
  1247. ZVAL_UNDEF(&intern->obj);
  1248. }
  1249. intern->ce = NULL;
  1250. }
  1251. /* }}} */
  1252. /* {{{ proto public string ReflectionFunction::__toString()
  1253. Returns a string representation */
  1254. ZEND_METHOD(ReflectionFunction, __toString)
  1255. {
  1256. reflection_object *intern;
  1257. zend_function *fptr;
  1258. smart_str str = {0};
  1259. if (zend_parse_parameters_none() == FAILURE) {
  1260. RETURN_THROWS();
  1261. }
  1262. GET_REFLECTION_OBJECT_PTR(fptr);
  1263. _function_string(&str, fptr, intern->ce, "");
  1264. RETURN_STR(smart_str_extract(&str));
  1265. }
  1266. /* }}} */
  1267. /* {{{ proto public string ReflectionFunction::getName()
  1268. Returns this function's name */
  1269. ZEND_METHOD(ReflectionFunctionAbstract, getName)
  1270. {
  1271. reflection_object *intern;
  1272. zend_function *fptr;
  1273. if (zend_parse_parameters_none() == FAILURE) {
  1274. RETURN_THROWS();
  1275. }
  1276. GET_REFLECTION_OBJECT_PTR(fptr);
  1277. RETURN_STR_COPY(fptr->common.function_name);
  1278. }
  1279. /* }}} */
  1280. /* {{{ proto public bool ReflectionFunction::isClosure()
  1281. Returns whether this is a closure */
  1282. ZEND_METHOD(ReflectionFunctionAbstract, isClosure)
  1283. {
  1284. reflection_object *intern;
  1285. zend_function *fptr;
  1286. if (zend_parse_parameters_none() == FAILURE) {
  1287. RETURN_THROWS();
  1288. }
  1289. GET_REFLECTION_OBJECT_PTR(fptr);
  1290. RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
  1291. }
  1292. /* }}} */
  1293. /* {{{ proto public bool ReflectionFunction::getClosureThis()
  1294. Returns this pointer bound to closure */
  1295. ZEND_METHOD(ReflectionFunctionAbstract, getClosureThis)
  1296. {
  1297. reflection_object *intern;
  1298. zval* closure_this;
  1299. if (zend_parse_parameters_none() == FAILURE) {
  1300. RETURN_THROWS();
  1301. }
  1302. GET_REFLECTION_OBJECT();
  1303. if (!Z_ISUNDEF(intern->obj)) {
  1304. closure_this = zend_get_closure_this_ptr(&intern->obj);
  1305. if (!Z_ISUNDEF_P(closure_this)) {
  1306. Z_ADDREF_P(closure_this);
  1307. ZVAL_OBJ(return_value, Z_OBJ_P(closure_this));
  1308. }
  1309. }
  1310. }
  1311. /* }}} */
  1312. /* {{{ proto public ReflectionClass ReflectionFunction::getClosureScopeClass()
  1313. Returns the scope associated to the closure */
  1314. ZEND_METHOD(ReflectionFunctionAbstract, getClosureScopeClass)
  1315. {
  1316. reflection_object *intern;
  1317. const zend_function *closure_func;
  1318. if (zend_parse_parameters_none() == FAILURE) {
  1319. RETURN_THROWS();
  1320. }
  1321. GET_REFLECTION_OBJECT();
  1322. if (!Z_ISUNDEF(intern->obj)) {
  1323. closure_func = zend_get_closure_method_def(&intern->obj);
  1324. if (closure_func && closure_func->common.scope) {
  1325. zend_reflection_class_factory(closure_func->common.scope, return_value);
  1326. }
  1327. }
  1328. }
  1329. /* }}} */
  1330. /* {{{ proto public mixed ReflectionFunction::getClosure()
  1331. Returns a dynamically created closure for the function */
  1332. ZEND_METHOD(ReflectionFunction, getClosure)
  1333. {
  1334. reflection_object *intern;
  1335. zend_function *fptr;
  1336. if (zend_parse_parameters_none() == FAILURE) {
  1337. RETURN_THROWS();
  1338. }
  1339. GET_REFLECTION_OBJECT_PTR(fptr);
  1340. if (!Z_ISUNDEF(intern->obj)) {
  1341. /* Closures are immutable objects */
  1342. Z_ADDREF(intern->obj);
  1343. ZVAL_OBJ(return_value, Z_OBJ(intern->obj));
  1344. } else {
  1345. zend_create_fake_closure(return_value, fptr, NULL, NULL, NULL);
  1346. }
  1347. }
  1348. /* }}} */
  1349. /* {{{ proto public bool ReflectionFunction::isInternal()
  1350. Returns whether this is an internal function */
  1351. ZEND_METHOD(ReflectionFunctionAbstract, isInternal)
  1352. {
  1353. reflection_object *intern;
  1354. zend_function *fptr;
  1355. if (zend_parse_parameters_none() == FAILURE) {
  1356. RETURN_THROWS();
  1357. }
  1358. GET_REFLECTION_OBJECT_PTR(fptr);
  1359. RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
  1360. }
  1361. /* }}} */
  1362. /* {{{ proto public bool ReflectionFunction::isUserDefined()
  1363. Returns whether this is a user-defined function */
  1364. ZEND_METHOD(ReflectionFunctionAbstract, isUserDefined)
  1365. {
  1366. reflection_object *intern;
  1367. zend_function *fptr;
  1368. if (zend_parse_parameters_none() == FAILURE) {
  1369. RETURN_THROWS();
  1370. }
  1371. GET_REFLECTION_OBJECT_PTR(fptr);
  1372. RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
  1373. }
  1374. /* }}} */
  1375. /* {{{ proto public bool ReflectionFunction::isDisabled()
  1376. Returns whether this function has been disabled or not */
  1377. ZEND_METHOD(ReflectionFunction, isDisabled)
  1378. {
  1379. if (zend_parse_parameters_none() == FAILURE) {
  1380. RETURN_THROWS();
  1381. }
  1382. /* A disabled function cannot be queried using Reflection. */
  1383. RETURN_FALSE;
  1384. }
  1385. /* }}} */
  1386. /* {{{ proto public string ReflectionFunction::getFileName()
  1387. Returns the filename of the file this function was declared in */
  1388. ZEND_METHOD(ReflectionFunctionAbstract, getFileName)
  1389. {
  1390. reflection_object *intern;
  1391. zend_function *fptr;
  1392. if (zend_parse_parameters_none() == FAILURE) {
  1393. RETURN_THROWS();
  1394. }
  1395. GET_REFLECTION_OBJECT_PTR(fptr);
  1396. if (fptr->type == ZEND_USER_FUNCTION) {
  1397. RETURN_STR_COPY(fptr->op_array.filename);
  1398. }
  1399. RETURN_FALSE;
  1400. }
  1401. /* }}} */
  1402. /* {{{ proto public int ReflectionFunction::getStartLine()
  1403. Returns the line this function's declaration starts at */
  1404. ZEND_METHOD(ReflectionFunctionAbstract, getStartLine)
  1405. {
  1406. reflection_object *intern;
  1407. zend_function *fptr;
  1408. if (zend_parse_parameters_none() == FAILURE) {
  1409. RETURN_THROWS();
  1410. }
  1411. GET_REFLECTION_OBJECT_PTR(fptr);
  1412. if (fptr->type == ZEND_USER_FUNCTION) {
  1413. RETURN_LONG(fptr->op_array.line_start);
  1414. }
  1415. RETURN_FALSE;
  1416. }
  1417. /* }}} */
  1418. /* {{{ proto public int ReflectionFunction::getEndLine()
  1419. Returns the line this function's declaration ends at */
  1420. ZEND_METHOD(ReflectionFunctionAbstract, getEndLine)
  1421. {
  1422. reflection_object *intern;
  1423. zend_function *fptr;
  1424. if (zend_parse_parameters_none() == FAILURE) {
  1425. RETURN_THROWS();
  1426. }
  1427. GET_REFLECTION_OBJECT_PTR(fptr);
  1428. if (fptr->type == ZEND_USER_FUNCTION) {
  1429. RETURN_LONG(fptr->op_array.line_end);
  1430. }
  1431. RETURN_FALSE;
  1432. }
  1433. /* }}} */
  1434. /* {{{ proto public string ReflectionFunction::getDocComment()
  1435. Returns the doc comment for this function */
  1436. ZEND_METHOD(ReflectionFunctionAbstract, getDocComment)
  1437. {
  1438. reflection_object *intern;
  1439. zend_function *fptr;
  1440. if (zend_parse_parameters_none() == FAILURE) {
  1441. RETURN_THROWS();
  1442. }
  1443. GET_REFLECTION_OBJECT_PTR(fptr);
  1444. if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
  1445. RETURN_STR_COPY(fptr->op_array.doc_comment);
  1446. }
  1447. RETURN_FALSE;
  1448. }
  1449. /* }}} */
  1450. /* {{{ proto public array ReflectionFunction::getStaticVariables()
  1451. Returns an associative array containing this function's static variables and their values */
  1452. ZEND_METHOD(ReflectionFunctionAbstract, getStaticVariables)
  1453. {
  1454. reflection_object *intern;
  1455. zend_function *fptr;
  1456. zval *val;
  1457. if (zend_parse_parameters_none() == FAILURE) {
  1458. RETURN_THROWS();
  1459. }
  1460. GET_REFLECTION_OBJECT_PTR(fptr);
  1461. /* Return an empty array in case no static variables exist */
  1462. if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
  1463. HashTable *ht;
  1464. array_init(return_value);
  1465. ht = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
  1466. if (!ht) {
  1467. ZEND_ASSERT(fptr->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
  1468. ht = zend_array_dup(fptr->op_array.static_variables);
  1469. ZEND_MAP_PTR_SET(fptr->op_array.static_variables_ptr, ht);
  1470. }
  1471. ZEND_HASH_FOREACH_VAL(ht, val) {
  1472. if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) {
  1473. return;
  1474. }
  1475. } ZEND_HASH_FOREACH_END();
  1476. zend_hash_copy(Z_ARRVAL_P(return_value), ht, zval_add_ref);
  1477. } else {
  1478. RETURN_EMPTY_ARRAY();
  1479. }
  1480. }
  1481. /* }}} */
  1482. /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args])
  1483. Invokes the function */
  1484. ZEND_METHOD(ReflectionFunction, invoke)
  1485. {
  1486. zval retval;
  1487. zval *params = NULL;
  1488. int result, num_args = 0;
  1489. zend_fcall_info fci;
  1490. zend_fcall_info_cache fcc;
  1491. reflection_object *intern;
  1492. zend_function *fptr;
  1493. GET_REFLECTION_OBJECT_PTR(fptr);
  1494. if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &params, &num_args) == FAILURE) {
  1495. RETURN_THROWS();
  1496. }
  1497. fci.size = sizeof(fci);
  1498. ZVAL_UNDEF(&fci.function_name);
  1499. fci.object = NULL;
  1500. fci.retval = &retval;
  1501. fci.param_count = num_args;
  1502. fci.params = params;
  1503. fci.no_separation = 1;
  1504. fcc.function_handler = fptr;
  1505. fcc.called_scope = NULL;
  1506. fcc.object = NULL;
  1507. if (!Z_ISUNDEF(intern->obj)) {
  1508. Z_OBJ_HT(intern->obj)->get_closure(
  1509. Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object, 0);
  1510. }
  1511. result = zend_call_function(&fci, &fcc);
  1512. if (result == FAILURE) {
  1513. zend_throw_exception_ex(reflection_exception_ptr, 0,
  1514. "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
  1515. RETURN_THROWS();
  1516. }
  1517. if (Z_TYPE(retval) != IS_UNDEF) {
  1518. if (Z_ISREF(retval)) {
  1519. zend_unwrap_reference(&retval);
  1520. }
  1521. ZVAL_COPY_VALUE(return_value, &retval);
  1522. }
  1523. }
  1524. /* }}} */
  1525. /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args)
  1526. Invokes the function and pass its arguments as array. */
  1527. ZEND_METHOD(ReflectionFunction, invokeArgs)
  1528. {
  1529. zval retval;
  1530. zval *params, *val;
  1531. int result;
  1532. int i, argc;
  1533. zend_fcall_info fci;
  1534. zend_fcall_info_cache fcc;
  1535. reflection_object *intern;
  1536. zend_function *fptr;
  1537. zval *param_array;
  1538. GET_REFLECTION_OBJECT_PTR(fptr);
  1539. if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &param_array) == FAILURE) {
  1540. RETURN_THROWS();
  1541. }
  1542. argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
  1543. params = safe_emalloc(sizeof(zval), argc, 0);
  1544. argc = 0;
  1545. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
  1546. ZVAL_COPY(&params[argc], val);
  1547. argc++;
  1548. } ZEND_HASH_FOREACH_END();
  1549. fci.size = sizeof(fci);
  1550. ZVAL_UNDEF(&fci.function_name);
  1551. fci.object = NULL;
  1552. fci.retval = &retval;
  1553. fci.param_count = argc;
  1554. fci.params = params;
  1555. fci.no_separation = 1;
  1556. fcc.function_handler = fptr;
  1557. fcc.called_scope = NULL;
  1558. fcc.object = NULL;
  1559. if (!Z_ISUNDEF(intern->obj)) {
  1560. Z_OBJ_HT(intern->obj)->get_closure(
  1561. Z_OBJ(intern->obj), &fcc.called_scope, &fcc.function_handler, &fcc.object, 0);
  1562. }
  1563. result = zend_call_function(&fci, &fcc);
  1564. for (i = 0; i < argc; i++) {
  1565. zval_ptr_dtor(&params[i]);
  1566. }
  1567. efree(params);
  1568. if (result == FAILURE) {
  1569. zend_throw_exception_ex(reflection_exception_ptr, 0,
  1570. "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
  1571. RETURN_THROWS();
  1572. }
  1573. if (Z_TYPE(retval) != IS_UNDEF) {
  1574. if (Z_ISREF(retval)) {
  1575. zend_unwrap_reference(&retval);
  1576. }
  1577. ZVAL_COPY_VALUE(return_value, &retval);
  1578. }
  1579. }
  1580. /* }}} */
  1581. /* {{{ proto public bool ReflectionFunction::returnsReference()
  1582. Gets whether this function returns a reference */
  1583. ZEND_METHOD(ReflectionFunctionAbstract, returnsReference)
  1584. {
  1585. reflection_object *intern;
  1586. zend_function *fptr;
  1587. GET_REFLECTION_OBJECT_PTR(fptr);
  1588. if (zend_parse_parameters_none() == FAILURE) {
  1589. RETURN_THROWS();
  1590. }
  1591. RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
  1592. }
  1593. /* }}} */
  1594. /* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
  1595. Gets the number of parameters */
  1596. ZEND_METHOD(ReflectionFunctionAbstract, getNumberOfParameters)
  1597. {
  1598. reflection_object *intern;
  1599. zend_function *fptr;
  1600. uint32_t num_args;
  1601. GET_REFLECTION_OBJECT_PTR(fptr);
  1602. if (zend_parse_parameters_none() == FAILURE) {
  1603. RETURN_THROWS();
  1604. }
  1605. num_args = fptr->common.num_args;
  1606. if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
  1607. num_args++;
  1608. }
  1609. RETURN_LONG(num_args);
  1610. }
  1611. /* }}} */
  1612. /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
  1613. Gets the number of required parameters */
  1614. ZEND_METHOD(ReflectionFunctionAbstract, getNumberOfRequiredParameters)
  1615. {
  1616. reflection_object *intern;
  1617. zend_function *fptr;
  1618. GET_REFLECTION_OBJECT_PTR(fptr);
  1619. if (zend_parse_parameters_none() == FAILURE) {
  1620. RETURN_THROWS();
  1621. }
  1622. RETURN_LONG(fptr->common.required_num_args);
  1623. }
  1624. /* }}} */
  1625. /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
  1626. Returns an array of parameter objects for this function */
  1627. ZEND_METHOD(ReflectionFunctionAbstract, getParameters)
  1628. {
  1629. reflection_object *intern;
  1630. zend_function *fptr;
  1631. uint32_t i, num_args;
  1632. struct _zend_arg_info *arg_info;
  1633. GET_REFLECTION_OBJECT_PTR(fptr);
  1634. if (zend_parse_parameters_none() == FAILURE) {
  1635. RETURN_THROWS();
  1636. }
  1637. arg_info= fptr->common.arg_info;
  1638. num_args = fptr->common.num_args;
  1639. if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
  1640. num_args++;
  1641. }
  1642. if (!num_args) {
  1643. RETURN_EMPTY_ARRAY();
  1644. }
  1645. array_init(return_value);
  1646. for (i = 0; i < num_args; i++) {
  1647. zval parameter;
  1648. reflection_parameter_factory(
  1649. _copy_function(fptr),
  1650. Z_ISUNDEF(intern->obj) ? NULL : &intern->obj,
  1651. arg_info,
  1652. i,
  1653. i < fptr->common.required_num_args,
  1654. &parameter
  1655. );
  1656. add_next_index_zval(return_value, &parameter);
  1657. arg_info++;
  1658. }
  1659. }
  1660. /* }}} */
  1661. /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension()
  1662. Returns NULL or the extension the function belongs to */
  1663. ZEND_METHOD(ReflectionFunctionAbstract, getExtension)
  1664. {
  1665. reflection_object *intern;
  1666. zend_function *fptr;
  1667. zend_internal_function *internal;
  1668. GET_REFLECTION_OBJECT_PTR(fptr);
  1669. if (zend_parse_parameters_none() == FAILURE) {
  1670. RETURN_THROWS();
  1671. }
  1672. if (fptr->type != ZEND_INTERNAL_FUNCTION) {
  1673. RETURN_NULL();
  1674. }
  1675. internal = (zend_internal_function *)fptr;
  1676. if (internal->module) {
  1677. reflection_extension_factory(return_value, internal->module->name);
  1678. } else {
  1679. RETURN_NULL();
  1680. }
  1681. }
  1682. /* }}} */
  1683. /* {{{ proto public string|false ReflectionFunction::getExtensionName()
  1684. Returns false or the name of the extension the function belongs to */
  1685. ZEND_METHOD(ReflectionFunctionAbstract, getExtensionName)
  1686. {
  1687. reflection_object *intern;
  1688. zend_function *fptr;
  1689. zend_internal_function *internal;
  1690. GET_REFLECTION_OBJECT_PTR(fptr);
  1691. if (zend_parse_parameters_none() == FAILURE) {
  1692. RETURN_THROWS();
  1693. }
  1694. if (fptr->type != ZEND_INTERNAL_FUNCTION) {
  1695. RETURN_FALSE;
  1696. }
  1697. internal = (zend_internal_function *)fptr;
  1698. if (internal->module) {
  1699. RETURN_STRING(internal->module->name);
  1700. } else {
  1701. RETURN_FALSE;
  1702. }
  1703. }
  1704. /* }}} */
  1705. /* {{{ proto public void ReflectionGenerator::__construct(object Generator) */
  1706. ZEND_METHOD(ReflectionGenerator, __construct)
  1707. {
  1708. zval *generator, *object;
  1709. reflection_object *intern;
  1710. zend_execute_data *ex;
  1711. object = ZEND_THIS;
  1712. intern = Z_REFLECTION_P(object);
  1713. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &generator, zend_ce_generator) == FAILURE) {
  1714. RETURN_THROWS();
  1715. }
  1716. ex = ((zend_generator *) Z_OBJ_P(generator))->execute_data;
  1717. if (!ex) {
  1718. _DO_THROW("Cannot create ReflectionGenerator based on a terminated Generator");
  1719. RETURN_THROWS();
  1720. }
  1721. intern->ref_type = REF_TYPE_GENERATOR;
  1722. Z_ADDREF_P(generator);
  1723. ZVAL_OBJ(&intern->obj, Z_OBJ_P(generator));
  1724. intern->ce = zend_ce_generator;
  1725. }
  1726. /* }}} */
  1727. #define REFLECTION_CHECK_VALID_GENERATOR(ex) \
  1728. if (!ex) { \
  1729. _DO_THROW("Cannot fetch information from a terminated Generator"); \
  1730. RETURN_THROWS(); \
  1731. }
  1732. /* {{{ proto public array ReflectionGenerator::getTrace($options = DEBUG_BACKTRACE_PROVIDE_OBJECT) */
  1733. ZEND_METHOD(ReflectionGenerator, getTrace)
  1734. {
  1735. zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
  1736. zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
  1737. zend_generator *root_generator;
  1738. zend_execute_data *ex_backup = EG(current_execute_data);
  1739. zend_execute_data *ex = generator->execute_data;
  1740. zend_execute_data *root_prev = NULL, *cur_prev;
  1741. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &options) == FAILURE) {
  1742. RETURN_THROWS();
  1743. }
  1744. REFLECTION_CHECK_VALID_GENERATOR(ex)
  1745. root_generator = zend_generator_get_current(generator);
  1746. cur_prev = generator->execute_data->prev_execute_data;
  1747. if (generator == root_generator) {
  1748. generator->execute_data->prev_execute_data = NULL;
  1749. } else {
  1750. root_prev = root_generator->execute_data->prev_execute_data;
  1751. generator->execute_fake.prev_execute_data = NULL;
  1752. root_generator->execute_data->prev_execute_data = &generator->execute_fake;
  1753. }
  1754. EG(current_execute_data) = root_generator->execute_data;
  1755. zend_fetch_debug_backtrace(return_value, 0, options, 0);
  1756. EG(current_execute_data) = ex_backup;
  1757. root_generator->execute_data->prev_execute_data = root_prev;
  1758. generator->execute_data->prev_execute_data = cur_prev;
  1759. }
  1760. /* }}} */
  1761. /* {{{ proto public int ReflectionGenerator::getExecutingLine() */
  1762. ZEND_METHOD(ReflectionGenerator, getExecutingLine)
  1763. {
  1764. zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
  1765. zend_execute_data *ex = generator->execute_data;
  1766. if (zend_parse_parameters_none() == FAILURE) {
  1767. RETURN_THROWS();
  1768. }
  1769. REFLECTION_CHECK_VALID_GENERATOR(ex)
  1770. ZVAL_LONG(return_value, ex->opline->lineno);
  1771. }
  1772. /* }}} */
  1773. /* {{{ proto public string ReflectionGenerator::getExecutingFile() */
  1774. ZEND_METHOD(ReflectionGenerator, getExecutingFile)
  1775. {
  1776. zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
  1777. zend_execute_data *ex = generator->execute_data;
  1778. if (zend_parse_parameters_none() == FAILURE) {
  1779. RETURN_THROWS();
  1780. }
  1781. REFLECTION_CHECK_VALID_GENERATOR(ex)
  1782. ZVAL_STR_COPY(return_value, ex->func->op_array.filename);
  1783. }
  1784. /* }}} */
  1785. /* {{{ proto public ReflectionFunctionAbstract ReflectionGenerator::getFunction() */
  1786. ZEND_METHOD(ReflectionGenerator, getFunction)
  1787. {
  1788. zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
  1789. zend_execute_data *ex = generator->execute_data;
  1790. if (zend_parse_parameters_none() == FAILURE) {
  1791. RETURN_THROWS();
  1792. }
  1793. REFLECTION_CHECK_VALID_GENERATOR(ex)
  1794. if (ex->func->common.fn_flags & ZEND_ACC_CLOSURE) {
  1795. zval closure;
  1796. ZVAL_OBJ(&closure, ZEND_CLOSURE_OBJECT(ex->func));
  1797. reflection_function_factory(ex->func, &closure, return_value);
  1798. } else if (ex->func->op_array.scope) {
  1799. reflection_method_factory(ex->func->op_array.scope, ex->func, NULL, return_value);
  1800. } else {
  1801. reflection_function_factory(ex->func, NULL, return_value);
  1802. }
  1803. }
  1804. /* }}} */
  1805. /* {{{ proto public object ReflectionGenerator::getThis() */
  1806. ZEND_METHOD(ReflectionGenerator, getThis)
  1807. {
  1808. zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
  1809. zend_execute_data *ex = generator->execute_data;
  1810. if (zend_parse_parameters_none() == FAILURE) {
  1811. RETURN_THROWS();
  1812. }
  1813. REFLECTION_CHECK_VALID_GENERATOR(ex)
  1814. if (Z_TYPE(ex->This) == IS_OBJECT) {
  1815. Z_ADDREF(ex->This);
  1816. ZVAL_OBJ(return_value, Z_OBJ(ex->This));
  1817. } else {
  1818. ZVAL_NULL(return_value);
  1819. }
  1820. }
  1821. /* }}} */
  1822. /* {{{ proto public Generator ReflectionGenerator::getExecutingGenerator() */
  1823. ZEND_METHOD(ReflectionGenerator, getExecutingGenerator)
  1824. {
  1825. zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
  1826. zend_execute_data *ex = generator->execute_data;
  1827. zend_generator *current;
  1828. if (zend_parse_parameters_none() == FAILURE) {
  1829. RETURN_THROWS();
  1830. }
  1831. REFLECTION_CHECK_VALID_GENERATOR(ex)
  1832. current = zend_generator_get_current(generator);
  1833. GC_ADDREF(&current->std);
  1834. ZVAL_OBJ(return_value, (zend_object *) current);
  1835. }
  1836. /* }}} */
  1837. /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter)
  1838. Constructor. Throws an Exception in case the given method does not exist */
  1839. ZEND_METHOD(ReflectionParameter, __construct)
  1840. {
  1841. parameter_reference *ref;
  1842. zval *reference;
  1843. zend_string *arg_name = NULL;
  1844. zend_long position;
  1845. zval *object;
  1846. zval *prop_name;
  1847. reflection_object *intern;
  1848. zend_function *fptr;
  1849. struct _zend_arg_info *arg_info;
  1850. uint32_t num_args;
  1851. zend_class_entry *ce = NULL;
  1852. zend_bool is_closure = 0;
  1853. ZEND_PARSE_PARAMETERS_START(2, 2)
  1854. Z_PARAM_ZVAL(reference)
  1855. Z_PARAM_STR_OR_LONG(arg_name, position)
  1856. ZEND_PARSE_PARAMETERS_END();
  1857. object = ZEND_THIS;
  1858. intern = Z_REFLECTION_P(object);
  1859. /* First, find the function */
  1860. switch (Z_TYPE_P(reference)) {
  1861. case IS_STRING:
  1862. {
  1863. zend_string *lcname = zend_string_tolower(Z_STR_P(reference));
  1864. fptr = zend_hash_find_ptr(EG(function_table), lcname);
  1865. zend_string_release(lcname);
  1866. if (!fptr) {
  1867. zend_throw_exception_ex(reflection_exception_ptr, 0,
  1868. "Function %s() does not exist", Z_STRVAL_P(reference));
  1869. RETURN_THROWS();
  1870. }
  1871. ce = fptr->common.scope;
  1872. }
  1873. break;
  1874. case IS_ARRAY: {
  1875. zval *classref;
  1876. zval *method;
  1877. zend_string *name, *lcname;
  1878. if (((classref = zend_hash_index_find(Z_ARRVAL_P(reference), 0)) == NULL)
  1879. || ((method = zend_hash_index_find(Z_ARRVAL_P(reference), 1)) == NULL))
  1880. {
  1881. _DO_THROW("Expected array($object, $method) or array($classname, $method)");
  1882. RETURN_THROWS();
  1883. }
  1884. if (Z_TYPE_P(classref) == IS_OBJECT) {
  1885. ce = Z_OBJCE_P(classref);
  1886. } else {
  1887. name = zval_try_get_string(classref);
  1888. if (UNEXPECTED(!name)) {
  1889. return;
  1890. }
  1891. if ((ce = zend_lookup_class(name)) == NULL) {
  1892. zend_throw_exception_ex(reflection_exception_ptr, 0,
  1893. "Class %s does not exist", ZSTR_VAL(name));
  1894. zend_string_release(name);
  1895. RETURN_THROWS();
  1896. }
  1897. zend_string_release(name);
  1898. }
  1899. name = zval_try_get_string(method);
  1900. if (UNEXPECTED(!name)) {
  1901. return;
  1902. }
  1903. lcname = zend_string_tolower(name);
  1904. if (Z_TYPE_P(classref) == IS_OBJECT && is_closure_invoke(ce, lcname)
  1905. && (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref))) != NULL)
  1906. {
  1907. /* nothing to do. don't set is_closure since is the invoke handler,
  1908. not the closure itself */
  1909. } else if ((fptr = zend_hash_find_ptr(&ce->function_table, lcname)) == NULL) {
  1910. zend_string_release(name);
  1911. zend_string_release(lcname);
  1912. zend_throw_exception_ex(reflection_exception_ptr, 0,
  1913. "Method %s::%s() does not exist", ZSTR_VAL(ce->name), Z_STRVAL_P(method));
  1914. RETURN_THROWS();
  1915. }
  1916. zend_string_release(name);
  1917. zend_string_release(lcname);
  1918. }
  1919. break;
  1920. case IS_OBJECT: {
  1921. ce = Z_OBJCE_P(reference);
  1922. if (instanceof_function(ce, zend_ce_closure)) {
  1923. fptr = (zend_function *)zend_get_closure_method_def(reference);
  1924. Z_ADDREF_P(reference);
  1925. is_closure = 1;
  1926. } else if ((fptr = zend_hash_find_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) == NULL) {
  1927. zend_throw_exception_ex(reflection_exception_ptr, 0,
  1928. "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZEND_INVOKE_FUNC_NAME);
  1929. RETURN_THROWS();
  1930. }
  1931. }
  1932. break;
  1933. default:
  1934. zend_argument_error(reflection_exception_ptr, 1, "must be either a string, an array(class, method) or a callable object, %s given", zend_zval_type_name(reference));
  1935. RETURN_THROWS();
  1936. }
  1937. /* Now, search for the parameter */
  1938. arg_info = fptr->common.arg_info;
  1939. num_args = fptr->common.num_args;
  1940. if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
  1941. num_args++;
  1942. }
  1943. if (arg_name != NULL) {
  1944. uint32_t i;
  1945. position = -1;
  1946. if (has_internal_arg_info(fptr)) {
  1947. for (i = 0; i < num_args; i++) {
  1948. if (arg_info[i].name) {
  1949. if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, ZSTR_VAL(arg_name)) == 0) {
  1950. position = i;
  1951. break;
  1952. }
  1953. }
  1954. }
  1955. } else {
  1956. for (i = 0; i < num_args; i++) {
  1957. if (arg_info[i].name) {
  1958. if (zend_string_equals(arg_name, arg_info[i].name)) {
  1959. position = i;
  1960. break;
  1961. }
  1962. }
  1963. }
  1964. }
  1965. if (position == -1) {
  1966. _DO_THROW("The parameter specified by its name could not be found");
  1967. goto failure;
  1968. }
  1969. } else {
  1970. if (position < 0) {
  1971. zend_argument_value_error(2, "must be greater than or equal to 0");
  1972. goto failure;
  1973. }
  1974. if (position >= num_args) {
  1975. _DO_THROW("The parameter specified by its offset could not be found");
  1976. goto failure;
  1977. }
  1978. }
  1979. ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
  1980. ref->arg_info = &arg_info[position];
  1981. ref->offset = (uint32_t)position;
  1982. ref->required = (uint32_t)position < fptr->common.required_num_args;
  1983. ref->fptr = fptr;
  1984. /* TODO: copy fptr */
  1985. intern->ptr = ref;
  1986. intern->ref_type = REF_TYPE_PARAMETER;
  1987. intern->ce = ce;
  1988. if (reference && is_closure) {
  1989. ZVAL_COPY_VALUE(&intern->obj, reference);
  1990. }
  1991. prop_name = reflection_prop_name(object);
  1992. if (has_internal_arg_info(fptr)) {
  1993. ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)[position].name);
  1994. } else {
  1995. ZVAL_STR_COPY(prop_name, arg_info[position].name);
  1996. }
  1997. return;
  1998. failure:
  1999. if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
  2000. zend_string_release_ex(fptr->common.function_name, 0);
  2001. zend_free_trampoline(fptr);
  2002. }
  2003. if (is_closure) {
  2004. zval_ptr_dtor(reference);
  2005. }
  2006. RETURN_THROWS();
  2007. }
  2008. /* }}} */
  2009. /* {{{ proto public string ReflectionParameter::__toString()
  2010. Returns a string representation */
  2011. ZEND_METHOD(ReflectionParameter, __toString)
  2012. {
  2013. reflection_object *intern;
  2014. parameter_reference *param;
  2015. smart_str str = {0};
  2016. if (zend_parse_parameters_none() == FAILURE) {
  2017. RETURN_THROWS();
  2018. }
  2019. GET_REFLECTION_OBJECT_PTR(param);
  2020. _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "");
  2021. RETURN_STR(smart_str_extract(&str));
  2022. }
  2023. /* }}} */
  2024. /* {{{ proto public string ReflectionParameter::getName()
  2025. Returns this parameters's name */
  2026. ZEND_METHOD(ReflectionParameter, getName)
  2027. {
  2028. reflection_object *intern;
  2029. parameter_reference *param;
  2030. if (zend_parse_parameters_none() == FAILURE) {
  2031. RETURN_THROWS();
  2032. }
  2033. GET_REFLECTION_OBJECT_PTR(param);
  2034. if (has_internal_arg_info(param->fptr)) {
  2035. RETURN_STRING(((zend_internal_arg_info *) param->arg_info)->name);
  2036. } else {
  2037. RETURN_STR_COPY(param->arg_info->name);
  2038. }
  2039. }
  2040. /* }}} */
  2041. /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction()
  2042. Returns the ReflectionFunction for the function of this parameter */
  2043. ZEND_METHOD(ReflectionParameter, getDeclaringFunction)
  2044. {
  2045. reflection_object *intern;
  2046. parameter_reference *param;
  2047. if (zend_parse_parameters_none() == FAILURE) {
  2048. RETURN_THROWS();
  2049. }
  2050. GET_REFLECTION_OBJECT_PTR(param);
  2051. if (!param->fptr->common.scope) {
  2052. reflection_function_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
  2053. } else {
  2054. reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
  2055. }
  2056. }
  2057. /* }}} */
  2058. /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
  2059. Returns in which class this parameter is defined (not the type of the parameter) */
  2060. ZEND_METHOD(ReflectionParameter, getDeclaringClass)
  2061. {
  2062. reflection_object *intern;
  2063. parameter_reference *param;
  2064. if (zend_parse_parameters_none() == FAILURE) {
  2065. RETURN_THROWS();
  2066. }
  2067. GET_REFLECTION_OBJECT_PTR(param);
  2068. if (param->fptr->common.scope) {
  2069. zend_reflection_class_factory(param->fptr->common.scope, return_value);
  2070. }
  2071. }
  2072. /* }}} */
  2073. /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass()
  2074. Returns this parameters's class hint or NULL if there is none */
  2075. ZEND_METHOD(ReflectionParameter, getClass)
  2076. {
  2077. reflection_object *intern;
  2078. parameter_reference *param;
  2079. zend_class_entry *ce;
  2080. if (zend_parse_parameters_none() == FAILURE) {
  2081. RETURN_THROWS();
  2082. }
  2083. GET_REFLECTION_OBJECT_PTR(param);
  2084. // TODO: This is going to return null for union types, which is rather odd.
  2085. if (ZEND_TYPE_HAS_NAME(param->arg_info->type)) {
  2086. /* Class name is stored as a string, we might also get "self" or "parent"
  2087. * - For "self", simply use the function scope. If scope is NULL then
  2088. * the function is global and thus self does not make any sense
  2089. *
  2090. * - For "parent", use the function scope's parent. If scope is NULL then
  2091. * the function is global and thus parent does not make any sense.
  2092. * If the parent is NULL then the class does not extend anything and
  2093. * thus parent does not make any sense, either.
  2094. *
  2095. * TODO: Think about moving these checks to the compiler or some sort of
  2096. * lint-mode.
  2097. */
  2098. zend_string *class_name;
  2099. class_name = ZEND_TYPE_NAME(param->arg_info->type);
  2100. if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "self", sizeof("self")- 1)) {
  2101. ce = param->fptr->common.scope;
  2102. if (!ce) {
  2103. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2104. "Parameter uses 'self' as type hint but function is not a class member!");
  2105. RETURN_THROWS();
  2106. }
  2107. } else if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "parent", sizeof("parent")- 1)) {
  2108. ce = param->fptr->common.scope;
  2109. if (!ce) {
  2110. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2111. "Parameter uses 'parent' as type hint but function is not a class member!");
  2112. RETURN_THROWS();
  2113. }
  2114. if (!ce->parent) {
  2115. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2116. "Parameter uses 'parent' as type hint although class does not have a parent!");
  2117. RETURN_THROWS();
  2118. }
  2119. ce = ce->parent;
  2120. } else {
  2121. ce = zend_lookup_class(class_name);
  2122. if (!ce) {
  2123. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2124. "Class %s does not exist", ZSTR_VAL(class_name));
  2125. RETURN_THROWS();
  2126. }
  2127. }
  2128. zend_reflection_class_factory(ce, return_value);
  2129. }
  2130. }
  2131. /* }}} */
  2132. /* {{{ proto public bool ReflectionParameter::hasType()
  2133. Returns whether parameter has a type */
  2134. ZEND_METHOD(ReflectionParameter, hasType)
  2135. {
  2136. reflection_object *intern;
  2137. parameter_reference *param;
  2138. if (zend_parse_parameters_none() == FAILURE) {
  2139. RETURN_THROWS();
  2140. }
  2141. GET_REFLECTION_OBJECT_PTR(param);
  2142. RETVAL_BOOL(ZEND_TYPE_IS_SET(param->arg_info->type));
  2143. }
  2144. /* }}} */
  2145. /* {{{ proto public ReflectionType ReflectionParameter::getType()
  2146. Returns the type associated with the parameter */
  2147. ZEND_METHOD(ReflectionParameter, getType)
  2148. {
  2149. reflection_object *intern;
  2150. parameter_reference *param;
  2151. if (zend_parse_parameters_none() == FAILURE) {
  2152. RETURN_THROWS();
  2153. }
  2154. GET_REFLECTION_OBJECT_PTR(param);
  2155. if (!ZEND_TYPE_IS_SET(param->arg_info->type)) {
  2156. RETURN_NULL();
  2157. }
  2158. reflection_type_factory(param->arg_info->type, return_value, 1);
  2159. }
  2160. /* }}} */
  2161. /* {{{ proto public bool ReflectionParameter::isArray()
  2162. Returns whether parameter MUST be an array */
  2163. ZEND_METHOD(ReflectionParameter, isArray)
  2164. {
  2165. reflection_object *intern;
  2166. parameter_reference *param;
  2167. uint32_t type_mask;
  2168. if (zend_parse_parameters_none() == FAILURE) {
  2169. RETURN_THROWS();
  2170. }
  2171. GET_REFLECTION_OBJECT_PTR(param);
  2172. type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(param->arg_info->type);
  2173. RETVAL_BOOL(type_mask == MAY_BE_ARRAY);
  2174. }
  2175. /* }}} */
  2176. /* {{{ proto public bool ReflectionParameter::isCallable()
  2177. Returns whether parameter MUST be callable */
  2178. ZEND_METHOD(ReflectionParameter, isCallable)
  2179. {
  2180. reflection_object *intern;
  2181. parameter_reference *param;
  2182. uint32_t type_mask;
  2183. if (zend_parse_parameters_none() == FAILURE) {
  2184. RETURN_THROWS();
  2185. }
  2186. GET_REFLECTION_OBJECT_PTR(param);
  2187. type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(param->arg_info->type);
  2188. RETVAL_BOOL(type_mask == MAY_BE_CALLABLE);
  2189. }
  2190. /* }}} */
  2191. /* {{{ proto public bool ReflectionParameter::allowsNull()
  2192. Returns whether NULL is allowed as this parameters's value */
  2193. ZEND_METHOD(ReflectionParameter, allowsNull)
  2194. {
  2195. reflection_object *intern;
  2196. parameter_reference *param;
  2197. if (zend_parse_parameters_none() == FAILURE) {
  2198. RETURN_THROWS();
  2199. }
  2200. GET_REFLECTION_OBJECT_PTR(param);
  2201. RETVAL_BOOL(!ZEND_TYPE_IS_SET(param->arg_info->type)
  2202. || ZEND_TYPE_ALLOW_NULL(param->arg_info->type));
  2203. }
  2204. /* }}} */
  2205. /* {{{ proto public bool ReflectionParameter::isPassedByReference()
  2206. Returns whether this parameters is passed to by reference */
  2207. ZEND_METHOD(ReflectionParameter, isPassedByReference)
  2208. {
  2209. reflection_object *intern;
  2210. parameter_reference *param;
  2211. if (zend_parse_parameters_none() == FAILURE) {
  2212. RETURN_THROWS();
  2213. }
  2214. GET_REFLECTION_OBJECT_PTR(param);
  2215. RETVAL_BOOL(ZEND_ARG_SEND_MODE(param->arg_info));
  2216. }
  2217. /* }}} */
  2218. /* {{{ proto public bool ReflectionParameter::canBePassedByValue()
  2219. Returns whether this parameter can be passed by value */
  2220. ZEND_METHOD(ReflectionParameter, canBePassedByValue)
  2221. {
  2222. reflection_object *intern;
  2223. parameter_reference *param;
  2224. if (zend_parse_parameters_none() == FAILURE) {
  2225. RETURN_THROWS();
  2226. }
  2227. GET_REFLECTION_OBJECT_PTR(param);
  2228. /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
  2229. RETVAL_BOOL(ZEND_ARG_SEND_MODE(param->arg_info) != ZEND_SEND_BY_REF);
  2230. }
  2231. /* }}} */
  2232. /* {{{ proto public bool ReflectionParameter::getPosition()
  2233. Returns whether this parameter is an optional parameter */
  2234. ZEND_METHOD(ReflectionParameter, getPosition)
  2235. {
  2236. reflection_object *intern;
  2237. parameter_reference *param;
  2238. if (zend_parse_parameters_none() == FAILURE) {
  2239. RETURN_THROWS();
  2240. }
  2241. GET_REFLECTION_OBJECT_PTR(param);
  2242. RETVAL_LONG(param->offset);
  2243. }
  2244. /* }}} */
  2245. /* {{{ proto public bool ReflectionParameter::isOptional()
  2246. Returns whether this parameter is an optional parameter */
  2247. ZEND_METHOD(ReflectionParameter, isOptional)
  2248. {
  2249. reflection_object *intern;
  2250. parameter_reference *param;
  2251. if (zend_parse_parameters_none() == FAILURE) {
  2252. RETURN_THROWS();
  2253. }
  2254. GET_REFLECTION_OBJECT_PTR(param);
  2255. RETVAL_BOOL(!param->required);
  2256. }
  2257. /* }}} */
  2258. /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
  2259. Returns whether the default value of this parameter is available */
  2260. ZEND_METHOD(ReflectionParameter, isDefaultValueAvailable)
  2261. {
  2262. reflection_object *intern;
  2263. parameter_reference *param;
  2264. if (zend_parse_parameters_none() == FAILURE) {
  2265. RETURN_THROWS();
  2266. }
  2267. GET_REFLECTION_OBJECT_PTR(param);
  2268. if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
  2269. RETURN_BOOL(((zend_internal_arg_info*) (param->arg_info))->default_value);
  2270. } else {
  2271. zval *default_value = get_default_from_recv((zend_op_array *)param->fptr, param->offset);
  2272. RETURN_BOOL(default_value != NULL);
  2273. }
  2274. }
  2275. /* }}} */
  2276. /* {{{ proto public bool ReflectionParameter::getDefaultValue()
  2277. Returns the default value of this parameter or throws an exception */
  2278. ZEND_METHOD(ReflectionParameter, getDefaultValue)
  2279. {
  2280. reflection_object *intern;
  2281. parameter_reference *param;
  2282. if (zend_parse_parameters_none() == FAILURE) {
  2283. RETURN_THROWS();
  2284. }
  2285. GET_REFLECTION_OBJECT_PTR(param);
  2286. if (get_parameter_default(return_value, param) == FAILURE) {
  2287. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2288. "Internal error: Failed to retrieve the default value");
  2289. RETURN_THROWS();
  2290. }
  2291. if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
  2292. zval_update_constant_ex(return_value, param->fptr->common.scope);
  2293. }
  2294. }
  2295. /* }}} */
  2296. /* {{{ proto public bool ReflectionParameter::isDefaultValueConstant()
  2297. Returns whether the default value of this parameter is constant */
  2298. ZEND_METHOD(ReflectionParameter, isDefaultValueConstant)
  2299. {
  2300. reflection_object *intern;
  2301. parameter_reference *param;
  2302. if (zend_parse_parameters_none() == FAILURE) {
  2303. RETURN_THROWS();
  2304. }
  2305. GET_REFLECTION_OBJECT_PTR(param);
  2306. zval default_value;
  2307. if (get_parameter_default(&default_value, param) == FAILURE) {
  2308. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2309. "Internal error: Failed to retrieve the default value");
  2310. RETURN_THROWS();
  2311. }
  2312. if (Z_TYPE(default_value) == IS_CONSTANT_AST) {
  2313. zend_ast *ast = Z_ASTVAL(default_value);
  2314. RETVAL_BOOL(ast->kind == ZEND_AST_CONSTANT || ast->kind == ZEND_AST_CONSTANT_CLASS);
  2315. zval_ptr_dtor_nogc(&default_value);
  2316. } else {
  2317. RETURN_FALSE;
  2318. }
  2319. }
  2320. /* }}} */
  2321. /* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName()
  2322. Returns the default value's constant name if default value is constant or null */
  2323. ZEND_METHOD(ReflectionParameter, getDefaultValueConstantName)
  2324. {
  2325. reflection_object *intern;
  2326. parameter_reference *param;
  2327. if (zend_parse_parameters_none() == FAILURE) {
  2328. RETURN_THROWS();
  2329. }
  2330. GET_REFLECTION_OBJECT_PTR(param);
  2331. zval default_value;
  2332. if (get_parameter_default(&default_value, param) == FAILURE) {
  2333. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2334. "Internal error: Failed to retrieve the default value");
  2335. RETURN_THROWS();
  2336. }
  2337. if (Z_TYPE(default_value) != IS_CONSTANT_AST) {
  2338. zval_ptr_dtor_nogc(&default_value);
  2339. RETURN_NULL();
  2340. }
  2341. zend_ast *ast = Z_ASTVAL(default_value);
  2342. if (ast->kind == ZEND_AST_CONSTANT) {
  2343. RETVAL_STR_COPY(zend_ast_get_constant_name(ast));
  2344. } else if (ast->kind == ZEND_AST_CONSTANT_CLASS) {
  2345. RETVAL_STRINGL("__CLASS__", sizeof("__CLASS__")-1);
  2346. } else {
  2347. RETVAL_NULL();
  2348. }
  2349. zval_ptr_dtor_nogc(&default_value);
  2350. }
  2351. /* {{{ proto public bool ReflectionParameter::isVariadic()
  2352. Returns whether this parameter is a variadic parameter */
  2353. ZEND_METHOD(ReflectionParameter, isVariadic)
  2354. {
  2355. reflection_object *intern;
  2356. parameter_reference *param;
  2357. if (zend_parse_parameters_none() == FAILURE) {
  2358. RETURN_THROWS();
  2359. }
  2360. GET_REFLECTION_OBJECT_PTR(param);
  2361. RETVAL_BOOL(ZEND_ARG_IS_VARIADIC(param->arg_info));
  2362. }
  2363. /* }}} */
  2364. /* {{{ proto public bool ReflectionType::allowsNull()
  2365. Returns whether parameter MAY be null */
  2366. ZEND_METHOD(ReflectionType, allowsNull)
  2367. {
  2368. reflection_object *intern;
  2369. type_reference *param;
  2370. if (zend_parse_parameters_none() == FAILURE) {
  2371. RETURN_THROWS();
  2372. }
  2373. GET_REFLECTION_OBJECT_PTR(param);
  2374. RETVAL_BOOL(ZEND_TYPE_ALLOW_NULL(param->type));
  2375. }
  2376. /* }}} */
  2377. static zend_string *zend_type_to_string_without_null(zend_type type) {
  2378. ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_NULL;
  2379. return zend_type_to_string(type);
  2380. }
  2381. /* {{{ proto public string ReflectionType::__toString()
  2382. Return the text of the type hint */
  2383. ZEND_METHOD(ReflectionType, __toString)
  2384. {
  2385. reflection_object *intern;
  2386. type_reference *param;
  2387. if (zend_parse_parameters_none() == FAILURE) {
  2388. RETURN_THROWS();
  2389. }
  2390. GET_REFLECTION_OBJECT_PTR(param);
  2391. RETURN_STR(zend_type_to_string(param->type));
  2392. }
  2393. /* }}} */
  2394. /* {{{ proto public string ReflectionNamedType::getName()
  2395. Return the name of the type */
  2396. ZEND_METHOD(ReflectionNamedType, getName)
  2397. {
  2398. reflection_object *intern;
  2399. type_reference *param;
  2400. if (zend_parse_parameters_none() == FAILURE) {
  2401. RETURN_THROWS();
  2402. }
  2403. GET_REFLECTION_OBJECT_PTR(param);
  2404. if (param->legacy_behavior) {
  2405. RETURN_STR(zend_type_to_string_without_null(param->type));
  2406. }
  2407. RETURN_STR(zend_type_to_string(param->type));
  2408. }
  2409. /* }}} */
  2410. /* {{{ proto public bool ReflectionNamedType::isBuiltin()
  2411. Returns whether type is a builtin type */
  2412. ZEND_METHOD(ReflectionNamedType, isBuiltin)
  2413. {
  2414. reflection_object *intern;
  2415. type_reference *param;
  2416. if (zend_parse_parameters_none() == FAILURE) {
  2417. RETURN_THROWS();
  2418. }
  2419. GET_REFLECTION_OBJECT_PTR(param);
  2420. /* Treat "static" as a class type for the purposes of reflection. */
  2421. RETVAL_BOOL(ZEND_TYPE_IS_ONLY_MASK(param->type)
  2422. && !(ZEND_TYPE_FULL_MASK(param->type) & MAY_BE_STATIC));
  2423. }
  2424. /* }}} */
  2425. static void append_type(zval *return_value, zend_type type) {
  2426. zval reflection_type;
  2427. reflection_type_factory(type, &reflection_type, 0);
  2428. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &reflection_type);
  2429. }
  2430. static void append_type_mask(zval *return_value, uint32_t type_mask) {
  2431. append_type(return_value, (zend_type) ZEND_TYPE_INIT_MASK(type_mask));
  2432. }
  2433. /* {{{ proto public string ReflectionUnionType::getTypes()
  2434. Returns the types that are part of this union type */
  2435. ZEND_METHOD(ReflectionUnionType, getTypes)
  2436. {
  2437. reflection_object *intern;
  2438. type_reference *param;
  2439. uint32_t type_mask;
  2440. if (zend_parse_parameters_none() == FAILURE) {
  2441. RETURN_THROWS();
  2442. }
  2443. GET_REFLECTION_OBJECT_PTR(param);
  2444. array_init(return_value);
  2445. if (ZEND_TYPE_HAS_LIST(param->type)) {
  2446. zend_type *list_type;
  2447. ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(param->type), list_type) {
  2448. append_type(return_value, *list_type);
  2449. } ZEND_TYPE_LIST_FOREACH_END();
  2450. } else if (ZEND_TYPE_HAS_NAME(param->type)) {
  2451. append_type(return_value,
  2452. (zend_type) ZEND_TYPE_INIT_CLASS(ZEND_TYPE_NAME(param->type), 0, 0));
  2453. } else if (ZEND_TYPE_HAS_CE(param->type)) {
  2454. append_type(return_value,
  2455. (zend_type) ZEND_TYPE_INIT_CE(ZEND_TYPE_CE(param->type), 0, 0));
  2456. }
  2457. type_mask = ZEND_TYPE_PURE_MASK(param->type);
  2458. ZEND_ASSERT(!(type_mask & MAY_BE_VOID));
  2459. if (type_mask & MAY_BE_CALLABLE) {
  2460. append_type_mask(return_value, MAY_BE_CALLABLE);
  2461. }
  2462. if (type_mask & MAY_BE_ITERABLE) {
  2463. append_type_mask(return_value, MAY_BE_ITERABLE);
  2464. }
  2465. if (type_mask & MAY_BE_OBJECT) {
  2466. append_type_mask(return_value, MAY_BE_OBJECT);
  2467. }
  2468. if (type_mask & MAY_BE_ARRAY) {
  2469. append_type_mask(return_value, MAY_BE_ARRAY);
  2470. }
  2471. if (type_mask & MAY_BE_STRING) {
  2472. append_type_mask(return_value, MAY_BE_STRING);
  2473. }
  2474. if (type_mask & MAY_BE_LONG) {
  2475. append_type_mask(return_value, MAY_BE_LONG);
  2476. }
  2477. if (type_mask & MAY_BE_DOUBLE) {
  2478. append_type_mask(return_value, MAY_BE_DOUBLE);
  2479. }
  2480. if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) {
  2481. append_type_mask(return_value, MAY_BE_BOOL);
  2482. } else if (type_mask & MAY_BE_FALSE) {
  2483. append_type_mask(return_value, MAY_BE_FALSE);
  2484. }
  2485. if (type_mask & MAY_BE_NULL) {
  2486. append_type_mask(return_value, MAY_BE_NULL);
  2487. }
  2488. }
  2489. /* }}} */
  2490. /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name])
  2491. Constructor. Throws an Exception in case the given method does not exist */
  2492. ZEND_METHOD(ReflectionMethod, __construct)
  2493. {
  2494. zval *classname;
  2495. zval *object, *orig_obj;
  2496. reflection_object *intern;
  2497. char *lcname;
  2498. zend_class_entry *ce;
  2499. zend_function *mptr;
  2500. char *name_str, *tmp;
  2501. size_t name_len, tmp_len;
  2502. zval ztmp;
  2503. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
  2504. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
  2505. RETURN_THROWS();
  2506. }
  2507. if ((tmp = strstr(name_str, "::")) == NULL) {
  2508. zend_argument_error(reflection_exception_ptr, 1, "must be a valid method name");
  2509. RETURN_THROWS();
  2510. }
  2511. classname = &ztmp;
  2512. tmp_len = tmp - name_str;
  2513. ZVAL_STRINGL(classname, name_str, tmp_len);
  2514. name_len = name_len - (tmp_len + 2);
  2515. name_str = tmp + 2;
  2516. orig_obj = NULL;
  2517. } else if (Z_TYPE_P(classname) == IS_OBJECT) {
  2518. orig_obj = classname;
  2519. } else {
  2520. orig_obj = NULL;
  2521. }
  2522. object = ZEND_THIS;
  2523. intern = Z_REFLECTION_P(object);
  2524. /* Find the class entry */
  2525. switch (Z_TYPE_P(classname)) {
  2526. case IS_STRING:
  2527. if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
  2528. if (!EG(exception)) {
  2529. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2530. "Class %s does not exist", Z_STRVAL_P(classname));
  2531. }
  2532. if (classname == &ztmp) {
  2533. zval_ptr_dtor_str(&ztmp);
  2534. }
  2535. RETURN_THROWS();
  2536. }
  2537. break;
  2538. case IS_OBJECT:
  2539. ce = Z_OBJCE_P(classname);
  2540. break;
  2541. default:
  2542. if (classname == &ztmp) {
  2543. zval_ptr_dtor_str(&ztmp);
  2544. }
  2545. zend_argument_error(reflection_exception_ptr, 1, "must be of type object|string, %s given", zend_zval_type_name(classname));
  2546. RETURN_THROWS();
  2547. }
  2548. if (classname == &ztmp) {
  2549. zval_ptr_dtor_str(&ztmp);
  2550. }
  2551. lcname = zend_str_tolower_dup(name_str, name_len);
  2552. if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
  2553. && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
  2554. && (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
  2555. {
  2556. /* do nothing, mptr already set */
  2557. } else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
  2558. efree(lcname);
  2559. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2560. "Method %s::%s() does not exist", ZSTR_VAL(ce->name), name_str);
  2561. RETURN_THROWS();
  2562. }
  2563. efree(lcname);
  2564. ZVAL_STR_COPY(reflection_prop_name(object), mptr->common.function_name);
  2565. ZVAL_STR_COPY(reflection_prop_class(object), mptr->common.scope->name);
  2566. intern->ptr = mptr;
  2567. intern->ref_type = REF_TYPE_FUNCTION;
  2568. intern->ce = ce;
  2569. }
  2570. /* }}} */
  2571. /* {{{ proto public string ReflectionMethod::__toString()
  2572. Returns a string representation */
  2573. ZEND_METHOD(ReflectionMethod, __toString)
  2574. {
  2575. reflection_object *intern;
  2576. zend_function *mptr;
  2577. smart_str str = {0};
  2578. if (zend_parse_parameters_none() == FAILURE) {
  2579. RETURN_THROWS();
  2580. }
  2581. GET_REFLECTION_OBJECT_PTR(mptr);
  2582. _function_string(&str, mptr, intern->ce, "");
  2583. RETURN_STR(smart_str_extract(&str));
  2584. }
  2585. /* }}} */
  2586. /* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
  2587. Invokes the function */
  2588. ZEND_METHOD(ReflectionMethod, getClosure)
  2589. {
  2590. reflection_object *intern;
  2591. zval *obj;
  2592. zend_function *mptr;
  2593. GET_REFLECTION_OBJECT_PTR(mptr);
  2594. if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
  2595. zend_create_fake_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL);
  2596. } else {
  2597. if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
  2598. RETURN_THROWS();
  2599. }
  2600. if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope)) {
  2601. _DO_THROW("Given object is not an instance of the class this method was declared in");
  2602. RETURN_THROWS();
  2603. }
  2604. /* This is an original closure object and __invoke is to be called. */
  2605. if (Z_OBJCE_P(obj) == zend_ce_closure &&
  2606. (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
  2607. {
  2608. Z_ADDREF_P(obj);
  2609. ZVAL_OBJ(return_value, Z_OBJ_P(obj));
  2610. } else {
  2611. zend_create_fake_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
  2612. }
  2613. }
  2614. }
  2615. /* }}} */
  2616. /* {{{ reflection_method_invoke */
  2617. static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
  2618. {
  2619. zval retval;
  2620. zval *params = NULL, *val, *object;
  2621. reflection_object *intern;
  2622. zend_function *mptr;
  2623. int i, argc = 0, result;
  2624. zend_fcall_info fci;
  2625. zend_fcall_info_cache fcc;
  2626. zend_class_entry *obj_ce;
  2627. zval *param_array;
  2628. GET_REFLECTION_OBJECT_PTR(mptr);
  2629. if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
  2630. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2631. "Trying to invoke abstract method %s::%s()",
  2632. ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
  2633. RETURN_THROWS();
  2634. }
  2635. if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
  2636. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2637. "Trying to invoke %s method %s::%s() from scope %s",
  2638. mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
  2639. ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name),
  2640. ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
  2641. RETURN_THROWS();
  2642. }
  2643. if (variadic) {
  2644. if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!*", &object, &params, &argc) == FAILURE) {
  2645. RETURN_THROWS();
  2646. }
  2647. } else {
  2648. if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, &param_array) == FAILURE) {
  2649. RETURN_THROWS();
  2650. }
  2651. argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
  2652. params = safe_emalloc(sizeof(zval), argc, 0);
  2653. argc = 0;
  2654. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
  2655. ZVAL_COPY(&params[argc], val);
  2656. argc++;
  2657. } ZEND_HASH_FOREACH_END();
  2658. }
  2659. /* In case this is a static method, we shouldn't pass an object_ptr
  2660. * (which is used as calling context aka $this). We can thus ignore the
  2661. * first parameter.
  2662. *
  2663. * Else, we verify that the given object is an instance of the class.
  2664. */
  2665. if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
  2666. object = NULL;
  2667. obj_ce = mptr->common.scope;
  2668. } else {
  2669. if (!object) {
  2670. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2671. "Trying to invoke non static method %s::%s() without an object",
  2672. ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
  2673. RETURN_THROWS();
  2674. }
  2675. obj_ce = Z_OBJCE_P(object);
  2676. if (!instanceof_function(obj_ce, mptr->common.scope)) {
  2677. if (!variadic) {
  2678. efree(params);
  2679. }
  2680. _DO_THROW("Given object is not an instance of the class this method was declared in");
  2681. RETURN_THROWS();
  2682. }
  2683. }
  2684. fci.size = sizeof(fci);
  2685. ZVAL_UNDEF(&fci.function_name);
  2686. fci.object = object ? Z_OBJ_P(object) : NULL;
  2687. fci.retval = &retval;
  2688. fci.param_count = argc;
  2689. fci.params = params;
  2690. fci.no_separation = 1;
  2691. fcc.function_handler = mptr;
  2692. fcc.called_scope = intern->ce;
  2693. fcc.object = object ? Z_OBJ_P(object) : NULL;
  2694. /*
  2695. * Copy the zend_function when calling via handler (e.g. Closure::__invoke())
  2696. */
  2697. if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
  2698. fcc.function_handler = _copy_function(mptr);
  2699. }
  2700. result = zend_call_function(&fci, &fcc);
  2701. if (!variadic) {
  2702. for (i = 0; i < argc; i++) {
  2703. zval_ptr_dtor(&params[i]);
  2704. }
  2705. efree(params);
  2706. }
  2707. if (result == FAILURE) {
  2708. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2709. "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
  2710. RETURN_THROWS();
  2711. }
  2712. if (Z_TYPE(retval) != IS_UNDEF) {
  2713. if (Z_ISREF(retval)) {
  2714. zend_unwrap_reference(&retval);
  2715. }
  2716. ZVAL_COPY_VALUE(return_value, &retval);
  2717. }
  2718. }
  2719. /* }}} */
  2720. /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, [mixed* args])
  2721. Invokes the method. */
  2722. ZEND_METHOD(ReflectionMethod, invoke)
  2723. {
  2724. reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2725. }
  2726. /* }}} */
  2727. /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
  2728. Invokes the function and pass its arguments as array. */
  2729. ZEND_METHOD(ReflectionMethod, invokeArgs)
  2730. {
  2731. reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2732. }
  2733. /* }}} */
  2734. /* {{{ proto public bool ReflectionMethod::isFinal()
  2735. Returns whether this method is final */
  2736. ZEND_METHOD(ReflectionMethod, isFinal)
  2737. {
  2738. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
  2739. }
  2740. /* }}} */
  2741. /* {{{ proto public bool ReflectionMethod::isAbstract()
  2742. Returns whether this method is abstract */
  2743. ZEND_METHOD(ReflectionMethod, isAbstract)
  2744. {
  2745. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
  2746. }
  2747. /* }}} */
  2748. /* {{{ proto public bool ReflectionMethod::isPublic()
  2749. Returns whether this method is public */
  2750. ZEND_METHOD(ReflectionMethod, isPublic)
  2751. {
  2752. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
  2753. }
  2754. /* }}} */
  2755. /* {{{ proto public bool ReflectionMethod::isPrivate()
  2756. Returns whether this method is private */
  2757. ZEND_METHOD(ReflectionMethod, isPrivate)
  2758. {
  2759. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
  2760. }
  2761. /* }}} */
  2762. /* {{{ proto public bool ReflectionMethod::isProtected()
  2763. Returns whether this method is protected */
  2764. ZEND_METHOD(ReflectionMethod, isProtected)
  2765. {
  2766. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
  2767. }
  2768. /* }}} */
  2769. /* {{{ proto public bool ReflectionMethod::isStatic()
  2770. Returns whether this method is static */
  2771. ZEND_METHOD(ReflectionMethod, isStatic)
  2772. {
  2773. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
  2774. }
  2775. /* }}} */
  2776. /* {{{ proto public bool ReflectionFunction::isDeprecated()
  2777. Returns whether this function is deprecated */
  2778. ZEND_METHOD(ReflectionFunctionAbstract, isDeprecated)
  2779. {
  2780. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
  2781. }
  2782. /* }}} */
  2783. /* {{{ proto public bool ReflectionFunction::isGenerator()
  2784. Returns whether this function is a generator */
  2785. ZEND_METHOD(ReflectionFunctionAbstract, isGenerator)
  2786. {
  2787. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_GENERATOR);
  2788. }
  2789. /* }}} */
  2790. /* {{{ proto public bool ReflectionFunction::isVariadic()
  2791. Returns whether this function is variadic */
  2792. ZEND_METHOD(ReflectionFunctionAbstract, isVariadic)
  2793. {
  2794. _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_VARIADIC);
  2795. }
  2796. /* }}} */
  2797. /* {{{ proto public bool ReflectionFunction::inNamespace()
  2798. Returns whether this function is defined in namespace */
  2799. ZEND_METHOD(ReflectionFunctionAbstract, inNamespace)
  2800. {
  2801. reflection_object *intern;
  2802. zend_function *fptr;
  2803. if (zend_parse_parameters_none() == FAILURE) {
  2804. RETURN_THROWS();
  2805. }
  2806. GET_REFLECTION_OBJECT_PTR(fptr);
  2807. zend_string *name = fptr->common.function_name;
  2808. const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  2809. RETURN_BOOL(backslash && backslash > ZSTR_VAL(name));
  2810. }
  2811. /* }}} */
  2812. /* {{{ proto public string ReflectionFunction::getNamespaceName()
  2813. Returns the name of namespace where this function is defined */
  2814. ZEND_METHOD(ReflectionFunctionAbstract, getNamespaceName)
  2815. {
  2816. reflection_object *intern;
  2817. zend_function *fptr;
  2818. if (zend_parse_parameters_none() == FAILURE) {
  2819. RETURN_THROWS();
  2820. }
  2821. GET_REFLECTION_OBJECT_PTR(fptr);
  2822. zend_string *name = fptr->common.function_name;
  2823. const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  2824. if (backslash && backslash > ZSTR_VAL(name)) {
  2825. RETURN_STRINGL(ZSTR_VAL(name), backslash - ZSTR_VAL(name));
  2826. }
  2827. RETURN_EMPTY_STRING();
  2828. }
  2829. /* }}} */
  2830. /* {{{ proto public string ReflectionFunction::getShortName()
  2831. Returns the short name of the function (without namespace part) */
  2832. ZEND_METHOD(ReflectionFunctionAbstract, getShortName)
  2833. {
  2834. reflection_object *intern;
  2835. zend_function *fptr;
  2836. if (zend_parse_parameters_none() == FAILURE) {
  2837. RETURN_THROWS();
  2838. }
  2839. GET_REFLECTION_OBJECT_PTR(fptr);
  2840. zend_string *name = fptr->common.function_name;
  2841. const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  2842. if (backslash && backslash > ZSTR_VAL(name)) {
  2843. RETURN_STRINGL(backslash + 1, ZSTR_LEN(name) - (backslash - ZSTR_VAL(name) + 1));
  2844. }
  2845. RETURN_STR_COPY(name);
  2846. }
  2847. /* }}} */
  2848. /* {{{ proto public bool ReflectionFunctionAbstract:hasReturnType()
  2849. Return whether the function has a return type */
  2850. ZEND_METHOD(ReflectionFunctionAbstract, hasReturnType)
  2851. {
  2852. reflection_object *intern;
  2853. zend_function *fptr;
  2854. if (zend_parse_parameters_none() == FAILURE) {
  2855. RETURN_THROWS();
  2856. }
  2857. GET_REFLECTION_OBJECT_PTR(fptr);
  2858. RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
  2859. }
  2860. /* }}} */
  2861. /* {{{ proto public string ReflectionFunctionAbstract::getReturnType()
  2862. Returns the return type associated with the function */
  2863. ZEND_METHOD(ReflectionFunctionAbstract, getReturnType)
  2864. {
  2865. reflection_object *intern;
  2866. zend_function *fptr;
  2867. if (zend_parse_parameters_none() == FAILURE) {
  2868. RETURN_THROWS();
  2869. }
  2870. GET_REFLECTION_OBJECT_PTR(fptr);
  2871. if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
  2872. RETURN_NULL();
  2873. }
  2874. reflection_type_factory(fptr->common.arg_info[-1].type, return_value, 1);
  2875. }
  2876. /* }}} */
  2877. /* {{{ proto public bool ReflectionMethod::isConstructor()
  2878. Returns whether this method is the constructor */
  2879. ZEND_METHOD(ReflectionMethod, isConstructor)
  2880. {
  2881. reflection_object *intern;
  2882. zend_function *mptr;
  2883. if (zend_parse_parameters_none() == FAILURE) {
  2884. RETURN_THROWS();
  2885. }
  2886. GET_REFLECTION_OBJECT_PTR(mptr);
  2887. /* we need to check if the ctor is the ctor of the class level we we
  2888. * looking at since we might be looking at an inherited old style ctor
  2889. * defined in base class. */
  2890. RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
  2891. }
  2892. /* }}} */
  2893. /* {{{ proto public bool ReflectionMethod::isDestructor()
  2894. Returns whether this method is a destructor */
  2895. ZEND_METHOD(ReflectionMethod, isDestructor)
  2896. {
  2897. reflection_object *intern;
  2898. zend_function *mptr;
  2899. if (zend_parse_parameters_none() == FAILURE) {
  2900. RETURN_THROWS();
  2901. }
  2902. GET_REFLECTION_OBJECT_PTR(mptr);
  2903. RETURN_BOOL(zend_string_equals_literal_ci(
  2904. mptr->common.function_name, ZEND_DESTRUCTOR_FUNC_NAME));
  2905. }
  2906. /* }}} */
  2907. /* {{{ proto public int ReflectionMethod::getModifiers()
  2908. Returns a bitfield of the access modifiers for this method */
  2909. ZEND_METHOD(ReflectionMethod, getModifiers)
  2910. {
  2911. reflection_object *intern;
  2912. zend_function *mptr;
  2913. uint32_t keep_flags = ZEND_ACC_PPP_MASK
  2914. | ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL;
  2915. if (zend_parse_parameters_none() == FAILURE) {
  2916. RETURN_THROWS();
  2917. }
  2918. GET_REFLECTION_OBJECT_PTR(mptr);
  2919. RETURN_LONG((mptr->common.fn_flags & keep_flags));
  2920. }
  2921. /* }}} */
  2922. /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
  2923. Get the declaring class */
  2924. ZEND_METHOD(ReflectionMethod, getDeclaringClass)
  2925. {
  2926. reflection_object *intern;
  2927. zend_function *mptr;
  2928. GET_REFLECTION_OBJECT_PTR(mptr);
  2929. if (zend_parse_parameters_none() == FAILURE) {
  2930. RETURN_THROWS();
  2931. }
  2932. zend_reflection_class_factory(mptr->common.scope, return_value);
  2933. }
  2934. /* }}} */
  2935. /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype()
  2936. Get the prototype */
  2937. ZEND_METHOD(ReflectionMethod, getPrototype)
  2938. {
  2939. reflection_object *intern;
  2940. zend_function *mptr;
  2941. GET_REFLECTION_OBJECT_PTR(mptr);
  2942. if (zend_parse_parameters_none() == FAILURE) {
  2943. RETURN_THROWS();
  2944. }
  2945. if (!mptr->common.prototype) {
  2946. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2947. "Method %s::%s does not have a prototype", ZSTR_VAL(intern->ce->name), ZSTR_VAL(mptr->common.function_name));
  2948. RETURN_THROWS();
  2949. }
  2950. reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value);
  2951. }
  2952. /* }}} */
  2953. /* {{{ proto public void ReflectionMethod::setAccessible(bool visible)
  2954. Sets whether non-public methods can be invoked */
  2955. ZEND_METHOD(ReflectionMethod, setAccessible)
  2956. {
  2957. reflection_object *intern;
  2958. zend_bool visible;
  2959. if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
  2960. RETURN_THROWS();
  2961. }
  2962. intern = Z_REFLECTION_P(ZEND_THIS);
  2963. intern->ignore_visibility = visible;
  2964. }
  2965. /* }}} */
  2966. /* {{{ proto public void ReflectionClassConstant::__construct(mixed class, string name)
  2967. Constructor. Throws an Exception in case the given class constant does not exist */
  2968. ZEND_METHOD(ReflectionClassConstant, __construct)
  2969. {
  2970. zval *classname, *object;
  2971. zend_string *constname;
  2972. reflection_object *intern;
  2973. zend_class_entry *ce;
  2974. zend_class_constant *constant = NULL;
  2975. if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &classname, &constname) == FAILURE) {
  2976. RETURN_THROWS();
  2977. }
  2978. object = ZEND_THIS;
  2979. intern = Z_REFLECTION_P(object);
  2980. /* Find the class entry */
  2981. switch (Z_TYPE_P(classname)) {
  2982. case IS_STRING:
  2983. if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
  2984. zend_throw_exception_ex(reflection_exception_ptr, 0,
  2985. "Class %s does not exist", Z_STRVAL_P(classname));
  2986. RETURN_THROWS();
  2987. }
  2988. break;
  2989. case IS_OBJECT:
  2990. ce = Z_OBJCE_P(classname);
  2991. break;
  2992. default:
  2993. zend_argument_error(reflection_exception_ptr, 1, "must be of type object|string, %s given", zend_zval_type_name(classname));
  2994. RETURN_THROWS();
  2995. }
  2996. if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
  2997. zend_throw_exception_ex(reflection_exception_ptr, 0, "Class Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
  2998. RETURN_THROWS();
  2999. }
  3000. intern->ptr = constant;
  3001. intern->ref_type = REF_TYPE_CLASS_CONSTANT;
  3002. intern->ce = constant->ce;
  3003. intern->ignore_visibility = 0;
  3004. ZVAL_STR_COPY(reflection_prop_name(object), constname);
  3005. ZVAL_STR_COPY(reflection_prop_class(object), constant->ce->name);
  3006. }
  3007. /* }}} */
  3008. /* {{{ proto public string ReflectionClassConstant::__toString()
  3009. Returns a string representation */
  3010. ZEND_METHOD(ReflectionClassConstant, __toString)
  3011. {
  3012. reflection_object *intern;
  3013. zend_class_constant *ref;
  3014. smart_str str = {0};
  3015. zval name;
  3016. if (zend_parse_parameters_none() == FAILURE) {
  3017. RETURN_THROWS();
  3018. }
  3019. GET_REFLECTION_OBJECT_PTR(ref);
  3020. _default_get_name(ZEND_THIS, &name);
  3021. _class_const_string(&str, Z_STRVAL(name), ref, "");
  3022. zval_ptr_dtor(&name);
  3023. RETURN_STR(smart_str_extract(&str));
  3024. }
  3025. /* }}} */
  3026. /* {{{ proto public string ReflectionClassConstant::getName()
  3027. Returns the constant' name */
  3028. ZEND_METHOD(ReflectionClassConstant, getName)
  3029. {
  3030. if (zend_parse_parameters_none() == FAILURE) {
  3031. RETURN_THROWS();
  3032. }
  3033. _default_get_name(ZEND_THIS, return_value);
  3034. }
  3035. /* }}} */
  3036. static void _class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
  3037. {
  3038. reflection_object *intern;
  3039. zend_class_constant *ref;
  3040. if (zend_parse_parameters_none() == FAILURE) {
  3041. RETURN_THROWS();
  3042. }
  3043. GET_REFLECTION_OBJECT_PTR(ref);
  3044. RETURN_BOOL(Z_ACCESS_FLAGS(ref->value) & mask);
  3045. }
  3046. /* }}} */
  3047. /* {{{ proto public bool ReflectionClassConstant::isPublic()
  3048. Returns whether this constant is public */
  3049. ZEND_METHOD(ReflectionClassConstant, isPublic)
  3050. {
  3051. _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
  3052. }
  3053. /* }}} */
  3054. /* {{{ proto public bool ReflectionClassConstant::isPrivate()
  3055. Returns whether this constant is private */
  3056. ZEND_METHOD(ReflectionClassConstant, isPrivate)
  3057. {
  3058. _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
  3059. }
  3060. /* }}} */
  3061. /* {{{ proto public bool ReflectionClassConstant::isProtected()
  3062. Returns whether this constant is protected */
  3063. ZEND_METHOD(ReflectionClassConstant, isProtected)
  3064. {
  3065. _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
  3066. }
  3067. /* }}} */
  3068. /* {{{ proto public int ReflectionClassConstant::getModifiers()
  3069. Returns a bitfield of the access modifiers for this constant */
  3070. ZEND_METHOD(ReflectionClassConstant, getModifiers)
  3071. {
  3072. reflection_object *intern;
  3073. zend_class_constant *ref;
  3074. if (zend_parse_parameters_none() == FAILURE) {
  3075. RETURN_THROWS();
  3076. }
  3077. GET_REFLECTION_OBJECT_PTR(ref);
  3078. RETURN_LONG(Z_ACCESS_FLAGS(ref->value));
  3079. }
  3080. /* }}} */
  3081. /* {{{ proto public mixed ReflectionClassConstant::getValue()
  3082. Returns this constant's value */
  3083. ZEND_METHOD(ReflectionClassConstant, getValue)
  3084. {
  3085. reflection_object *intern;
  3086. zend_class_constant *ref;
  3087. if (zend_parse_parameters_none() == FAILURE) {
  3088. RETURN_THROWS();
  3089. }
  3090. GET_REFLECTION_OBJECT_PTR(ref);
  3091. ZVAL_COPY_OR_DUP(return_value, &ref->value);
  3092. if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
  3093. zval_update_constant_ex(return_value, ref->ce);
  3094. }
  3095. }
  3096. /* }}} */
  3097. /* {{{ proto public ReflectionClass ReflectionClassConstant::getDeclaringClass()
  3098. Get the declaring class */
  3099. ZEND_METHOD(ReflectionClassConstant, getDeclaringClass)
  3100. {
  3101. reflection_object *intern;
  3102. zend_class_constant *ref;
  3103. if (zend_parse_parameters_none() == FAILURE) {
  3104. RETURN_THROWS();
  3105. }
  3106. GET_REFLECTION_OBJECT_PTR(ref);
  3107. zend_reflection_class_factory(ref->ce, return_value);
  3108. }
  3109. /* }}} */
  3110. /* {{{ proto public string ReflectionClassConstant::getDocComment()
  3111. Returns the doc comment for this constant */
  3112. ZEND_METHOD(ReflectionClassConstant, getDocComment)
  3113. {
  3114. reflection_object *intern;
  3115. zend_class_constant *ref;
  3116. if (zend_parse_parameters_none() == FAILURE) {
  3117. RETURN_THROWS();
  3118. }
  3119. GET_REFLECTION_OBJECT_PTR(ref);
  3120. if (ref->doc_comment) {
  3121. RETURN_STR_COPY(ref->doc_comment);
  3122. }
  3123. RETURN_FALSE;
  3124. }
  3125. /* }}} */
  3126. /* {{{ reflection_class_object_ctor */
  3127. static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
  3128. {
  3129. zval *argument;
  3130. zval *object;
  3131. reflection_object *intern;
  3132. zend_class_entry *ce;
  3133. if (is_object) {
  3134. ZEND_PARSE_PARAMETERS_START(1, 1)
  3135. Z_PARAM_OBJECT(argument)
  3136. ZEND_PARSE_PARAMETERS_END();
  3137. } else {
  3138. ZEND_PARSE_PARAMETERS_START(1, 1)
  3139. Z_PARAM_ZVAL(argument)
  3140. ZEND_PARSE_PARAMETERS_END();
  3141. }
  3142. object = ZEND_THIS;
  3143. intern = Z_REFLECTION_P(object);
  3144. if (Z_TYPE_P(argument) == IS_OBJECT) {
  3145. ZVAL_STR_COPY(reflection_prop_name(object), Z_OBJCE_P(argument)->name);
  3146. intern->ptr = Z_OBJCE_P(argument);
  3147. if (is_object) {
  3148. ZVAL_COPY(&intern->obj, argument);
  3149. }
  3150. } else {
  3151. if (!try_convert_to_string(argument)) {
  3152. RETURN_THROWS();
  3153. }
  3154. if ((ce = zend_lookup_class(Z_STR_P(argument))) == NULL) {
  3155. if (!EG(exception)) {
  3156. zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", Z_STRVAL_P(argument));
  3157. }
  3158. RETURN_THROWS();
  3159. }
  3160. ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
  3161. intern->ptr = ce;
  3162. }
  3163. intern->ref_type = REF_TYPE_OTHER;
  3164. }
  3165. /* }}} */
  3166. /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException
  3167. Constructor. Takes a string or an instance as an argument */
  3168. ZEND_METHOD(ReflectionClass, __construct)
  3169. {
  3170. reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  3171. }
  3172. /* }}} */
  3173. /* {{{ add_class_vars */
  3174. static void add_class_vars(zend_class_entry *ce, zend_bool statics, zval *return_value)
  3175. {
  3176. zend_property_info *prop_info;
  3177. zval *prop, prop_copy;
  3178. zend_string *key;
  3179. ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
  3180. if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
  3181. !zend_check_protected(prop_info->ce, ce)) ||
  3182. ((prop_info->flags & ZEND_ACC_PRIVATE) &&
  3183. prop_info->ce != ce)) {
  3184. continue;
  3185. }
  3186. zend_bool is_static = (prop_info->flags & ZEND_ACC_STATIC) != 0;
  3187. if (statics != is_static) {
  3188. continue;
  3189. }
  3190. prop = property_get_default(prop_info);
  3191. if (Z_ISUNDEF_P(prop)) {
  3192. continue;
  3193. }
  3194. /* copy: enforce read only access */
  3195. ZVAL_DEREF(prop);
  3196. ZVAL_COPY_OR_DUP(&prop_copy, prop);
  3197. /* this is necessary to make it able to work with default array
  3198. * properties, returned to user */
  3199. if (Z_TYPE(prop_copy) == IS_CONSTANT_AST) {
  3200. if (UNEXPECTED(zval_update_constant_ex(&prop_copy, ce) != SUCCESS)) {
  3201. return;
  3202. }
  3203. }
  3204. zend_hash_update(Z_ARRVAL_P(return_value), key, &prop_copy);
  3205. } ZEND_HASH_FOREACH_END();
  3206. }
  3207. /* }}} */
  3208. /* {{{ proto public array ReflectionClass::getStaticProperties()
  3209. Returns an associative array containing all static property values of the class */
  3210. ZEND_METHOD(ReflectionClass, getStaticProperties)
  3211. {
  3212. reflection_object *intern;
  3213. zend_class_entry *ce;
  3214. if (zend_parse_parameters_none() == FAILURE) {
  3215. RETURN_THROWS();
  3216. }
  3217. GET_REFLECTION_OBJECT_PTR(ce);
  3218. if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
  3219. return;
  3220. }
  3221. array_init(return_value);
  3222. add_class_vars(ce, 1, return_value);
  3223. }
  3224. /* }}} */
  3225. /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default])
  3226. Returns the value of a static property */
  3227. ZEND_METHOD(ReflectionClass, getStaticPropertyValue)
  3228. {
  3229. reflection_object *intern;
  3230. zend_class_entry *ce;
  3231. zend_string *name;
  3232. zval *prop, *def_value = NULL;
  3233. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &name, &def_value) == FAILURE) {
  3234. RETURN_THROWS();
  3235. }
  3236. GET_REFLECTION_OBJECT_PTR(ce);
  3237. if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
  3238. return;
  3239. }
  3240. prop = zend_std_get_static_property(ce, name, BP_VAR_IS);
  3241. if (!prop) {
  3242. if (def_value) {
  3243. ZVAL_COPY(return_value, def_value);
  3244. } else {
  3245. zend_throw_exception_ex(reflection_exception_ptr, 0,
  3246. "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
  3247. }
  3248. return;
  3249. } else {
  3250. ZVAL_COPY_DEREF(return_value, prop);
  3251. }
  3252. }
  3253. /* }}} */
  3254. /* {{{ proto public void ReflectionClass::setStaticPropertyValue(string $name, mixed $value)
  3255. Sets the value of a static property */
  3256. ZEND_METHOD(ReflectionClass, setStaticPropertyValue)
  3257. {
  3258. reflection_object *intern;
  3259. zend_class_entry *ce;
  3260. zend_property_info *prop_info;
  3261. zend_string *name;
  3262. zval *variable_ptr, *value;
  3263. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &name, &value) == FAILURE) {
  3264. RETURN_THROWS();
  3265. }
  3266. GET_REFLECTION_OBJECT_PTR(ce);
  3267. if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
  3268. return;
  3269. }
  3270. variable_ptr = zend_std_get_static_property_with_info(ce, name, BP_VAR_W, &prop_info);
  3271. if (!variable_ptr) {
  3272. zend_clear_exception();
  3273. zend_throw_exception_ex(reflection_exception_ptr, 0,
  3274. "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
  3275. RETURN_THROWS();
  3276. }
  3277. if (Z_ISREF_P(variable_ptr)) {
  3278. zend_reference *ref = Z_REF_P(variable_ptr);
  3279. variable_ptr = Z_REFVAL_P(variable_ptr);
  3280. if (!zend_verify_ref_assignable_zval(ref, value, 0)) {
  3281. return;
  3282. }
  3283. }
  3284. if (ZEND_TYPE_IS_SET(prop_info->type) && !zend_verify_property_type(prop_info, value, 0)) {
  3285. return;
  3286. }
  3287. zval_ptr_dtor(variable_ptr);
  3288. ZVAL_COPY(variable_ptr, value);
  3289. }
  3290. /* }}} */
  3291. /* {{{ proto public array ReflectionClass::getDefaultProperties()
  3292. Returns an associative array containing copies of all default property values of the class */
  3293. ZEND_METHOD(ReflectionClass, getDefaultProperties)
  3294. {
  3295. reflection_object *intern;
  3296. zend_class_entry *ce;
  3297. if (zend_parse_parameters_none() == FAILURE) {
  3298. RETURN_THROWS();
  3299. }
  3300. GET_REFLECTION_OBJECT_PTR(ce);
  3301. array_init(return_value);
  3302. if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
  3303. return;
  3304. }
  3305. add_class_vars(ce, 1, return_value);
  3306. add_class_vars(ce, 0, return_value);
  3307. }
  3308. /* }}} */
  3309. /* {{{ proto public string ReflectionClass::__toString()
  3310. Returns a string representation */
  3311. ZEND_METHOD(ReflectionClass, __toString)
  3312. {
  3313. reflection_object *intern;
  3314. zend_class_entry *ce;
  3315. smart_str str = {0};
  3316. if (zend_parse_parameters_none() == FAILURE) {
  3317. RETURN_THROWS();
  3318. }
  3319. GET_REFLECTION_OBJECT_PTR(ce);
  3320. _class_string(&str, ce, &intern->obj, "");
  3321. RETURN_STR(smart_str_extract(&str));
  3322. }
  3323. /* }}} */
  3324. /* {{{ proto public string ReflectionClass::getName()
  3325. Returns the class' name */
  3326. ZEND_METHOD(ReflectionClass, getName)
  3327. {
  3328. reflection_object *intern;
  3329. zend_class_entry *ce;
  3330. if (zend_parse_parameters_none() == FAILURE) {
  3331. RETURN_THROWS();
  3332. }
  3333. GET_REFLECTION_OBJECT_PTR(ce);
  3334. RETURN_STR_COPY(ce->name);
  3335. }
  3336. /* }}} */
  3337. /* {{{ proto public bool ReflectionClass::isInternal()
  3338. Returns whether this class is an internal class */
  3339. ZEND_METHOD(ReflectionClass, isInternal)
  3340. {
  3341. reflection_object *intern;
  3342. zend_class_entry *ce;
  3343. if (zend_parse_parameters_none() == FAILURE) {
  3344. RETURN_THROWS();
  3345. }
  3346. GET_REFLECTION_OBJECT_PTR(ce);
  3347. RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
  3348. }
  3349. /* }}} */
  3350. /* {{{ proto public bool ReflectionClass::isUserDefined()
  3351. Returns whether this class is user-defined */
  3352. ZEND_METHOD(ReflectionClass, isUserDefined)
  3353. {
  3354. reflection_object *intern;
  3355. zend_class_entry *ce;
  3356. if (zend_parse_parameters_none() == FAILURE) {
  3357. RETURN_THROWS();
  3358. }
  3359. GET_REFLECTION_OBJECT_PTR(ce);
  3360. RETURN_BOOL(ce->type == ZEND_USER_CLASS);
  3361. }
  3362. /* }}} */
  3363. /* {{{ proto public bool ReflectionClass::isAnonymous()
  3364. Returns whether this class is anonymous */
  3365. ZEND_METHOD(ReflectionClass, isAnonymous)
  3366. {
  3367. reflection_object *intern;
  3368. zend_class_entry *ce;
  3369. if (zend_parse_parameters_none() == FAILURE) {
  3370. RETURN_THROWS();
  3371. }
  3372. GET_REFLECTION_OBJECT_PTR(ce);
  3373. RETURN_BOOL(ce->ce_flags & ZEND_ACC_ANON_CLASS);
  3374. }
  3375. /* }}} */
  3376. /* {{{ proto public string ReflectionClass::getFileName()
  3377. Returns the filename of the file this class was declared in */
  3378. ZEND_METHOD(ReflectionClass, getFileName)
  3379. {
  3380. reflection_object *intern;
  3381. zend_class_entry *ce;
  3382. if (zend_parse_parameters_none() == FAILURE) {
  3383. RETURN_THROWS();
  3384. }
  3385. GET_REFLECTION_OBJECT_PTR(ce);
  3386. if (ce->type == ZEND_USER_CLASS) {
  3387. RETURN_STR_COPY(ce->info.user.filename);
  3388. }
  3389. RETURN_FALSE;
  3390. }
  3391. /* }}} */
  3392. /* {{{ proto public int ReflectionClass::getStartLine()
  3393. Returns the line this class' declaration starts at */
  3394. ZEND_METHOD(ReflectionClass, getStartLine)
  3395. {
  3396. reflection_object *intern;
  3397. zend_class_entry *ce;
  3398. if (zend_parse_parameters_none() == FAILURE) {
  3399. RETURN_THROWS();
  3400. }
  3401. GET_REFLECTION_OBJECT_PTR(ce);
  3402. if (ce->type == ZEND_USER_CLASS) {
  3403. RETURN_LONG(ce->info.user.line_start);
  3404. }
  3405. RETURN_FALSE;
  3406. }
  3407. /* }}} */
  3408. /* {{{ proto public int ReflectionClass::getEndLine()
  3409. Returns the line this class' declaration ends at */
  3410. ZEND_METHOD(ReflectionClass, getEndLine)
  3411. {
  3412. reflection_object *intern;
  3413. zend_class_entry *ce;
  3414. if (zend_parse_parameters_none() == FAILURE) {
  3415. RETURN_THROWS();
  3416. }
  3417. GET_REFLECTION_OBJECT_PTR(ce);
  3418. if (ce->type == ZEND_USER_CLASS) {
  3419. RETURN_LONG(ce->info.user.line_end);
  3420. }
  3421. RETURN_FALSE;
  3422. }
  3423. /* }}} */
  3424. /* {{{ proto public string ReflectionClass::getDocComment()
  3425. Returns the doc comment for this class */
  3426. ZEND_METHOD(ReflectionClass, getDocComment)
  3427. {
  3428. reflection_object *intern;
  3429. zend_class_entry *ce;
  3430. if (zend_parse_parameters_none() == FAILURE) {
  3431. RETURN_THROWS();
  3432. }
  3433. GET_REFLECTION_OBJECT_PTR(ce);
  3434. if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
  3435. RETURN_STR_COPY(ce->info.user.doc_comment);
  3436. }
  3437. RETURN_FALSE;
  3438. }
  3439. /* }}} */
  3440. /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
  3441. Returns the class' constructor if there is one, NULL otherwise */
  3442. ZEND_METHOD(ReflectionClass, getConstructor)
  3443. {
  3444. reflection_object *intern;
  3445. zend_class_entry *ce;
  3446. if (zend_parse_parameters_none() == FAILURE) {
  3447. RETURN_THROWS();
  3448. }
  3449. GET_REFLECTION_OBJECT_PTR(ce);
  3450. if (ce->constructor) {
  3451. reflection_method_factory(ce, ce->constructor, NULL, return_value);
  3452. } else {
  3453. RETURN_NULL();
  3454. }
  3455. }
  3456. /* }}} */
  3457. /* {{{ proto public bool ReflectionClass::hasMethod(string name)
  3458. Returns whether a method exists or not */
  3459. ZEND_METHOD(ReflectionClass, hasMethod)
  3460. {
  3461. reflection_object *intern;
  3462. zend_class_entry *ce;
  3463. zend_string *name, *lc_name;
  3464. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
  3465. RETURN_THROWS();
  3466. }
  3467. GET_REFLECTION_OBJECT_PTR(ce);
  3468. lc_name = zend_string_tolower(name);
  3469. RETVAL_BOOL(zend_hash_exists(&ce->function_table, lc_name) || is_closure_invoke(ce, lc_name));
  3470. zend_string_release(lc_name);
  3471. }
  3472. /* }}} */
  3473. /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
  3474. Returns the class' method specified by its name */
  3475. ZEND_METHOD(ReflectionClass, getMethod)
  3476. {
  3477. reflection_object *intern;
  3478. zend_class_entry *ce;
  3479. zend_function *mptr;
  3480. zval obj_tmp;
  3481. zend_string *name, *lc_name;
  3482. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
  3483. RETURN_THROWS();
  3484. }
  3485. GET_REFLECTION_OBJECT_PTR(ce);
  3486. lc_name = zend_string_tolower(name);
  3487. if (!Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
  3488. && (mptr = zend_get_closure_invoke_method(Z_OBJ(intern->obj))) != NULL)
  3489. {
  3490. /* don't assign closure_object since we only reflect the invoke handler
  3491. method and not the closure definition itself */
  3492. reflection_method_factory(ce, mptr, NULL, return_value);
  3493. } else if (Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
  3494. && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(Z_OBJ(obj_tmp))) != NULL) {
  3495. /* don't assign closure_object since we only reflect the invoke handler
  3496. method and not the closure definition itself */
  3497. reflection_method_factory(ce, mptr, NULL, return_value);
  3498. zval_ptr_dtor(&obj_tmp);
  3499. } else if ((mptr = zend_hash_find_ptr(&ce->function_table, lc_name)) != NULL) {
  3500. reflection_method_factory(ce, mptr, NULL, return_value);
  3501. } else {
  3502. zend_throw_exception_ex(reflection_exception_ptr, 0,
  3503. "Method %s does not exist", ZSTR_VAL(name));
  3504. }
  3505. zend_string_release(lc_name);
  3506. }
  3507. /* }}} */
  3508. /* {{{ _addmethod */
  3509. static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter)
  3510. {
  3511. if ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && mptr->common.scope != ce) {
  3512. return;
  3513. }
  3514. if (mptr->common.fn_flags & filter) {
  3515. zval method;
  3516. reflection_method_factory(ce, mptr, NULL, &method);
  3517. add_next_index_zval(retval, &method);
  3518. }
  3519. }
  3520. /* }}} */
  3521. /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter])
  3522. Returns an array of this class' methods */
  3523. ZEND_METHOD(ReflectionClass, getMethods)
  3524. {
  3525. reflection_object *intern;
  3526. zend_class_entry *ce;
  3527. zend_function *mptr;
  3528. zend_long filter = 0;
  3529. zend_bool filter_is_null = 1;
  3530. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
  3531. RETURN_THROWS();
  3532. }
  3533. if (filter_is_null) {
  3534. filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
  3535. }
  3536. GET_REFLECTION_OBJECT_PTR(ce);
  3537. array_init(return_value);
  3538. ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
  3539. _addmethod(mptr, ce, return_value, filter);
  3540. } ZEND_HASH_FOREACH_END();
  3541. if (instanceof_function(ce, zend_ce_closure)) {
  3542. zend_bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
  3543. zval obj_tmp;
  3544. zend_object *obj;
  3545. if (!has_obj) {
  3546. object_init_ex(&obj_tmp, ce);
  3547. obj = Z_OBJ(obj_tmp);
  3548. } else {
  3549. obj = Z_OBJ(intern->obj);
  3550. }
  3551. zend_function *closure = zend_get_closure_invoke_method(obj);
  3552. if (closure) {
  3553. _addmethod(closure, ce, return_value, filter);
  3554. }
  3555. if (!has_obj) {
  3556. zval_ptr_dtor(&obj_tmp);
  3557. }
  3558. }
  3559. }
  3560. /* }}} */
  3561. /* {{{ proto public bool ReflectionClass::hasProperty(string name)
  3562. Returns whether a property exists or not */
  3563. ZEND_METHOD(ReflectionClass, hasProperty)
  3564. {
  3565. reflection_object *intern;
  3566. zend_property_info *property_info;
  3567. zend_class_entry *ce;
  3568. zend_string *name;
  3569. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
  3570. RETURN_THROWS();
  3571. }
  3572. GET_REFLECTION_OBJECT_PTR(ce);
  3573. if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
  3574. if ((property_info->flags & ZEND_ACC_PRIVATE) && property_info->ce != ce) {
  3575. RETURN_FALSE;
  3576. }
  3577. RETURN_TRUE;
  3578. } else {
  3579. if (Z_TYPE(intern->obj) != IS_UNDEF) {
  3580. if (Z_OBJ_HANDLER(intern->obj, has_property)(Z_OBJ(intern->obj), name, 2, NULL)) {
  3581. RETURN_TRUE;
  3582. }
  3583. }
  3584. RETURN_FALSE;
  3585. }
  3586. }
  3587. /* }}} */
  3588. /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
  3589. Returns the class' property specified by its name */
  3590. ZEND_METHOD(ReflectionClass, getProperty)
  3591. {
  3592. reflection_object *intern;
  3593. zend_class_entry *ce, *ce2;
  3594. zend_property_info *property_info;
  3595. zend_string *name, *classname;
  3596. char *tmp, *str_name;
  3597. size_t classname_len, str_name_len;
  3598. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
  3599. RETURN_THROWS();
  3600. }
  3601. GET_REFLECTION_OBJECT_PTR(ce);
  3602. if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
  3603. if (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce) {
  3604. reflection_property_factory(ce, name, property_info, return_value);
  3605. return;
  3606. }
  3607. } else if (Z_TYPE(intern->obj) != IS_UNDEF) {
  3608. /* Check for dynamic properties */
  3609. if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(Z_OBJ(intern->obj)), name)) {
  3610. reflection_property_factory(ce, name, NULL, return_value);
  3611. return;
  3612. }
  3613. }
  3614. str_name = ZSTR_VAL(name);
  3615. if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) {
  3616. classname_len = tmp - ZSTR_VAL(name);
  3617. classname = zend_string_alloc(classname_len, 0);
  3618. zend_str_tolower_copy(ZSTR_VAL(classname), ZSTR_VAL(name), classname_len);
  3619. ZSTR_VAL(classname)[classname_len] = '\0';
  3620. str_name_len = ZSTR_LEN(name) - (classname_len + 2);
  3621. str_name = tmp + 2;
  3622. ce2 = zend_lookup_class(classname);
  3623. if (!ce2) {
  3624. if (!EG(exception)) {
  3625. zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", ZSTR_VAL(classname));
  3626. }
  3627. zend_string_release_ex(classname, 0);
  3628. RETURN_THROWS();
  3629. }
  3630. zend_string_release_ex(classname, 0);
  3631. if (!instanceof_function(ce, ce2)) {
  3632. zend_throw_exception_ex(reflection_exception_ptr, -1, "Fully qualified property name %s::%s does not specify a base class of %s", ZSTR_VAL(ce2->name), str_name, ZSTR_VAL(ce->name));
  3633. RETURN_THROWS();
  3634. }
  3635. ce = ce2;
  3636. property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len);
  3637. if (property_info != NULL
  3638. && (!(property_info->flags & ZEND_ACC_PRIVATE)
  3639. || property_info->ce == ce)) {
  3640. reflection_property_factory_str(ce, str_name, str_name_len, property_info, return_value);
  3641. return;
  3642. }
  3643. }
  3644. zend_throw_exception_ex(reflection_exception_ptr, 0,
  3645. "Property %s does not exist", str_name);
  3646. }
  3647. /* }}} */
  3648. /* {{{ _addproperty */
  3649. static void _addproperty(zend_property_info *pptr, zend_string *key, zend_class_entry *ce, zval *retval, long filter)
  3650. {
  3651. if ((pptr->flags & ZEND_ACC_PRIVATE) && pptr->ce != ce) {
  3652. return;
  3653. }
  3654. if (pptr->flags & filter) {
  3655. zval property;
  3656. reflection_property_factory(ce, key, pptr, &property);
  3657. add_next_index_zval(retval, &property);
  3658. }
  3659. }
  3660. /* }}} */
  3661. /* {{{ _adddynproperty */
  3662. static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, zval *retval)
  3663. {
  3664. zval property;
  3665. /* under some circumstances, the properties hash table may contain numeric
  3666. * properties (e.g. when casting from array). This is a WON'T FIX bug, at
  3667. * least for the moment. Ignore these */
  3668. if (key == NULL) {
  3669. return;
  3670. }
  3671. /* Not a dynamic property */
  3672. if (Z_TYPE_P(ptr) == IS_INDIRECT) {
  3673. return;
  3674. }
  3675. reflection_property_factory(ce, key, NULL, &property);
  3676. add_next_index_zval(retval, &property);
  3677. }
  3678. /* }}} */
  3679. /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter])
  3680. Returns an array of this class' properties */
  3681. ZEND_METHOD(ReflectionClass, getProperties)
  3682. {
  3683. reflection_object *intern;
  3684. zend_class_entry *ce;
  3685. zend_string *key;
  3686. zend_property_info *prop_info;
  3687. zend_long filter = 0;
  3688. zend_bool filter_is_null = 1;
  3689. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
  3690. RETURN_THROWS();
  3691. }
  3692. if (filter_is_null) {
  3693. filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
  3694. }
  3695. GET_REFLECTION_OBJECT_PTR(ce);
  3696. array_init(return_value);
  3697. ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
  3698. _addproperty(prop_info, key, ce, return_value, filter);
  3699. } ZEND_HASH_FOREACH_END();
  3700. if (Z_TYPE(intern->obj) != IS_UNDEF && (filter & ZEND_ACC_PUBLIC) != 0) {
  3701. HashTable *properties = Z_OBJ_HT(intern->obj)->get_properties(Z_OBJ(intern->obj));
  3702. zval *prop;
  3703. ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
  3704. _adddynproperty(prop, key, ce, return_value);
  3705. } ZEND_HASH_FOREACH_END();
  3706. }
  3707. }
  3708. /* }}} */
  3709. /* {{{ proto public bool ReflectionClass::hasConstant(string name)
  3710. Returns whether a constant exists or not */
  3711. ZEND_METHOD(ReflectionClass, hasConstant)
  3712. {
  3713. reflection_object *intern;
  3714. zend_class_entry *ce;
  3715. zend_string *name;
  3716. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
  3717. RETURN_THROWS();
  3718. }
  3719. GET_REFLECTION_OBJECT_PTR(ce);
  3720. if (zend_hash_exists(&ce->constants_table, name)) {
  3721. RETURN_TRUE;
  3722. } else {
  3723. RETURN_FALSE;
  3724. }
  3725. }
  3726. /* }}} */
  3727. /* {{{ proto public array ReflectionClass::getConstants()
  3728. Returns an associative array containing this class' constants and their values */
  3729. ZEND_METHOD(ReflectionClass, getConstants)
  3730. {
  3731. reflection_object *intern;
  3732. zend_class_entry *ce;
  3733. zend_string *key;
  3734. zend_class_constant *c;
  3735. zval val;
  3736. if (zend_parse_parameters_none() == FAILURE) {
  3737. RETURN_THROWS();
  3738. }
  3739. GET_REFLECTION_OBJECT_PTR(ce);
  3740. array_init(return_value);
  3741. ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
  3742. if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
  3743. zend_array_destroy(Z_ARRVAL_P(return_value));
  3744. RETURN_NULL();
  3745. }
  3746. ZVAL_COPY_OR_DUP(&val, &c->value);
  3747. zend_hash_add_new(Z_ARRVAL_P(return_value), key, &val);
  3748. } ZEND_HASH_FOREACH_END();
  3749. }
  3750. /* }}} */
  3751. /* {{{ proto public array ReflectionClass::getReflectionConstants()
  3752. Returns an associative array containing this class' constants as ReflectionClassConstant objects */
  3753. ZEND_METHOD(ReflectionClass, getReflectionConstants)
  3754. {
  3755. reflection_object *intern;
  3756. zend_class_entry *ce;
  3757. zend_string *name;
  3758. zend_class_constant *constant;
  3759. if (zend_parse_parameters_none() == FAILURE) {
  3760. RETURN_THROWS();
  3761. }
  3762. GET_REFLECTION_OBJECT_PTR(ce);
  3763. array_init(return_value);
  3764. ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
  3765. zval class_const;
  3766. reflection_class_constant_factory(name, constant, &class_const);
  3767. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
  3768. } ZEND_HASH_FOREACH_END();
  3769. }
  3770. /* }}} */
  3771. /* {{{ proto public mixed ReflectionClass::getConstant(string name)
  3772. Returns the class' constant specified by its name */
  3773. ZEND_METHOD(ReflectionClass, getConstant)
  3774. {
  3775. reflection_object *intern;
  3776. zend_class_entry *ce;
  3777. zend_class_constant *c;
  3778. zend_string *name;
  3779. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
  3780. RETURN_THROWS();
  3781. }
  3782. GET_REFLECTION_OBJECT_PTR(ce);
  3783. ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
  3784. if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
  3785. return;
  3786. }
  3787. } ZEND_HASH_FOREACH_END();
  3788. if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
  3789. RETURN_FALSE;
  3790. }
  3791. ZVAL_COPY_OR_DUP(return_value, &c->value);
  3792. }
  3793. /* }}} */
  3794. /* {{{ proto public mixed ReflectionClass::getReflectionConstant(string name)
  3795. Returns the class' constant as ReflectionClassConstant objects */
  3796. ZEND_METHOD(ReflectionClass, getReflectionConstant)
  3797. {
  3798. reflection_object *intern;
  3799. zend_class_entry *ce;
  3800. zend_class_constant *constant;
  3801. zend_string *name;
  3802. GET_REFLECTION_OBJECT_PTR(ce);
  3803. if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
  3804. RETURN_THROWS();
  3805. }
  3806. if ((constant = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
  3807. RETURN_FALSE;
  3808. }
  3809. reflection_class_constant_factory(name, constant, return_value);
  3810. }
  3811. /* }}} */
  3812. /* {{{ _class_check_flag */
  3813. static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
  3814. {
  3815. reflection_object *intern;
  3816. zend_class_entry *ce;
  3817. if (zend_parse_parameters_none() == FAILURE) {
  3818. RETURN_THROWS();
  3819. }
  3820. GET_REFLECTION_OBJECT_PTR(ce);
  3821. RETVAL_BOOL(ce->ce_flags & mask);
  3822. }
  3823. /* }}} */
  3824. /* {{{ proto public bool ReflectionClass::isInstantiable()
  3825. Returns whether this class is instantiable */
  3826. ZEND_METHOD(ReflectionClass, isInstantiable)
  3827. {
  3828. reflection_object *intern;
  3829. zend_class_entry *ce;
  3830. if (zend_parse_parameters_none() == FAILURE) {
  3831. RETURN_THROWS();
  3832. }
  3833. GET_REFLECTION_OBJECT_PTR(ce);
  3834. if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
  3835. RETURN_FALSE;
  3836. }
  3837. /* Basically, the class is instantiable. Though, if there is a constructor
  3838. * and it is not publicly accessible, it isn't! */
  3839. if (!ce->constructor) {
  3840. RETURN_TRUE;
  3841. }
  3842. RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
  3843. }
  3844. /* }}} */
  3845. /* {{{ proto public bool ReflectionClass::isCloneable()
  3846. Returns whether this class is cloneable */
  3847. ZEND_METHOD(ReflectionClass, isCloneable)
  3848. {
  3849. reflection_object *intern;
  3850. zend_class_entry *ce;
  3851. zval obj;
  3852. if (zend_parse_parameters_none() == FAILURE) {
  3853. RETURN_THROWS();
  3854. }
  3855. GET_REFLECTION_OBJECT_PTR(ce);
  3856. if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
  3857. RETURN_FALSE;
  3858. }
  3859. if (!Z_ISUNDEF(intern->obj)) {
  3860. if (ce->clone) {
  3861. RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
  3862. } else {
  3863. RETURN_BOOL(Z_OBJ_HANDLER(intern->obj, clone_obj) != NULL);
  3864. }
  3865. } else {
  3866. if (ce->clone) {
  3867. RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
  3868. } else {
  3869. if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) {
  3870. return;
  3871. }
  3872. /* We're not calling the constructor, so don't call the destructor either. */
  3873. zend_object_store_ctor_failed(Z_OBJ(obj));
  3874. RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
  3875. zval_ptr_dtor(&obj);
  3876. }
  3877. }
  3878. }
  3879. /* }}} */
  3880. /* {{{ proto public bool ReflectionClass::isInterface()
  3881. Returns whether this is an interface or a class */
  3882. ZEND_METHOD(ReflectionClass, isInterface)
  3883. {
  3884. _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
  3885. }
  3886. /* }}} */
  3887. /* {{{ proto public bool ReflectionClass::isTrait()
  3888. Returns whether this is a trait */
  3889. ZEND_METHOD(ReflectionClass, isTrait)
  3890. {
  3891. _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT);
  3892. }
  3893. /* }}} */
  3894. /* {{{ proto public bool ReflectionClass::isFinal()
  3895. Returns whether this class is final */
  3896. ZEND_METHOD(ReflectionClass, isFinal)
  3897. {
  3898. _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
  3899. }
  3900. /* }}} */
  3901. /* {{{ proto public bool ReflectionClass::isAbstract()
  3902. Returns whether this class is abstract */
  3903. ZEND_METHOD(ReflectionClass, isAbstract)
  3904. {
  3905. _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
  3906. }
  3907. /* }}} */
  3908. /* {{{ proto public int ReflectionClass::getModifiers()
  3909. Returns a bitfield of the access modifiers for this class */
  3910. ZEND_METHOD(ReflectionClass, getModifiers)
  3911. {
  3912. reflection_object *intern;
  3913. zend_class_entry *ce;
  3914. uint32_t keep_flags = ZEND_ACC_FINAL
  3915. | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
  3916. if (zend_parse_parameters_none() == FAILURE) {
  3917. RETURN_THROWS();
  3918. }
  3919. GET_REFLECTION_OBJECT_PTR(ce);
  3920. RETURN_LONG((ce->ce_flags & keep_flags));
  3921. }
  3922. /* }}} */
  3923. /* {{{ proto public bool ReflectionClass::isInstance(stdclass object)
  3924. Returns whether the given object is an instance of this class */
  3925. ZEND_METHOD(ReflectionClass, isInstance)
  3926. {
  3927. reflection_object *intern;
  3928. zend_class_entry *ce;
  3929. zval *object;
  3930. if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
  3931. RETURN_THROWS();
  3932. }
  3933. GET_REFLECTION_OBJECT_PTR(ce);
  3934. RETURN_BOOL(instanceof_function(Z_OBJCE_P(object), ce));
  3935. }
  3936. /* }}} */
  3937. /* {{{ proto public object ReflectionClass::newInstance([mixed* args], ...)
  3938. Returns an instance of this class */
  3939. ZEND_METHOD(ReflectionClass, newInstance)
  3940. {
  3941. zval retval;
  3942. reflection_object *intern;
  3943. zend_class_entry *ce, *old_scope;
  3944. zend_function *constructor;
  3945. GET_REFLECTION_OBJECT_PTR(ce);
  3946. if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
  3947. return;
  3948. }
  3949. old_scope = EG(fake_scope);
  3950. EG(fake_scope) = ce;
  3951. constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
  3952. EG(fake_scope) = old_scope;
  3953. /* Run the constructor if there is one */
  3954. if (constructor) {
  3955. zval *params = NULL;
  3956. int ret, i, num_args = 0;
  3957. zend_fcall_info fci;
  3958. zend_fcall_info_cache fcc;
  3959. if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
  3960. zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
  3961. zval_ptr_dtor(return_value);
  3962. RETURN_NULL();
  3963. }
  3964. if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &params, &num_args) == FAILURE) {
  3965. zval_ptr_dtor(return_value);
  3966. RETURN_THROWS();
  3967. }
  3968. for (i = 0; i < num_args; i++) {
  3969. Z_TRY_ADDREF(params[i]);
  3970. }
  3971. fci.size = sizeof(fci);
  3972. ZVAL_UNDEF(&fci.function_name);
  3973. fci.object = Z_OBJ_P(return_value);
  3974. fci.retval = &retval;
  3975. fci.param_count = num_args;
  3976. fci.params = params;
  3977. fci.no_separation = 1;
  3978. fcc.function_handler = constructor;
  3979. fcc.called_scope = Z_OBJCE_P(return_value);
  3980. fcc.object = Z_OBJ_P(return_value);
  3981. ret = zend_call_function(&fci, &fcc);
  3982. zval_ptr_dtor(&retval);
  3983. for (i = 0; i < num_args; i++) {
  3984. zval_ptr_dtor(&params[i]);
  3985. }
  3986. if (EG(exception)) {
  3987. zend_object_store_ctor_failed(Z_OBJ_P(return_value));
  3988. }
  3989. if (ret == FAILURE) {
  3990. php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
  3991. zval_ptr_dtor(return_value);
  3992. RETURN_NULL();
  3993. }
  3994. } else if (ZEND_NUM_ARGS()) {
  3995. zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
  3996. }
  3997. }
  3998. /* }}} */
  3999. /* {{{ proto public object ReflectionClass::newInstanceWithoutConstructor()
  4000. Returns an instance of this class without invoking its constructor */
  4001. ZEND_METHOD(ReflectionClass, newInstanceWithoutConstructor)
  4002. {
  4003. reflection_object *intern;
  4004. zend_class_entry *ce;
  4005. GET_REFLECTION_OBJECT_PTR(ce);
  4006. if (zend_parse_parameters_none() == FAILURE) {
  4007. RETURN_THROWS();
  4008. }
  4009. if (ce->type == ZEND_INTERNAL_CLASS
  4010. && ce->create_object != NULL && (ce->ce_flags & ZEND_ACC_FINAL)) {
  4011. zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s is an internal class marked as final that cannot be instantiated without invoking its constructor", ZSTR_VAL(ce->name));
  4012. RETURN_THROWS();
  4013. }
  4014. object_init_ex(return_value, ce);
  4015. }
  4016. /* }}} */
  4017. /* {{{ proto public object ReflectionClass::newInstanceArgs([array args])
  4018. Returns an instance of this class */
  4019. ZEND_METHOD(ReflectionClass, newInstanceArgs)
  4020. {
  4021. zval retval, *val;
  4022. reflection_object *intern;
  4023. zend_class_entry *ce, *old_scope;
  4024. int ret, i, argc = 0;
  4025. HashTable *args;
  4026. zend_function *constructor;
  4027. GET_REFLECTION_OBJECT_PTR(ce);
  4028. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &args) == FAILURE) {
  4029. RETURN_THROWS();
  4030. }
  4031. if (ZEND_NUM_ARGS() > 0) {
  4032. argc = args->nNumOfElements;
  4033. }
  4034. if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
  4035. return;
  4036. }
  4037. old_scope = EG(fake_scope);
  4038. EG(fake_scope) = ce;
  4039. constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
  4040. EG(fake_scope) = old_scope;
  4041. /* Run the constructor if there is one */
  4042. if (constructor) {
  4043. zval *params = NULL;
  4044. zend_fcall_info fci;
  4045. zend_fcall_info_cache fcc;
  4046. if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
  4047. zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
  4048. zval_ptr_dtor(return_value);
  4049. RETURN_NULL();
  4050. }
  4051. if (argc) {
  4052. params = safe_emalloc(sizeof(zval), argc, 0);
  4053. argc = 0;
  4054. ZEND_HASH_FOREACH_VAL(args, val) {
  4055. ZVAL_COPY(&params[argc], val);
  4056. argc++;
  4057. } ZEND_HASH_FOREACH_END();
  4058. }
  4059. fci.size = sizeof(fci);
  4060. ZVAL_UNDEF(&fci.function_name);
  4061. fci.object = Z_OBJ_P(return_value);
  4062. fci.retval = &retval;
  4063. fci.param_count = argc;
  4064. fci.params = params;
  4065. fci.no_separation = 1;
  4066. fcc.function_handler = constructor;
  4067. fcc.called_scope = Z_OBJCE_P(return_value);
  4068. fcc.object = Z_OBJ_P(return_value);
  4069. ret = zend_call_function(&fci, &fcc);
  4070. zval_ptr_dtor(&retval);
  4071. if (params) {
  4072. for (i = 0; i < argc; i++) {
  4073. zval_ptr_dtor(&params[i]);
  4074. }
  4075. efree(params);
  4076. }
  4077. if (EG(exception)) {
  4078. zend_object_store_ctor_failed(Z_OBJ_P(return_value));
  4079. }
  4080. if (ret == FAILURE) {
  4081. zval_ptr_dtor(&retval);
  4082. php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
  4083. zval_ptr_dtor(return_value);
  4084. RETURN_NULL();
  4085. }
  4086. } else if (argc) {
  4087. zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
  4088. }
  4089. }
  4090. /* }}} */
  4091. /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
  4092. Returns an array of interfaces this class implements */
  4093. ZEND_METHOD(ReflectionClass, getInterfaces)
  4094. {
  4095. reflection_object *intern;
  4096. zend_class_entry *ce;
  4097. if (zend_parse_parameters_none() == FAILURE) {
  4098. RETURN_THROWS();
  4099. }
  4100. GET_REFLECTION_OBJECT_PTR(ce);
  4101. if (ce->num_interfaces) {
  4102. uint32_t i;
  4103. ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
  4104. array_init(return_value);
  4105. for (i=0; i < ce->num_interfaces; i++) {
  4106. zval interface;
  4107. zend_reflection_class_factory(ce->interfaces[i], &interface);
  4108. zend_hash_update(Z_ARRVAL_P(return_value), ce->interfaces[i]->name, &interface);
  4109. }
  4110. } else {
  4111. RETURN_EMPTY_ARRAY();
  4112. }
  4113. }
  4114. /* }}} */
  4115. /* {{{ proto public String[] ReflectionClass::getInterfaceNames()
  4116. Returns an array of names of interfaces this class implements */
  4117. ZEND_METHOD(ReflectionClass, getInterfaceNames)
  4118. {
  4119. reflection_object *intern;
  4120. zend_class_entry *ce;
  4121. uint32_t i;
  4122. if (zend_parse_parameters_none() == FAILURE) {
  4123. RETURN_THROWS();
  4124. }
  4125. GET_REFLECTION_OBJECT_PTR(ce);
  4126. if (!ce->num_interfaces) {
  4127. /* Return an empty array if this class implements no interfaces */
  4128. RETURN_EMPTY_ARRAY();
  4129. }
  4130. ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
  4131. array_init(return_value);
  4132. for (i=0; i < ce->num_interfaces; i++) {
  4133. add_next_index_str(return_value, zend_string_copy(ce->interfaces[i]->name));
  4134. }
  4135. }
  4136. /* }}} */
  4137. /* {{{ proto public ReflectionClass[] ReflectionClass::getTraits()
  4138. Returns an array of traits used by this class */
  4139. ZEND_METHOD(ReflectionClass, getTraits)
  4140. {
  4141. reflection_object *intern;
  4142. zend_class_entry *ce;
  4143. uint32_t i;
  4144. if (zend_parse_parameters_none() == FAILURE) {
  4145. RETURN_THROWS();
  4146. }
  4147. GET_REFLECTION_OBJECT_PTR(ce);
  4148. if (!ce->num_traits) {
  4149. RETURN_EMPTY_ARRAY();
  4150. }
  4151. array_init(return_value);
  4152. for (i=0; i < ce->num_traits; i++) {
  4153. zval trait;
  4154. zend_class_entry *trait_ce;
  4155. trait_ce = zend_fetch_class_by_name(ce->trait_names[i].name,
  4156. ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT);
  4157. ZEND_ASSERT(trait_ce);
  4158. zend_reflection_class_factory(trait_ce, &trait);
  4159. zend_hash_update(Z_ARRVAL_P(return_value), ce->trait_names[i].name, &trait);
  4160. }
  4161. }
  4162. /* }}} */
  4163. /* {{{ proto public String[] ReflectionClass::getTraitNames()
  4164. Returns an array of names of traits used by this class */
  4165. ZEND_METHOD(ReflectionClass, getTraitNames)
  4166. {
  4167. reflection_object *intern;
  4168. zend_class_entry *ce;
  4169. uint32_t i;
  4170. if (zend_parse_parameters_none() == FAILURE) {
  4171. RETURN_THROWS();
  4172. }
  4173. GET_REFLECTION_OBJECT_PTR(ce);
  4174. if (!ce->num_traits) {
  4175. RETURN_EMPTY_ARRAY();
  4176. }
  4177. array_init(return_value);
  4178. for (i=0; i < ce->num_traits; i++) {
  4179. add_next_index_str(return_value, zend_string_copy(ce->trait_names[i].name));
  4180. }
  4181. }
  4182. /* }}} */
  4183. /* {{{ proto public array ReflectionClass::getTraitAliases()
  4184. Returns an array of trait aliases */
  4185. ZEND_METHOD(ReflectionClass, getTraitAliases)
  4186. {
  4187. reflection_object *intern;
  4188. zend_class_entry *ce;
  4189. if (zend_parse_parameters_none() == FAILURE) {
  4190. RETURN_THROWS();
  4191. }
  4192. GET_REFLECTION_OBJECT_PTR(ce);
  4193. if (ce->trait_aliases) {
  4194. uint32_t i = 0;
  4195. array_init(return_value);
  4196. while (ce->trait_aliases[i]) {
  4197. zend_string *mname;
  4198. zend_trait_method_reference *cur_ref = &ce->trait_aliases[i]->trait_method;
  4199. if (ce->trait_aliases[i]->alias) {
  4200. mname = zend_string_alloc(ZSTR_LEN(cur_ref->class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
  4201. snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->class_name), ZSTR_VAL(cur_ref->method_name));
  4202. add_assoc_str_ex(return_value, ZSTR_VAL(ce->trait_aliases[i]->alias), ZSTR_LEN(ce->trait_aliases[i]->alias), mname);
  4203. }
  4204. i++;
  4205. }
  4206. } else {
  4207. RETURN_EMPTY_ARRAY();
  4208. }
  4209. }
  4210. /* }}} */
  4211. /* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
  4212. Returns the class' parent class, or, if none exists, FALSE */
  4213. ZEND_METHOD(ReflectionClass, getParentClass)
  4214. {
  4215. reflection_object *intern;
  4216. zend_class_entry *ce;
  4217. if (zend_parse_parameters_none() == FAILURE) {
  4218. RETURN_THROWS();
  4219. }
  4220. GET_REFLECTION_OBJECT_PTR(ce);
  4221. if (ce->parent) {
  4222. zend_reflection_class_factory(ce->parent, return_value);
  4223. } else {
  4224. RETURN_FALSE;
  4225. }
  4226. }
  4227. /* }}} */
  4228. /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
  4229. Returns whether this class is a subclass of another class */
  4230. ZEND_METHOD(ReflectionClass, isSubclassOf)
  4231. {
  4232. reflection_object *intern, *argument;
  4233. zend_class_entry *ce, *class_ce;
  4234. zval *class_name;
  4235. GET_REFLECTION_OBJECT_PTR(ce);
  4236. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE) {
  4237. RETURN_THROWS();
  4238. }
  4239. switch (Z_TYPE_P(class_name)) {
  4240. case IS_STRING:
  4241. if ((class_ce = zend_lookup_class(Z_STR_P(class_name))) == NULL) {
  4242. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4243. "Class %s does not exist", Z_STRVAL_P(class_name));
  4244. RETURN_THROWS();
  4245. }
  4246. break;
  4247. case IS_OBJECT:
  4248. if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr)) {
  4249. argument = Z_REFLECTION_P(class_name);
  4250. if (argument->ptr == NULL) {
  4251. zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
  4252. RETURN_THROWS();
  4253. }
  4254. class_ce = argument->ptr;
  4255. break;
  4256. }
  4257. /* no break */
  4258. default:
  4259. zend_argument_error(reflection_exception_ptr, 1, "must be of type ReflectionClass|string, %s given", zend_zval_type_name(class_name));
  4260. RETURN_THROWS();
  4261. }
  4262. RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce)));
  4263. }
  4264. /* }}} */
  4265. /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
  4266. Returns whether this class is a subclass of another class */
  4267. ZEND_METHOD(ReflectionClass, implementsInterface)
  4268. {
  4269. reflection_object *intern, *argument;
  4270. zend_class_entry *ce, *interface_ce;
  4271. zval *interface;
  4272. GET_REFLECTION_OBJECT_PTR(ce);
  4273. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &interface) == FAILURE) {
  4274. RETURN_THROWS();
  4275. }
  4276. switch (Z_TYPE_P(interface)) {
  4277. case IS_STRING:
  4278. if ((interface_ce = zend_lookup_class(Z_STR_P(interface))) == NULL) {
  4279. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4280. "Interface %s does not exist", Z_STRVAL_P(interface));
  4281. RETURN_THROWS();
  4282. }
  4283. break;
  4284. case IS_OBJECT:
  4285. if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr)) {
  4286. argument = Z_REFLECTION_P(interface);
  4287. if (argument->ptr == NULL) {
  4288. zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
  4289. RETURN_THROWS();
  4290. }
  4291. interface_ce = argument->ptr;
  4292. break;
  4293. }
  4294. /* no break */
  4295. default:
  4296. zend_argument_error(reflection_exception_ptr, 1, "must be of type ReflectionClass|string, %s given", zend_zval_type_name(interface));
  4297. RETURN_THROWS();
  4298. }
  4299. if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
  4300. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4301. "%s is not an interface", ZSTR_VAL(interface_ce->name));
  4302. RETURN_THROWS();
  4303. }
  4304. RETURN_BOOL(instanceof_function(ce, interface_ce));
  4305. }
  4306. /* }}} */
  4307. /* {{{ proto public bool ReflectionClass::isIterable()
  4308. Returns whether this class is iterable (can be used inside foreach) */
  4309. ZEND_METHOD(ReflectionClass, isIterable)
  4310. {
  4311. reflection_object *intern;
  4312. zend_class_entry *ce;
  4313. if (zend_parse_parameters_none() == FAILURE) {
  4314. RETURN_THROWS();
  4315. }
  4316. GET_REFLECTION_OBJECT_PTR(ce);
  4317. if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS |
  4318. ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
  4319. RETURN_FALSE;
  4320. }
  4321. RETURN_BOOL(ce->get_iterator || instanceof_function(ce, zend_ce_traversable));
  4322. }
  4323. /* }}} */
  4324. /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension()
  4325. Returns NULL or the extension the class belongs to */
  4326. ZEND_METHOD(ReflectionClass, getExtension)
  4327. {
  4328. reflection_object *intern;
  4329. zend_class_entry *ce;
  4330. if (zend_parse_parameters_none() == FAILURE) {
  4331. RETURN_THROWS();
  4332. }
  4333. GET_REFLECTION_OBJECT_PTR(ce);
  4334. if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
  4335. reflection_extension_factory(return_value, ce->info.internal.module->name);
  4336. }
  4337. }
  4338. /* }}} */
  4339. /* {{{ proto public string|false ReflectionClass::getExtensionName()
  4340. Returns false or the name of the extension the class belongs to */
  4341. ZEND_METHOD(ReflectionClass, getExtensionName)
  4342. {
  4343. reflection_object *intern;
  4344. zend_class_entry *ce;
  4345. if (zend_parse_parameters_none() == FAILURE) {
  4346. RETURN_THROWS();
  4347. }
  4348. GET_REFLECTION_OBJECT_PTR(ce);
  4349. if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
  4350. RETURN_STRING(ce->info.internal.module->name);
  4351. } else {
  4352. RETURN_FALSE;
  4353. }
  4354. }
  4355. /* }}} */
  4356. /* {{{ proto public bool ReflectionClass::inNamespace()
  4357. Returns whether this class is defined in namespace */
  4358. ZEND_METHOD(ReflectionClass, inNamespace)
  4359. {
  4360. reflection_object *intern;
  4361. zend_class_entry *ce;
  4362. if (zend_parse_parameters_none() == FAILURE) {
  4363. RETURN_THROWS();
  4364. }
  4365. GET_REFLECTION_OBJECT_PTR(ce);
  4366. zend_string *name = ce->name;
  4367. const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  4368. RETURN_BOOL(backslash && backslash > ZSTR_VAL(name));
  4369. }
  4370. /* }}} */
  4371. /* {{{ proto public string ReflectionClass::getNamespaceName()
  4372. Returns the name of namespace where this class is defined */
  4373. ZEND_METHOD(ReflectionClass, getNamespaceName)
  4374. {
  4375. reflection_object *intern;
  4376. zend_class_entry *ce;
  4377. if (zend_parse_parameters_none() == FAILURE) {
  4378. RETURN_THROWS();
  4379. }
  4380. GET_REFLECTION_OBJECT_PTR(ce);
  4381. zend_string *name = ce->name;
  4382. const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  4383. if (backslash && backslash > ZSTR_VAL(name)) {
  4384. RETURN_STRINGL(ZSTR_VAL(name), backslash - ZSTR_VAL(name));
  4385. }
  4386. RETURN_EMPTY_STRING();
  4387. }
  4388. /* }}} */
  4389. /* {{{ proto public string ReflectionClass::getShortName()
  4390. Returns the short name of the class (without namespace part) */
  4391. ZEND_METHOD(ReflectionClass, getShortName)
  4392. {
  4393. reflection_object *intern;
  4394. zend_class_entry *ce;
  4395. if (zend_parse_parameters_none() == FAILURE) {
  4396. RETURN_THROWS();
  4397. }
  4398. GET_REFLECTION_OBJECT_PTR(ce);
  4399. zend_string *name = ce->name;
  4400. const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
  4401. if (backslash && backslash > ZSTR_VAL(name)) {
  4402. RETURN_STRINGL(backslash + 1, ZSTR_LEN(name) - (backslash - ZSTR_VAL(name) + 1));
  4403. }
  4404. RETURN_STR_COPY(name);
  4405. }
  4406. /* }}} */
  4407. /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException
  4408. Constructor. Takes an instance as an argument */
  4409. ZEND_METHOD(ReflectionObject, __construct)
  4410. {
  4411. reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  4412. }
  4413. /* }}} */
  4414. /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
  4415. Constructor. Throws an Exception in case the given property does not exist */
  4416. ZEND_METHOD(ReflectionProperty, __construct)
  4417. {
  4418. zval *classname;
  4419. zend_string *name;
  4420. int dynam_prop = 0;
  4421. zval *object;
  4422. reflection_object *intern;
  4423. zend_class_entry *ce;
  4424. zend_property_info *property_info = NULL;
  4425. property_reference *reference;
  4426. if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &classname, &name) == FAILURE) {
  4427. RETURN_THROWS();
  4428. }
  4429. object = ZEND_THIS;
  4430. intern = Z_REFLECTION_P(object);
  4431. /* Find the class entry */
  4432. switch (Z_TYPE_P(classname)) {
  4433. case IS_STRING:
  4434. if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
  4435. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4436. "Class %s does not exist", Z_STRVAL_P(classname));
  4437. RETURN_THROWS();
  4438. }
  4439. break;
  4440. case IS_OBJECT:
  4441. ce = Z_OBJCE_P(classname);
  4442. break;
  4443. default:
  4444. zend_argument_error(reflection_exception_ptr, 1, "must be of type object|string, %s given", zend_zval_type_name(classname));
  4445. RETURN_THROWS();
  4446. }
  4447. property_info = zend_hash_find_ptr(&ce->properties_info, name);
  4448. if (property_info == NULL
  4449. || ((property_info->flags & ZEND_ACC_PRIVATE)
  4450. && property_info->ce != ce)) {
  4451. /* Check for dynamic properties */
  4452. if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT) {
  4453. if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(Z_OBJ_P(classname)), name)) {
  4454. dynam_prop = 1;
  4455. }
  4456. }
  4457. if (dynam_prop == 0) {
  4458. zend_throw_exception_ex(reflection_exception_ptr, 0, "Property %s::$%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
  4459. RETURN_THROWS();
  4460. }
  4461. }
  4462. ZVAL_STR_COPY(reflection_prop_name(object), name);
  4463. if (dynam_prop == 0) {
  4464. ZVAL_STR_COPY(reflection_prop_class(object), property_info->ce->name);
  4465. } else {
  4466. ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
  4467. }
  4468. reference = (property_reference*) emalloc(sizeof(property_reference));
  4469. reference->prop = dynam_prop ? NULL : property_info;
  4470. reference->unmangled_name = zend_string_copy(name);
  4471. intern->ptr = reference;
  4472. intern->ref_type = REF_TYPE_PROPERTY;
  4473. intern->ce = ce;
  4474. intern->ignore_visibility = 0;
  4475. }
  4476. /* }}} */
  4477. /* {{{ proto public string ReflectionProperty::__toString()
  4478. Returns a string representation */
  4479. ZEND_METHOD(ReflectionProperty, __toString)
  4480. {
  4481. reflection_object *intern;
  4482. property_reference *ref;
  4483. smart_str str = {0};
  4484. if (zend_parse_parameters_none() == FAILURE) {
  4485. RETURN_THROWS();
  4486. }
  4487. GET_REFLECTION_OBJECT_PTR(ref);
  4488. _property_string(&str, ref->prop, ZSTR_VAL(ref->unmangled_name), "");
  4489. RETURN_STR(smart_str_extract(&str));
  4490. }
  4491. /* }}} */
  4492. /* {{{ proto public string ReflectionProperty::getName()
  4493. Returns the class' name */
  4494. ZEND_METHOD(ReflectionProperty, getName)
  4495. {
  4496. reflection_object *intern;
  4497. property_reference *ref;
  4498. if (zend_parse_parameters_none() == FAILURE) {
  4499. RETURN_THROWS();
  4500. }
  4501. GET_REFLECTION_OBJECT_PTR(ref);
  4502. RETURN_STR_COPY(ref->unmangled_name);
  4503. }
  4504. /* }}} */
  4505. static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
  4506. {
  4507. reflection_object *intern;
  4508. property_reference *ref;
  4509. if (zend_parse_parameters_none() == FAILURE) {
  4510. RETURN_THROWS();
  4511. }
  4512. GET_REFLECTION_OBJECT_PTR(ref);
  4513. RETURN_BOOL(prop_get_flags(ref) & mask);
  4514. }
  4515. /* }}} */
  4516. /* {{{ proto public bool ReflectionProperty::isPublic()
  4517. Returns whether this property is public */
  4518. ZEND_METHOD(ReflectionProperty, isPublic)
  4519. {
  4520. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
  4521. }
  4522. /* }}} */
  4523. /* {{{ proto public bool ReflectionProperty::isPrivate()
  4524. Returns whether this property is private */
  4525. ZEND_METHOD(ReflectionProperty, isPrivate)
  4526. {
  4527. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
  4528. }
  4529. /* }}} */
  4530. /* {{{ proto public bool ReflectionProperty::isProtected()
  4531. Returns whether this property is protected */
  4532. ZEND_METHOD(ReflectionProperty, isProtected)
  4533. {
  4534. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
  4535. }
  4536. /* }}} */
  4537. /* {{{ proto public bool ReflectionProperty::isStatic()
  4538. Returns whether this property is static */
  4539. ZEND_METHOD(ReflectionProperty, isStatic)
  4540. {
  4541. _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
  4542. }
  4543. /* }}} */
  4544. /* {{{ proto public bool ReflectionProperty::isDefault()
  4545. Returns whether this property is default (declared at compilation time). */
  4546. ZEND_METHOD(ReflectionProperty, isDefault)
  4547. {
  4548. reflection_object *intern;
  4549. property_reference *ref;
  4550. if (zend_parse_parameters_none() == FAILURE) {
  4551. RETURN_THROWS();
  4552. }
  4553. GET_REFLECTION_OBJECT_PTR(ref);
  4554. RETURN_BOOL(ref->prop != NULL);
  4555. }
  4556. /* }}} */
  4557. /* {{{ proto public int ReflectionProperty::getModifiers()
  4558. Returns a bitfield of the access modifiers for this property */
  4559. ZEND_METHOD(ReflectionProperty, getModifiers)
  4560. {
  4561. reflection_object *intern;
  4562. property_reference *ref;
  4563. uint32_t keep_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
  4564. if (zend_parse_parameters_none() == FAILURE) {
  4565. RETURN_THROWS();
  4566. }
  4567. GET_REFLECTION_OBJECT_PTR(ref);
  4568. RETURN_LONG(prop_get_flags(ref) & keep_flags);
  4569. }
  4570. /* }}} */
  4571. /* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
  4572. Returns this property's value */
  4573. ZEND_METHOD(ReflectionProperty, getValue)
  4574. {
  4575. reflection_object *intern;
  4576. property_reference *ref;
  4577. zval *object = NULL;
  4578. zval *member_p = NULL;
  4579. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) {
  4580. RETURN_THROWS();
  4581. }
  4582. GET_REFLECTION_OBJECT_PTR(ref);
  4583. if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
  4584. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4585. "Cannot access non-public member %s::$%s",
  4586. ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->unmangled_name));
  4587. RETURN_THROWS();
  4588. }
  4589. if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
  4590. member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 0);
  4591. if (member_p) {
  4592. ZVAL_COPY_DEREF(return_value, member_p);
  4593. }
  4594. } else {
  4595. zval rv;
  4596. if (!object) {
  4597. zend_argument_type_error(1, "must be provided for instance properties");
  4598. RETURN_THROWS();
  4599. }
  4600. /* TODO: Should this always use intern->ce? */
  4601. if (!instanceof_function(Z_OBJCE_P(object), ref->prop ? ref->prop->ce : intern->ce)) {
  4602. _DO_THROW("Given object is not an instance of the class this property was declared in");
  4603. RETURN_THROWS();
  4604. }
  4605. member_p = zend_read_property_ex(intern->ce, object, ref->unmangled_name, 0, &rv);
  4606. if (member_p != &rv) {
  4607. ZVAL_COPY_DEREF(return_value, member_p);
  4608. } else {
  4609. if (Z_ISREF_P(member_p)) {
  4610. zend_unwrap_reference(member_p);
  4611. }
  4612. ZVAL_COPY_VALUE(return_value, member_p);
  4613. }
  4614. }
  4615. }
  4616. /* }}} */
  4617. /* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
  4618. Sets this property's value */
  4619. ZEND_METHOD(ReflectionProperty, setValue)
  4620. {
  4621. reflection_object *intern;
  4622. property_reference *ref;
  4623. zval *object;
  4624. zval *value;
  4625. zval *tmp;
  4626. GET_REFLECTION_OBJECT_PTR(ref);
  4627. if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
  4628. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4629. "Cannot access non-public member %s::$%s",
  4630. ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->unmangled_name));
  4631. RETURN_THROWS();
  4632. }
  4633. if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
  4634. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
  4635. if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
  4636. RETURN_THROWS();
  4637. }
  4638. }
  4639. zend_update_static_property_ex(intern->ce, ref->unmangled_name, value);
  4640. } else {
  4641. if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
  4642. RETURN_THROWS();
  4643. }
  4644. zend_update_property_ex(intern->ce, object, ref->unmangled_name, value);
  4645. }
  4646. }
  4647. /* }}} */
  4648. /* {{{ proto public mixed ReflectionProperty::isInitialized([stdclass object])
  4649. Returns this property's value */
  4650. ZEND_METHOD(ReflectionProperty, isInitialized)
  4651. {
  4652. reflection_object *intern;
  4653. property_reference *ref;
  4654. zval *object = NULL;
  4655. zval *member_p = NULL;
  4656. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &object) == FAILURE) {
  4657. RETURN_THROWS();
  4658. }
  4659. GET_REFLECTION_OBJECT_PTR(ref);
  4660. if (!(prop_get_flags(ref) & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
  4661. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4662. "Cannot access non-public member %s::$%s",
  4663. ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->unmangled_name));
  4664. RETURN_THROWS();
  4665. }
  4666. if (prop_get_flags(ref) & ZEND_ACC_STATIC) {
  4667. member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 1);
  4668. if (member_p) {
  4669. RETURN_BOOL(!Z_ISUNDEF_P(member_p));
  4670. }
  4671. RETURN_FALSE;
  4672. } else {
  4673. zend_class_entry *old_scope;
  4674. int retval;
  4675. if (!object) {
  4676. zend_argument_type_error(1, "must be provided for instance properties");
  4677. RETURN_THROWS();
  4678. }
  4679. /* TODO: Should this always use intern->ce? */
  4680. if (!instanceof_function(Z_OBJCE_P(object), ref->prop ? ref->prop->ce : intern->ce)) {
  4681. _DO_THROW("Given object is not an instance of the class this property was declared in");
  4682. RETURN_THROWS();
  4683. }
  4684. old_scope = EG(fake_scope);
  4685. EG(fake_scope) = intern->ce;
  4686. retval = Z_OBJ_HT_P(object)->has_property(Z_OBJ_P(object), ref->unmangled_name, ZEND_PROPERTY_EXISTS, NULL);
  4687. EG(fake_scope) = old_scope;
  4688. RETVAL_BOOL(retval);
  4689. }
  4690. }
  4691. /* }}} */
  4692. /* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
  4693. Get the declaring class */
  4694. ZEND_METHOD(ReflectionProperty, getDeclaringClass)
  4695. {
  4696. reflection_object *intern;
  4697. property_reference *ref;
  4698. zend_class_entry *ce;
  4699. if (zend_parse_parameters_none() == FAILURE) {
  4700. RETURN_THROWS();
  4701. }
  4702. GET_REFLECTION_OBJECT_PTR(ref);
  4703. ce = ref->prop ? ref->prop->ce : intern->ce;
  4704. zend_reflection_class_factory(ce, return_value);
  4705. }
  4706. /* }}} */
  4707. /* {{{ proto public string ReflectionProperty::getDocComment()
  4708. Returns the doc comment for this property */
  4709. ZEND_METHOD(ReflectionProperty, getDocComment)
  4710. {
  4711. reflection_object *intern;
  4712. property_reference *ref;
  4713. if (zend_parse_parameters_none() == FAILURE) {
  4714. RETURN_THROWS();
  4715. }
  4716. GET_REFLECTION_OBJECT_PTR(ref);
  4717. if (ref->prop && ref->prop->doc_comment) {
  4718. RETURN_STR_COPY(ref->prop->doc_comment);
  4719. }
  4720. RETURN_FALSE;
  4721. }
  4722. /* }}} */
  4723. /* {{{ proto public int ReflectionProperty::setAccessible(bool visible)
  4724. Sets whether non-public properties can be requested */
  4725. ZEND_METHOD(ReflectionProperty, setAccessible)
  4726. {
  4727. reflection_object *intern;
  4728. zend_bool visible;
  4729. if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
  4730. RETURN_THROWS();
  4731. }
  4732. intern = Z_REFLECTION_P(ZEND_THIS);
  4733. intern->ignore_visibility = visible;
  4734. }
  4735. /* }}} */
  4736. /* {{{ proto public ReflectionType ReflectionProperty::getType()
  4737. Returns the type associated with the property */
  4738. ZEND_METHOD(ReflectionProperty, getType)
  4739. {
  4740. reflection_object *intern;
  4741. property_reference *ref;
  4742. if (zend_parse_parameters_none() == FAILURE) {
  4743. RETURN_THROWS();
  4744. }
  4745. GET_REFLECTION_OBJECT_PTR(ref);
  4746. if (!ref->prop || !ZEND_TYPE_IS_SET(ref->prop->type)) {
  4747. RETURN_NULL();
  4748. }
  4749. reflection_type_factory(ref->prop->type, return_value, 1);
  4750. }
  4751. /* }}} */
  4752. /* {{{ proto public bool ReflectionProperty::hasType()
  4753. Returns whether property has a type */
  4754. ZEND_METHOD(ReflectionProperty, hasType)
  4755. {
  4756. reflection_object *intern;
  4757. property_reference *ref;
  4758. if (zend_parse_parameters_none() == FAILURE) {
  4759. RETURN_THROWS();
  4760. }
  4761. GET_REFLECTION_OBJECT_PTR(ref);
  4762. RETVAL_BOOL(ref->prop && ZEND_TYPE_IS_SET(ref->prop->type));
  4763. }
  4764. /* }}} */
  4765. /* {{{ proto public bool ReflectionProperty::hasDefaultValue()
  4766. Returns whether property has a default value */
  4767. ZEND_METHOD(ReflectionProperty, hasDefaultValue)
  4768. {
  4769. reflection_object *intern;
  4770. property_reference *ref;
  4771. zend_property_info *prop_info;
  4772. zval *prop;
  4773. if (zend_parse_parameters_none() == FAILURE) {
  4774. RETURN_THROWS();
  4775. }
  4776. GET_REFLECTION_OBJECT_PTR(ref);
  4777. prop_info = ref->prop;
  4778. if (prop_info == NULL) {
  4779. RETURN_FALSE;
  4780. }
  4781. prop = property_get_default(prop_info);
  4782. RETURN_BOOL(!Z_ISUNDEF_P(prop));
  4783. }
  4784. /* }}} */
  4785. /* {{{ proto public mixed ReflectionProperty::getDefaultValue()
  4786. Returns the default value of a property */
  4787. ZEND_METHOD(ReflectionProperty, getDefaultValue)
  4788. {
  4789. reflection_object *intern;
  4790. property_reference *ref;
  4791. zend_property_info *prop_info;
  4792. zval *prop;
  4793. if (zend_parse_parameters_none() == FAILURE) {
  4794. RETURN_THROWS();
  4795. }
  4796. GET_REFLECTION_OBJECT_PTR(ref);
  4797. prop_info = ref->prop;
  4798. if (prop_info == NULL) {
  4799. return; // throw exception?
  4800. }
  4801. prop = property_get_default(prop_info);
  4802. if (Z_ISUNDEF_P(prop)) {
  4803. return;
  4804. }
  4805. /* copy: enforce read only access */
  4806. ZVAL_DEREF(prop);
  4807. ZVAL_COPY_OR_DUP(return_value, prop);
  4808. /* this is necessary to make it able to work with default array
  4809. * properties, returned to user */
  4810. if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
  4811. if (UNEXPECTED(zval_update_constant_ex(return_value, prop_info->ce) != SUCCESS)) {
  4812. RETURN_THROWS();
  4813. }
  4814. }
  4815. }
  4816. /* }}} */
  4817. /* {{{ proto public void ReflectionExtension::__construct(string name)
  4818. Constructor. Throws an Exception in case the given extension does not exist */
  4819. ZEND_METHOD(ReflectionExtension, __construct)
  4820. {
  4821. zval *object;
  4822. char *lcname;
  4823. reflection_object *intern;
  4824. zend_module_entry *module;
  4825. char *name_str;
  4826. size_t name_len;
  4827. ALLOCA_FLAG(use_heap)
  4828. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
  4829. RETURN_THROWS();
  4830. }
  4831. object = ZEND_THIS;
  4832. intern = Z_REFLECTION_P(object);
  4833. lcname = do_alloca(name_len + 1, use_heap);
  4834. zend_str_tolower_copy(lcname, name_str, name_len);
  4835. if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) {
  4836. free_alloca(lcname, use_heap);
  4837. zend_throw_exception_ex(reflection_exception_ptr, 0,
  4838. "Extension %s does not exist", name_str);
  4839. RETURN_THROWS();
  4840. }
  4841. free_alloca(lcname, use_heap);
  4842. ZVAL_STRING(reflection_prop_name(object), module->name);
  4843. intern->ptr = module;
  4844. intern->ref_type = REF_TYPE_OTHER;
  4845. intern->ce = NULL;
  4846. }
  4847. /* }}} */
  4848. /* {{{ proto public string ReflectionExtension::__toString()
  4849. Returns a string representation */
  4850. ZEND_METHOD(ReflectionExtension, __toString)
  4851. {
  4852. reflection_object *intern;
  4853. zend_module_entry *module;
  4854. smart_str str = {0};
  4855. if (zend_parse_parameters_none() == FAILURE) {
  4856. RETURN_THROWS();
  4857. }
  4858. GET_REFLECTION_OBJECT_PTR(module);
  4859. _extension_string(&str, module, "");
  4860. RETURN_STR(smart_str_extract(&str));
  4861. }
  4862. /* }}} */
  4863. /* {{{ proto public string ReflectionExtension::getName()
  4864. Returns this extension's name */
  4865. ZEND_METHOD(ReflectionExtension, getName)
  4866. {
  4867. reflection_object *intern;
  4868. zend_module_entry *module;
  4869. if (zend_parse_parameters_none() == FAILURE) {
  4870. RETURN_THROWS();
  4871. }
  4872. GET_REFLECTION_OBJECT_PTR(module);
  4873. RETURN_STRING(module->name);
  4874. }
  4875. /* }}} */
  4876. /* {{{ proto public string ReflectionExtension::getVersion()
  4877. Returns this extension's version */
  4878. ZEND_METHOD(ReflectionExtension, getVersion)
  4879. {
  4880. reflection_object *intern;
  4881. zend_module_entry *module;
  4882. if (zend_parse_parameters_none() == FAILURE) {
  4883. RETURN_THROWS();
  4884. }
  4885. GET_REFLECTION_OBJECT_PTR(module);
  4886. /* An extension does not necessarily have a version number */
  4887. if (module->version == NO_VERSION_YET) {
  4888. RETURN_NULL();
  4889. } else {
  4890. RETURN_STRING(module->version);
  4891. }
  4892. }
  4893. /* }}} */
  4894. /* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
  4895. Returns an array of this extension's functions */
  4896. ZEND_METHOD(ReflectionExtension, getFunctions)
  4897. {
  4898. reflection_object *intern;
  4899. zend_module_entry *module;
  4900. zval function;
  4901. zend_function *fptr;
  4902. if (zend_parse_parameters_none() == FAILURE) {
  4903. RETURN_THROWS();
  4904. }
  4905. GET_REFLECTION_OBJECT_PTR(module);
  4906. array_init(return_value);
  4907. ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
  4908. if (fptr->common.type==ZEND_INTERNAL_FUNCTION
  4909. && fptr->internal_function.module == module) {
  4910. reflection_function_factory(fptr, NULL, &function);
  4911. zend_hash_update(Z_ARRVAL_P(return_value), fptr->common.function_name, &function);
  4912. }
  4913. } ZEND_HASH_FOREACH_END();
  4914. }
  4915. /* }}} */
  4916. /* {{{ proto public array ReflectionExtension::getConstants()
  4917. Returns an associative array containing this extension's constants and their values */
  4918. ZEND_METHOD(ReflectionExtension, getConstants)
  4919. {
  4920. reflection_object *intern;
  4921. zend_module_entry *module;
  4922. zend_constant *constant;
  4923. if (zend_parse_parameters_none() == FAILURE) {
  4924. RETURN_THROWS();
  4925. }
  4926. GET_REFLECTION_OBJECT_PTR(module);
  4927. array_init(return_value);
  4928. ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) {
  4929. if (module->module_number == ZEND_CONSTANT_MODULE_NUMBER(constant)) {
  4930. zval const_val;
  4931. ZVAL_COPY_OR_DUP(&const_val, &constant->value);
  4932. zend_hash_update(Z_ARRVAL_P(return_value), constant->name, &const_val);
  4933. }
  4934. } ZEND_HASH_FOREACH_END();
  4935. }
  4936. /* }}} */
  4937. /* {{{ _addinientry */
  4938. static void _addinientry(zend_ini_entry *ini_entry, zval *retval, int number)
  4939. {
  4940. if (number == ini_entry->module_number) {
  4941. zval zv;
  4942. if (ini_entry->value) {
  4943. ZVAL_STR_COPY(&zv, ini_entry->value);
  4944. } else {
  4945. ZVAL_NULL(&zv);
  4946. }
  4947. zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &zv);
  4948. }
  4949. }
  4950. /* }}} */
  4951. /* {{{ proto public array ReflectionExtension::getINIEntries()
  4952. Returns an associative array containing this extension's INI entries and their values */
  4953. ZEND_METHOD(ReflectionExtension, getINIEntries)
  4954. {
  4955. reflection_object *intern;
  4956. zend_module_entry *module;
  4957. zend_ini_entry *ini_entry;
  4958. if (zend_parse_parameters_none() == FAILURE) {
  4959. RETURN_THROWS();
  4960. }
  4961. GET_REFLECTION_OBJECT_PTR(module);
  4962. array_init(return_value);
  4963. ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) {
  4964. _addinientry(ini_entry, return_value, module->module_number);
  4965. } ZEND_HASH_FOREACH_END();
  4966. }
  4967. /* }}} */
  4968. /* {{{ add_extension_class */
  4969. static void add_extension_class(zend_class_entry *ce, zend_string *key, zval *class_array, zend_module_entry *module, zend_bool add_reflection_class)
  4970. {
  4971. if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
  4972. zend_string *name;
  4973. if (!zend_string_equals_ci(ce->name, key)) {
  4974. /* This is a class alias, use alias name */
  4975. name = key;
  4976. } else {
  4977. /* Use class name */
  4978. name = ce->name;
  4979. }
  4980. if (add_reflection_class) {
  4981. zval zclass;
  4982. zend_reflection_class_factory(ce, &zclass);
  4983. zend_hash_update(Z_ARRVAL_P(class_array), name, &zclass);
  4984. } else {
  4985. add_next_index_str(class_array, zend_string_copy(name));
  4986. }
  4987. }
  4988. }
  4989. /* }}} */
  4990. /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses()
  4991. Returns an array containing ReflectionClass objects for all classes of this extension */
  4992. ZEND_METHOD(ReflectionExtension, getClasses)
  4993. {
  4994. reflection_object *intern;
  4995. zend_module_entry *module;
  4996. zend_string *key;
  4997. zend_class_entry *ce;
  4998. if (zend_parse_parameters_none() == FAILURE) {
  4999. RETURN_THROWS();
  5000. }
  5001. GET_REFLECTION_OBJECT_PTR(module);
  5002. array_init(return_value);
  5003. ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
  5004. add_extension_class(ce, key, return_value, module, 1);
  5005. } ZEND_HASH_FOREACH_END();
  5006. }
  5007. /* }}} */
  5008. /* {{{ proto public array ReflectionExtension::getClassNames()
  5009. Returns an array containing all names of all classes of this extension */
  5010. ZEND_METHOD(ReflectionExtension, getClassNames)
  5011. {
  5012. reflection_object *intern;
  5013. zend_module_entry *module;
  5014. zend_string *key;
  5015. zend_class_entry *ce;
  5016. if (zend_parse_parameters_none() == FAILURE) {
  5017. RETURN_THROWS();
  5018. }
  5019. GET_REFLECTION_OBJECT_PTR(module);
  5020. array_init(return_value);
  5021. ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
  5022. add_extension_class(ce, key, return_value, module, 0);
  5023. } ZEND_HASH_FOREACH_END();
  5024. }
  5025. /* }}} */
  5026. /* {{{ proto public array ReflectionExtension::getDependencies()
  5027. Returns an array containing all names of all extensions this extension depends on */
  5028. ZEND_METHOD(ReflectionExtension, getDependencies)
  5029. {
  5030. reflection_object *intern;
  5031. zend_module_entry *module;
  5032. const zend_module_dep *dep;
  5033. if (zend_parse_parameters_none() == FAILURE) {
  5034. RETURN_THROWS();
  5035. }
  5036. GET_REFLECTION_OBJECT_PTR(module);
  5037. dep = module->deps;
  5038. if (!dep)
  5039. {
  5040. RETURN_EMPTY_ARRAY();
  5041. }
  5042. array_init(return_value);
  5043. while(dep->name) {
  5044. zend_string *relation;
  5045. char *rel_type;
  5046. size_t len = 0;
  5047. switch(dep->type) {
  5048. case MODULE_DEP_REQUIRED:
  5049. rel_type = "Required";
  5050. len += sizeof("Required") - 1;
  5051. break;
  5052. case MODULE_DEP_CONFLICTS:
  5053. rel_type = "Conflicts";
  5054. len += sizeof("Conflicts") - 1;
  5055. break;
  5056. case MODULE_DEP_OPTIONAL:
  5057. rel_type = "Optional";
  5058. len += sizeof("Optional") - 1;
  5059. break;
  5060. default:
  5061. rel_type = "Error"; /* shouldn't happen */
  5062. len += sizeof("Error") - 1;
  5063. break;
  5064. }
  5065. if (dep->rel) {
  5066. len += strlen(dep->rel) + 1;
  5067. }
  5068. if (dep->version) {
  5069. len += strlen(dep->version) + 1;
  5070. }
  5071. relation = zend_string_alloc(len, 0);
  5072. snprintf(ZSTR_VAL(relation), ZSTR_LEN(relation) + 1, "%s%s%s%s%s",
  5073. rel_type,
  5074. dep->rel ? " " : "",
  5075. dep->rel ? dep->rel : "",
  5076. dep->version ? " " : "",
  5077. dep->version ? dep->version : "");
  5078. add_assoc_str(return_value, dep->name, relation);
  5079. dep++;
  5080. }
  5081. }
  5082. /* }}} */
  5083. /* {{{ proto public void ReflectionExtension::info()
  5084. Prints phpinfo block for the extension */
  5085. ZEND_METHOD(ReflectionExtension, info)
  5086. {
  5087. reflection_object *intern;
  5088. zend_module_entry *module;
  5089. if (zend_parse_parameters_none() == FAILURE) {
  5090. RETURN_THROWS();
  5091. }
  5092. GET_REFLECTION_OBJECT_PTR(module);
  5093. php_info_print_module(module);
  5094. }
  5095. /* }}} */
  5096. /* {{{ proto public bool ReflectionExtension::isPersistent()
  5097. Returns whether this extension is persistent */
  5098. ZEND_METHOD(ReflectionExtension, isPersistent)
  5099. {
  5100. reflection_object *intern;
  5101. zend_module_entry *module;
  5102. if (zend_parse_parameters_none() == FAILURE) {
  5103. RETURN_THROWS();
  5104. }
  5105. GET_REFLECTION_OBJECT_PTR(module);
  5106. RETURN_BOOL(module->type == MODULE_PERSISTENT);
  5107. }
  5108. /* }}} */
  5109. /* {{{ proto public bool ReflectionExtension::isTemporary()
  5110. Returns whether this extension is temporary */
  5111. ZEND_METHOD(ReflectionExtension, isTemporary)
  5112. {
  5113. reflection_object *intern;
  5114. zend_module_entry *module;
  5115. if (zend_parse_parameters_none() == FAILURE) {
  5116. RETURN_THROWS();
  5117. }
  5118. GET_REFLECTION_OBJECT_PTR(module);
  5119. RETURN_BOOL(module->type == MODULE_TEMPORARY);
  5120. }
  5121. /* }}} */
  5122. /* {{{ proto public void ReflectionZendExtension::__construct(string name)
  5123. Constructor. Throws an Exception in case the given Zend extension does not exist */
  5124. ZEND_METHOD(ReflectionZendExtension, __construct)
  5125. {
  5126. zval *object;
  5127. reflection_object *intern;
  5128. zend_extension *extension;
  5129. char *name_str;
  5130. size_t name_len;
  5131. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
  5132. RETURN_THROWS();
  5133. }
  5134. object = ZEND_THIS;
  5135. intern = Z_REFLECTION_P(object);
  5136. extension = zend_get_extension(name_str);
  5137. if (!extension) {
  5138. zend_throw_exception_ex(reflection_exception_ptr, 0,
  5139. "Zend Extension %s does not exist", name_str);
  5140. RETURN_THROWS();
  5141. }
  5142. ZVAL_STRING(reflection_prop_name(object), extension->name);
  5143. intern->ptr = extension;
  5144. intern->ref_type = REF_TYPE_OTHER;
  5145. intern->ce = NULL;
  5146. }
  5147. /* }}} */
  5148. /* {{{ proto public string ReflectionZendExtension::__toString()
  5149. Returns a string representation */
  5150. ZEND_METHOD(ReflectionZendExtension, __toString)
  5151. {
  5152. reflection_object *intern;
  5153. zend_extension *extension;
  5154. smart_str str = {0};
  5155. if (zend_parse_parameters_none() == FAILURE) {
  5156. RETURN_THROWS();
  5157. }
  5158. GET_REFLECTION_OBJECT_PTR(extension);
  5159. _zend_extension_string(&str, extension, "");
  5160. RETURN_STR(smart_str_extract(&str));
  5161. }
  5162. /* }}} */
  5163. /* {{{ proto public string ReflectionZendExtension::getName()
  5164. Returns the name of this Zend extension */
  5165. ZEND_METHOD(ReflectionZendExtension, getName)
  5166. {
  5167. reflection_object *intern;
  5168. zend_extension *extension;
  5169. if (zend_parse_parameters_none() == FAILURE) {
  5170. RETURN_THROWS();
  5171. }
  5172. GET_REFLECTION_OBJECT_PTR(extension);
  5173. RETURN_STRING(extension->name);
  5174. }
  5175. /* }}} */
  5176. /* {{{ proto public string ReflectionZendExtension::getVersion()
  5177. Returns the version information of this Zend extension */
  5178. ZEND_METHOD(ReflectionZendExtension, getVersion)
  5179. {
  5180. reflection_object *intern;
  5181. zend_extension *extension;
  5182. if (zend_parse_parameters_none() == FAILURE) {
  5183. RETURN_THROWS();
  5184. }
  5185. GET_REFLECTION_OBJECT_PTR(extension);
  5186. if (extension->version) {
  5187. RETURN_STRING(extension->version);
  5188. } else {
  5189. RETURN_EMPTY_STRING();
  5190. }
  5191. }
  5192. /* }}} */
  5193. /* {{{ proto public void ReflectionZendExtension::getAuthor()
  5194. * Returns the name of this Zend extension's author */
  5195. ZEND_METHOD(ReflectionZendExtension, getAuthor)
  5196. {
  5197. reflection_object *intern;
  5198. zend_extension *extension;
  5199. if (zend_parse_parameters_none() == FAILURE) {
  5200. RETURN_THROWS();
  5201. }
  5202. GET_REFLECTION_OBJECT_PTR(extension);
  5203. if (extension->author) {
  5204. RETURN_STRING(extension->author);
  5205. } else {
  5206. RETURN_EMPTY_STRING();
  5207. }
  5208. }
  5209. /* }}} */
  5210. /* {{{ proto public void ReflectionZendExtension::getURL()
  5211. Returns this Zend extension's URL*/
  5212. ZEND_METHOD(ReflectionZendExtension, getURL)
  5213. {
  5214. reflection_object *intern;
  5215. zend_extension *extension;
  5216. if (zend_parse_parameters_none() == FAILURE) {
  5217. RETURN_THROWS();
  5218. }
  5219. GET_REFLECTION_OBJECT_PTR(extension);
  5220. if (extension->URL) {
  5221. RETURN_STRING(extension->URL);
  5222. } else {
  5223. RETURN_EMPTY_STRING();
  5224. }
  5225. }
  5226. /* }}} */
  5227. /* {{{ proto public void ReflectionZendExtension::getCopyright()
  5228. Returns this Zend extension's copyright information */
  5229. ZEND_METHOD(ReflectionZendExtension, getCopyright)
  5230. {
  5231. reflection_object *intern;
  5232. zend_extension *extension;
  5233. if (zend_parse_parameters_none() == FAILURE) {
  5234. RETURN_THROWS();
  5235. }
  5236. GET_REFLECTION_OBJECT_PTR(extension);
  5237. if (extension->copyright) {
  5238. RETURN_STRING(extension->copyright);
  5239. } else {
  5240. RETURN_EMPTY_STRING();
  5241. }
  5242. }
  5243. /* }}} */
  5244. /* {{{ proto public ReflectionReference::__construct()
  5245. * Dummy constructor -- always throws ReflectionExceptions. */
  5246. ZEND_METHOD(ReflectionReference, __construct)
  5247. {
  5248. _DO_THROW(
  5249. "Cannot directly instantiate ReflectionReference. "
  5250. "Use ReflectionReference::fromArrayElement() instead"
  5251. );
  5252. }
  5253. /* }}} */
  5254. static zend_bool is_ignorable_reference(HashTable *ht, zval *ref) {
  5255. if (Z_REFCOUNT_P(ref) != 1) {
  5256. return 0;
  5257. }
  5258. /* Directly self-referential arrays are treated as proper references
  5259. * in zend_array_dup() despite rc=1. */
  5260. return Z_TYPE_P(Z_REFVAL_P(ref)) != IS_ARRAY || Z_ARRVAL_P(Z_REFVAL_P(ref)) != ht;
  5261. }
  5262. /* {{{ proto public ReflectionReference|null ReflectionReference::fromArrayElement(array array, mixed key)
  5263. * Create ReflectionReference for array item. Returns null if not a reference. */
  5264. ZEND_METHOD(ReflectionReference, fromArrayElement)
  5265. {
  5266. HashTable *ht;
  5267. zval *key, *item;
  5268. reflection_object *intern;
  5269. if (zend_parse_parameters(ZEND_NUM_ARGS(), "hz", &ht, &key) == FAILURE) {
  5270. RETURN_THROWS();
  5271. }
  5272. if (Z_TYPE_P(key) == IS_LONG) {
  5273. item = zend_hash_index_find(ht, Z_LVAL_P(key));
  5274. } else if (Z_TYPE_P(key) == IS_STRING) {
  5275. item = zend_symtable_find(ht, Z_STR_P(key));
  5276. } else {
  5277. zend_argument_type_error(2, "must be of type string|int, %s given", zend_zval_type_name(key));
  5278. RETURN_THROWS();
  5279. }
  5280. if (!item) {
  5281. _DO_THROW("Array key not found");
  5282. RETURN_THROWS();
  5283. }
  5284. if (Z_TYPE_P(item) != IS_REFERENCE || is_ignorable_reference(ht, item)) {
  5285. RETURN_NULL();
  5286. }
  5287. object_init_ex(return_value, reflection_reference_ptr);
  5288. intern = Z_REFLECTION_P(return_value);
  5289. ZVAL_COPY(&intern->obj, item);
  5290. intern->ref_type = REF_TYPE_OTHER;
  5291. }
  5292. /* }}} */
  5293. /* {{{ proto public int|string ReflectionReference::getId()
  5294. * Returns a unique identifier for the reference.
  5295. * The format of the return value is unspecified and may change. */
  5296. ZEND_METHOD(ReflectionReference, getId)
  5297. {
  5298. reflection_object *intern;
  5299. unsigned char digest[20];
  5300. PHP_SHA1_CTX context;
  5301. if (zend_parse_parameters_none() == FAILURE) {
  5302. RETURN_THROWS();
  5303. }
  5304. intern = Z_REFLECTION_P(getThis());
  5305. if (Z_TYPE(intern->obj) != IS_REFERENCE) {
  5306. _DO_THROW("Corrupted ReflectionReference object");
  5307. RETURN_THROWS();
  5308. }
  5309. if (!REFLECTION_G(key_initialized)) {
  5310. if (php_random_bytes_throw(&REFLECTION_G(key_initialized), 16) == FAILURE) {
  5311. RETURN_THROWS();
  5312. }
  5313. REFLECTION_G(key_initialized) = 1;
  5314. }
  5315. /* SHA1(ref || key) to avoid directly exposing memory addresses. */
  5316. PHP_SHA1Init(&context);
  5317. PHP_SHA1Update(&context, (unsigned char *) &Z_REF(intern->obj), sizeof(zend_reference *));
  5318. PHP_SHA1Update(&context, REFLECTION_G(key), REFLECTION_KEY_LEN);
  5319. PHP_SHA1Final(digest, &context);
  5320. RETURN_STRINGL((char *) digest, sizeof(digest));
  5321. }
  5322. /* }}} */
  5323. static const zend_function_entry reflection_ext_functions[] = { /* {{{ */
  5324. PHP_FE_END
  5325. }; /* }}} */
  5326. /* {{{ _reflection_write_property */
  5327. static zval *_reflection_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
  5328. {
  5329. if (zend_hash_exists(&object->ce->properties_info, name)
  5330. && ((ZSTR_LEN(name) == sizeof("name") - 1 && !memcmp(ZSTR_VAL(name), "name", sizeof("name")))
  5331. || (ZSTR_LEN(name) == sizeof("class") - 1 && !memcmp(ZSTR_VAL(name), "class", sizeof("class")))))
  5332. {
  5333. zend_throw_exception_ex(reflection_exception_ptr, 0,
  5334. "Cannot set read-only property %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
  5335. return &EG(uninitialized_zval);
  5336. }
  5337. else
  5338. {
  5339. return zend_std_write_property(object, name, value, cache_slot);
  5340. }
  5341. }
  5342. /* }}} */
  5343. static void reflection_init_class_handlers(zend_class_entry *ce) {
  5344. ce->create_object = reflection_objects_new;
  5345. ce->serialize = zend_class_serialize_deny;
  5346. ce->unserialize = zend_class_unserialize_deny;
  5347. }
  5348. PHP_MINIT_FUNCTION(reflection) /* {{{ */
  5349. {
  5350. zend_class_entry _reflection_entry;
  5351. memcpy(&reflection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  5352. reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
  5353. reflection_object_handlers.free_obj = reflection_free_objects_storage;
  5354. reflection_object_handlers.clone_obj = NULL;
  5355. reflection_object_handlers.write_property = _reflection_write_property;
  5356. reflection_object_handlers.get_gc = reflection_get_gc;
  5357. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", class_ReflectionException_methods);
  5358. reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_ce_exception);
  5359. INIT_CLASS_ENTRY(_reflection_entry, "Reflection", class_Reflection_methods);
  5360. reflection_ptr = zend_register_internal_class(&_reflection_entry);
  5361. INIT_CLASS_ENTRY(_reflection_entry, "Reflector", class_Reflector_methods);
  5362. reflector_ptr = zend_register_internal_interface(&_reflection_entry);
  5363. zend_class_implements(reflector_ptr, 1, zend_ce_stringable);
  5364. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", class_ReflectionFunctionAbstract_methods);
  5365. reflection_init_class_handlers(&_reflection_entry);
  5366. reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry);
  5367. zend_class_implements(reflection_function_abstract_ptr, 1, reflector_ptr);
  5368. zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT);
  5369. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", class_ReflectionFunction_methods);
  5370. reflection_init_class_handlers(&_reflection_entry);
  5371. reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
  5372. zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5373. REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
  5374. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionGenerator", class_ReflectionGenerator_methods);
  5375. reflection_init_class_handlers(&_reflection_entry);
  5376. reflection_generator_ptr = zend_register_internal_class(&_reflection_entry);
  5377. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", class_ReflectionParameter_methods);
  5378. reflection_init_class_handlers(&_reflection_entry);
  5379. reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry);
  5380. zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
  5381. zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5382. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", class_ReflectionType_methods);
  5383. reflection_init_class_handlers(&_reflection_entry);
  5384. reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
  5385. reflection_type_ptr->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
  5386. zend_class_implements(reflection_type_ptr, 1, zend_ce_stringable);
  5387. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", class_ReflectionNamedType_methods);
  5388. reflection_init_class_handlers(&_reflection_entry);
  5389. reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
  5390. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionUnionType", class_ReflectionUnionType_methods);
  5391. reflection_init_class_handlers(&_reflection_entry);
  5392. reflection_union_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
  5393. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", class_ReflectionMethod_methods);
  5394. reflection_init_class_handlers(&_reflection_entry);
  5395. reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
  5396. zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5397. zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
  5398. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
  5399. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
  5400. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PROTECTED", ZEND_ACC_PROTECTED);
  5401. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PRIVATE", ZEND_ACC_PRIVATE);
  5402. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
  5403. REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
  5404. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", class_ReflectionClass_methods);
  5405. reflection_init_class_handlers(&_reflection_entry);
  5406. reflection_class_ptr = zend_register_internal_class(&_reflection_entry);
  5407. zend_class_implements(reflection_class_ptr, 1, reflector_ptr);
  5408. zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5409. /* IS_IMPLICIT_ABSTRACT is not longer used */
  5410. REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
  5411. REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
  5412. REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL);
  5413. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", class_ReflectionObject_methods);
  5414. reflection_init_class_handlers(&_reflection_entry);
  5415. reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr);
  5416. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", class_ReflectionProperty_methods);
  5417. reflection_init_class_handlers(&_reflection_entry);
  5418. reflection_property_ptr = zend_register_internal_class(&_reflection_entry);
  5419. zend_class_implements(reflection_property_ptr, 1, reflector_ptr);
  5420. zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5421. zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
  5422. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", class_ReflectionClassConstant_methods);
  5423. reflection_init_class_handlers(&_reflection_entry);
  5424. reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
  5425. zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
  5426. zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5427. zend_declare_property_string(reflection_class_constant_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
  5428. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
  5429. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
  5430. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
  5431. REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
  5432. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", class_ReflectionExtension_methods);
  5433. reflection_init_class_handlers(&_reflection_entry);
  5434. reflection_extension_ptr = zend_register_internal_class(&_reflection_entry);
  5435. zend_class_implements(reflection_extension_ptr, 1, reflector_ptr);
  5436. zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5437. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", class_ReflectionZendExtension_methods);
  5438. reflection_init_class_handlers(&_reflection_entry);
  5439. reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry);
  5440. zend_class_implements(reflection_zend_extension_ptr, 1, reflector_ptr);
  5441. zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
  5442. INIT_CLASS_ENTRY(_reflection_entry, "ReflectionReference", class_ReflectionReference_methods);
  5443. reflection_init_class_handlers(&_reflection_entry);
  5444. _reflection_entry.ce_flags |= ZEND_ACC_FINAL;
  5445. reflection_reference_ptr = zend_register_internal_class(&_reflection_entry);
  5446. REFLECTION_G(key_initialized) = 0;
  5447. return SUCCESS;
  5448. } /* }}} */
  5449. PHP_MINFO_FUNCTION(reflection) /* {{{ */
  5450. {
  5451. php_info_print_table_start();
  5452. php_info_print_table_row(2, "Reflection", "enabled");
  5453. php_info_print_table_end();
  5454. } /* }}} */
  5455. zend_module_entry reflection_module_entry = { /* {{{ */
  5456. STANDARD_MODULE_HEADER,
  5457. "Reflection",
  5458. reflection_ext_functions,
  5459. PHP_MINIT(reflection),
  5460. NULL,
  5461. NULL,
  5462. NULL,
  5463. PHP_MINFO(reflection),
  5464. PHP_REFLECTION_VERSION,
  5465. ZEND_MODULE_GLOBALS(reflection),
  5466. NULL,
  5467. NULL,
  5468. NULL,
  5469. STANDARD_MODULE_PROPERTIES_EX
  5470. }; /* }}} */