1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Timm Friebe <thekid@thekid.de> |
16 | George Schlossnagle <george@omniti.com> |
17 | Andrei Zmievski <andrei@gravitonic.com> |
18 | Marcus Boerger <helly@php.net> |
19 | Johannes Schlueter <johannes@php.net> |
20 +----------------------------------------------------------------------+
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "php.h"
28 #include "php_ini.h"
29 #include "php_reflection.h"
30 #include "ext/standard/info.h"
31 #include "ext/standard/sha1.h"
32 #include "ext/standard/php_random.h"
33
34 #include "zend.h"
35 #include "zend_API.h"
36 #include "zend_exceptions.h"
37 #include "zend_operators.h"
38 #include "zend_constants.h"
39 #include "zend_ini.h"
40 #include "zend_interfaces.h"
41 #include "zend_closures.h"
42 #include "zend_generators.h"
43 #include "zend_extensions.h"
44 #include "zend_builtin_functions.h"
45 #include "zend_smart_str.h"
46
47 /* Key used to avoid leaking addresses in ReflectionProperty::getId() */
48 #define REFLECTION_KEY_LEN 16
49 ZEND_BEGIN_MODULE_GLOBALS(reflection)
50 zend_bool key_initialized;
51 unsigned char key[REFLECTION_KEY_LEN];
52 ZEND_END_MODULE_GLOBALS(reflection)
ZEND_DECLARE_MODULE_GLOBALS(reflection)53 ZEND_DECLARE_MODULE_GLOBALS(reflection)
54
55 #define REFLECTION_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(reflection, v)
56
57 static zend_always_inline zval *reflection_prop_name(zval *object) {
58 /* $name is always in the first property slot. */
59 ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 1);
60 return &Z_OBJ_P(object)->properties_table[0];
61 }
62
reflection_prop_class(zval * object)63 static zend_always_inline zval *reflection_prop_class(zval *object) {
64 /* $class is always in the second property slot. */
65 ZEND_ASSERT(Z_OBJCE_P(object)->default_properties_count >= 2);
66 return &Z_OBJ_P(object)->properties_table[1];
67 }
68
69 /* Class entry pointers */
70 PHPAPI zend_class_entry *reflector_ptr;
71 PHPAPI zend_class_entry *reflection_exception_ptr;
72 PHPAPI zend_class_entry *reflection_ptr;
73 PHPAPI zend_class_entry *reflection_function_abstract_ptr;
74 PHPAPI zend_class_entry *reflection_function_ptr;
75 PHPAPI zend_class_entry *reflection_generator_ptr;
76 PHPAPI zend_class_entry *reflection_parameter_ptr;
77 PHPAPI zend_class_entry *reflection_type_ptr;
78 PHPAPI zend_class_entry *reflection_named_type_ptr;
79 PHPAPI zend_class_entry *reflection_class_ptr;
80 PHPAPI zend_class_entry *reflection_object_ptr;
81 PHPAPI zend_class_entry *reflection_method_ptr;
82 PHPAPI zend_class_entry *reflection_property_ptr;
83 PHPAPI zend_class_entry *reflection_class_constant_ptr;
84 PHPAPI zend_class_entry *reflection_extension_ptr;
85 PHPAPI zend_class_entry *reflection_zend_extension_ptr;
86 PHPAPI zend_class_entry *reflection_reference_ptr;
87
88 /* Exception throwing macro */
89 #define _DO_THROW(msg) \
90 zend_throw_exception(reflection_exception_ptr, msg, 0);
91
92 #define GET_REFLECTION_OBJECT() do { \
93 intern = Z_REFLECTION_P(ZEND_THIS); \
94 if (intern->ptr == NULL) { \
95 if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) { \
96 return; \
97 } \
98 zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object"); \
99 return; \
100 } \
101 } while (0)
102
103 #define GET_REFLECTION_OBJECT_PTR(target) do { \
104 GET_REFLECTION_OBJECT(); \
105 target = intern->ptr; \
106 } while (0)
107
108 /* Class constants */
109 #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value) \
110 zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (zend_long)value);
111
112 /* {{{ Object structure */
113
114 /* Struct for properties */
115 typedef struct _property_reference {
116 zend_property_info prop;
117 zend_string *unmangled_name;
118 zend_bool dynamic;
119 } property_reference;
120
121 /* Struct for parameters */
122 typedef struct _parameter_reference {
123 uint32_t offset;
124 zend_bool required;
125 struct _zend_arg_info *arg_info;
126 zend_function *fptr;
127 } parameter_reference;
128
129 /* Struct for type hints */
130 typedef struct _type_reference {
131 zend_type type;
132 } type_reference;
133
134 typedef enum {
135 REF_TYPE_OTHER, /* Must be 0 */
136 REF_TYPE_FUNCTION,
137 REF_TYPE_GENERATOR,
138 REF_TYPE_PARAMETER,
139 REF_TYPE_TYPE,
140 REF_TYPE_PROPERTY,
141 REF_TYPE_CLASS_CONSTANT
142 } reflection_type_t;
143
144 /* Struct for reflection objects */
145 typedef struct {
146 zval obj;
147 void *ptr;
148 zend_class_entry *ce;
149 reflection_type_t ref_type;
150 unsigned int ignore_visibility:1;
151 zend_object zo;
152 } reflection_object;
153
reflection_object_from_obj(zend_object * obj)154 static inline reflection_object *reflection_object_from_obj(zend_object *obj) {
155 return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo));
156 }
157
158 #define Z_REFLECTION_P(zv) reflection_object_from_obj(Z_OBJ_P((zv)))
159 /* }}} */
160
161 static zend_object_handlers reflection_object_handlers;
162
is_closure_invoke(zend_class_entry * ce,zend_string * lcname)163 static inline zend_bool is_closure_invoke(zend_class_entry *ce, zend_string *lcname) {
164 return ce == zend_ce_closure
165 && zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME);
166 }
167
_default_load_name(zval * object)168 static zval *_default_load_name(zval *object) /* {{{ */
169 {
170 return zend_hash_find_ex_ind(Z_OBJPROP_P(object), ZSTR_KNOWN(ZEND_STR_NAME), 1);
171 }
172 /* }}} */
173
_default_get_name(zval * object,zval * return_value)174 static void _default_get_name(zval *object, zval *return_value) /* {{{ */
175 {
176 zval *value;
177
178 if ((value = _default_load_name(object)) == NULL) {
179 RETURN_FALSE;
180 }
181 ZVAL_COPY(return_value, value);
182 }
183 /* }}} */
184
_copy_function(zend_function * fptr)185 static zend_function *_copy_function(zend_function *fptr) /* {{{ */
186 {
187 if (fptr
188 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
189 {
190 zend_function *copy_fptr;
191 copy_fptr = emalloc(sizeof(zend_function));
192 memcpy(copy_fptr, fptr, sizeof(zend_function));
193 copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name);
194 return copy_fptr;
195 } else {
196 /* no copy needed */
197 return fptr;
198 }
199 }
200 /* }}} */
201
_free_function(zend_function * fptr)202 static void _free_function(zend_function *fptr) /* {{{ */
203 {
204 if (fptr
205 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
206 {
207 zend_string_release_ex(fptr->internal_function.function_name, 0);
208 zend_free_trampoline(fptr);
209 }
210 }
211 /* }}} */
212
reflection_free_objects_storage(zend_object * object)213 static void reflection_free_objects_storage(zend_object *object) /* {{{ */
214 {
215 reflection_object *intern = reflection_object_from_obj(object);
216 parameter_reference *reference;
217 property_reference *prop_reference;
218
219 if (intern->ptr) {
220 switch (intern->ref_type) {
221 case REF_TYPE_PARAMETER:
222 reference = (parameter_reference*)intern->ptr;
223 _free_function(reference->fptr);
224 efree(intern->ptr);
225 break;
226 case REF_TYPE_TYPE:
227 {
228 type_reference *type_ref = intern->ptr;
229 if (ZEND_TYPE_IS_NAME(type_ref->type)) {
230 zend_string_release(ZEND_TYPE_NAME(type_ref->type));
231 }
232 efree(type_ref);
233 break;
234 }
235 case REF_TYPE_FUNCTION:
236 _free_function(intern->ptr);
237 break;
238 case REF_TYPE_PROPERTY:
239 prop_reference = (property_reference*)intern->ptr;
240 zend_string_release_ex(prop_reference->unmangled_name, 0);
241
242 if (ZEND_TYPE_IS_NAME(prop_reference->prop.type)) {
243 zend_string_release(ZEND_TYPE_NAME(prop_reference->prop.type));
244 }
245
246 efree(intern->ptr);
247 break;
248 case REF_TYPE_GENERATOR:
249 case REF_TYPE_CLASS_CONSTANT:
250 case REF_TYPE_OTHER:
251 break;
252 }
253 }
254 intern->ptr = NULL;
255 zval_ptr_dtor(&intern->obj);
256 zend_object_std_dtor(object);
257 }
258 /* }}} */
259
reflection_get_gc(zval * obj,zval ** gc_data,int * gc_data_count)260 static HashTable *reflection_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */
261 {
262 reflection_object *intern = Z_REFLECTION_P(obj);
263 *gc_data = &intern->obj;
264 *gc_data_count = 1;
265 return zend_std_get_properties(obj);
266 }
267 /* }}} */
268
reflection_objects_new(zend_class_entry * class_type)269 static zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ */
270 {
271 reflection_object *intern = zend_object_alloc(sizeof(reflection_object), class_type);
272
273 zend_object_std_init(&intern->zo, class_type);
274 object_properties_init(&intern->zo, class_type);
275 intern->zo.handlers = &reflection_object_handlers;
276 return &intern->zo;
277 }
278 /* }}} */
279
reflection_instantiate(zend_class_entry * pce,zval * object)280 static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
281 {
282 object_init_ex(object, pce);
283 return object;
284 }
285 /* }}} */
286
287 static void _const_string(smart_str *str, char *name, zval *value, char *indent);
288 static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent);
289 static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent, zend_bool dynamic);
290 static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char* indent);
291 static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent);
292 static void _extension_string(smart_str *str, zend_module_entry *module, char *indent);
293 static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent);
294
295 /* {{{ _class_string */
_class_string(smart_str * str,zend_class_entry * ce,zval * obj,char * indent)296 static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent)
297 {
298 int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
299 zend_string *sub_indent = strpprintf(0, "%s ", indent);
300
301 /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
302 if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
303 smart_str_append_printf(str, "%s%s", indent, ZSTR_VAL(ce->info.user.doc_comment));
304 smart_str_appendc(str, '\n');
305 }
306
307 if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
308 smart_str_append_printf(str, "%sObject of class [ ", indent);
309 } else {
310 char *kind = "Class";
311 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
312 kind = "Interface";
313 } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
314 kind = "Trait";
315 }
316 smart_str_append_printf(str, "%s%s [ ", indent, kind);
317 }
318 smart_str_append_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
319 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
320 smart_str_append_printf(str, ":%s", ce->info.internal.module->name);
321 }
322 smart_str_append_printf(str, "> ");
323 if (ce->get_iterator != NULL) {
324 smart_str_append_printf(str, "<iterateable> ");
325 }
326 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
327 smart_str_append_printf(str, "interface ");
328 } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
329 smart_str_append_printf(str, "trait ");
330 } else {
331 if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
332 smart_str_append_printf(str, "abstract ");
333 }
334 if (ce->ce_flags & ZEND_ACC_FINAL) {
335 smart_str_append_printf(str, "final ");
336 }
337 smart_str_append_printf(str, "class ");
338 }
339 smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name));
340 if (ce->parent) {
341 smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
342 }
343
344 if (ce->num_interfaces) {
345 uint32_t i;
346
347 ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
348 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
349 smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->interfaces[0]->name));
350 } else {
351 smart_str_append_printf(str, " implements %s", ZSTR_VAL(ce->interfaces[0]->name));
352 }
353 for (i = 1; i < ce->num_interfaces; ++i) {
354 smart_str_append_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name));
355 }
356 }
357 smart_str_append_printf(str, " ] {\n");
358
359 /* The information where a class is declared is only available for user classes */
360 if (ce->type == ZEND_USER_CLASS) {
361 smart_str_append_printf(str, "%s @@ %s %d-%d\n", indent, ZSTR_VAL(ce->info.user.filename),
362 ce->info.user.line_start, ce->info.user.line_end);
363 }
364
365 /* Constants */
366 smart_str_append_printf(str, "\n");
367 count = zend_hash_num_elements(&ce->constants_table);
368 smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, count);
369 if (count > 0) {
370 zend_string *key;
371 zend_class_constant *c;
372
373 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
374 _class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent));
375 if (UNEXPECTED(EG(exception))) {
376 zend_string_release(sub_indent);
377 return;
378 }
379 } ZEND_HASH_FOREACH_END();
380 }
381 smart_str_append_printf(str, "%s }\n", indent);
382
383 /* Static properties */
384 /* counting static properties */
385 count = zend_hash_num_elements(&ce->properties_info);
386 if (count > 0) {
387 zend_property_info *prop;
388
389 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
390 if ((prop->flags & ZEND_ACC_PRIVATE) && prop->ce != ce) {
391 count_shadow_props++;
392 } else if (prop->flags & ZEND_ACC_STATIC) {
393 count_static_props++;
394 }
395 } ZEND_HASH_FOREACH_END();
396 }
397
398 /* static properties */
399 smart_str_append_printf(str, "\n%s - Static properties [%d] {\n", indent, count_static_props);
400 if (count_static_props > 0) {
401 zend_property_info *prop;
402
403 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
404 if ((prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
405 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent), 0);
406 }
407 } ZEND_HASH_FOREACH_END();
408 }
409 smart_str_append_printf(str, "%s }\n", indent);
410
411 /* Static methods */
412 /* counting static methods */
413 count = zend_hash_num_elements(&ce->function_table);
414 if (count > 0) {
415 zend_function *mptr;
416
417 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
418 if (mptr->common.fn_flags & ZEND_ACC_STATIC
419 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
420 {
421 count_static_funcs++;
422 }
423 } ZEND_HASH_FOREACH_END();
424 }
425
426 /* static methods */
427 smart_str_append_printf(str, "\n%s - Static methods [%d] {", indent, count_static_funcs);
428 if (count_static_funcs > 0) {
429 zend_function *mptr;
430
431 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
432 if (mptr->common.fn_flags & ZEND_ACC_STATIC
433 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
434 {
435 smart_str_append_printf(str, "\n");
436 _function_string(str, mptr, ce, ZSTR_VAL(sub_indent));
437 }
438 } ZEND_HASH_FOREACH_END();
439 } else {
440 smart_str_append_printf(str, "\n");
441 }
442 smart_str_append_printf(str, "%s }\n", indent);
443
444 /* Default/Implicit properties */
445 count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
446 smart_str_append_printf(str, "\n%s - Properties [%d] {\n", indent, count);
447 if (count > 0) {
448 zend_property_info *prop;
449
450 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
451 if (!(prop->flags & ZEND_ACC_STATIC)
452 && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
453 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent), 0);
454 }
455 } ZEND_HASH_FOREACH_END();
456 }
457 smart_str_append_printf(str, "%s }\n", indent);
458
459 if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
460 HashTable *properties = Z_OBJ_HT_P(obj)->get_properties(obj);
461 zend_string *prop_name;
462 smart_str prop_str = {0};
463
464 count = 0;
465 if (properties && zend_hash_num_elements(properties)) {
466 ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) {
467 if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
468 if (!zend_hash_exists(&ce->properties_info, prop_name)) {
469 count++;
470 _property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent), 0);
471 }
472 }
473 } ZEND_HASH_FOREACH_END();
474 }
475
476 smart_str_append_printf(str, "\n%s - Dynamic properties [%d] {\n", indent, count);
477 smart_str_append_smart_str(str, &prop_str);
478 smart_str_append_printf(str, "%s }\n", indent);
479 smart_str_free(&prop_str);
480 }
481
482 /* Non static methods */
483 count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
484 if (count > 0) {
485 zend_function *mptr;
486 smart_str method_str = {0};
487
488 count = 0;
489 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
490 if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
491 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
492 {
493 zend_function *closure;
494 /* see if this is a closure */
495 if (obj && is_closure_invoke(ce, mptr->common.function_name)
496 && (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
497 {
498 mptr = closure;
499 } else {
500 closure = NULL;
501 }
502 smart_str_appendc(&method_str, '\n');
503 _function_string(&method_str, mptr, ce, ZSTR_VAL(sub_indent));
504 count++;
505 _free_function(closure);
506 }
507 } ZEND_HASH_FOREACH_END();
508 smart_str_append_printf(str, "\n%s - Methods [%d] {", indent, count);
509 smart_str_append_smart_str(str, &method_str);
510 if (!count) {
511 smart_str_append_printf(str, "\n");
512 }
513 smart_str_free(&method_str);
514 } else {
515 smart_str_append_printf(str, "\n%s - Methods [0] {\n", indent);
516 }
517 smart_str_append_printf(str, "%s }\n", indent);
518
519 smart_str_append_printf(str, "%s}\n", indent);
520 zend_string_release_ex(sub_indent, 0);
521 }
522 /* }}} */
523
524 /* {{{ _const_string */
_const_string(smart_str * str,char * name,zval * value,char * indent)525 static void _const_string(smart_str *str, char *name, zval *value, char *indent)
526 {
527 char *type = zend_zval_type_name(value);
528
529 if (Z_TYPE_P(value) == IS_ARRAY) {
530 smart_str_append_printf(str, "%s Constant [ %s %s ] { Array }\n",
531 indent, type, name);
532 } else if (Z_TYPE_P(value) == IS_STRING) {
533 smart_str_append_printf(str, "%s Constant [ %s %s ] { %s }\n",
534 indent, type, name, Z_STRVAL_P(value));
535 } else {
536 zend_string *tmp_value_str;
537 zend_string *value_str = zval_get_tmp_string(value, &tmp_value_str);
538 smart_str_append_printf(str, "%s Constant [ %s %s ] { %s }\n",
539 indent, type, name, ZSTR_VAL(value_str));
540 zend_tmp_string_release(tmp_value_str);
541 }
542 }
543 /* }}} */
544
545 /* {{{ _class_const_string */
_class_const_string(smart_str * str,char * name,zend_class_constant * c,char * indent)546 static void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char *indent)
547 {
548 char *visibility = zend_visibility_string(Z_ACCESS_FLAGS(c->value));
549 char *type;
550
551 if (zval_update_constant_ex(&c->value, c->ce) == FAILURE) {
552 return;
553 }
554
555 type = zend_zval_type_name(&c->value);
556
557 if (Z_TYPE(c->value) == IS_ARRAY) {
558 smart_str_append_printf(str, "%sConstant [ %s %s %s ] { Array }\n",
559 indent, visibility, type, name);
560 } else {
561 zend_string *tmp_value_str;
562 zend_string *value_str = zval_get_tmp_string(&c->value, &tmp_value_str);
563
564 smart_str_append_printf(str, "%sConstant [ %s %s %s ] { %s }\n",
565 indent, visibility, type, name, ZSTR_VAL(value_str));
566
567 zend_tmp_string_release(tmp_value_str);
568 }
569 }
570 /* }}} */
571
572 /* {{{ _get_recv_opcode */
_get_recv_op(zend_op_array * op_array,uint32_t offset)573 static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
574 {
575 zend_op *op = op_array->opcodes;
576 zend_op *end = op + op_array->last;
577
578 ++offset;
579 while (op < end) {
580 if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
581 || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == offset)
582 {
583 return op;
584 }
585 ++op;
586 }
587 return NULL;
588 }
589 /* }}} */
590
591 /* {{{ _parameter_string */
_parameter_string(smart_str * str,zend_function * fptr,struct _zend_arg_info * arg_info,uint32_t offset,zend_bool required,char * indent)592 static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, char* indent)
593 {
594 smart_str_append_printf(str, "Parameter #%d [ ", offset);
595 if (!required) {
596 smart_str_append_printf(str, "<optional> ");
597 } else {
598 smart_str_append_printf(str, "<required> ");
599 }
600 if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
601 smart_str_append_printf(str, "%s ",
602 ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)));
603 if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
604 smart_str_append_printf(str, "or NULL ");
605 }
606 } else if (ZEND_TYPE_IS_CODE(arg_info->type)) {
607 smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)));
608 if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
609 smart_str_append_printf(str, "or NULL ");
610 }
611 }
612 if (arg_info->pass_by_reference) {
613 smart_str_appendc(str, '&');
614 }
615 if (arg_info->is_variadic) {
616 smart_str_appends(str, "...");
617 }
618 if (arg_info->name) {
619 smart_str_append_printf(str, "$%s",
620 (fptr->type == ZEND_INTERNAL_FUNCTION &&
621 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
622 ((zend_internal_arg_info*)arg_info)->name :
623 ZSTR_VAL(arg_info->name));
624 } else {
625 smart_str_append_printf(str, "$param%d", offset);
626 }
627 if (fptr->type == ZEND_USER_FUNCTION && !required) {
628 zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
629 if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
630 zval zv;
631
632 smart_str_appends(str, " = ");
633 ZVAL_COPY(&zv, RT_CONSTANT(precv, precv->op2));
634 if (UNEXPECTED(zval_update_constant_ex(&zv, fptr->common.scope) == FAILURE)) {
635 zval_ptr_dtor(&zv);
636 return;
637 }
638 if (Z_TYPE(zv) == IS_TRUE) {
639 smart_str_appends(str, "true");
640 } else if (Z_TYPE(zv) == IS_FALSE) {
641 smart_str_appends(str, "false");
642 } else if (Z_TYPE(zv) == IS_NULL) {
643 smart_str_appends(str, "NULL");
644 } else if (Z_TYPE(zv) == IS_STRING) {
645 smart_str_appendc(str, '\'');
646 smart_str_appendl(str, Z_STRVAL(zv), MIN(Z_STRLEN(zv), 15));
647 if (Z_STRLEN(zv) > 15) {
648 smart_str_appends(str, "...");
649 }
650 smart_str_appendc(str, '\'');
651 } else if (Z_TYPE(zv) == IS_ARRAY) {
652 smart_str_appends(str, "Array");
653 } else {
654 zend_string *tmp_zv_str;
655 zend_string *zv_str = zval_get_tmp_string(&zv, &tmp_zv_str);
656 smart_str_append(str, zv_str);
657 zend_tmp_string_release(tmp_zv_str);
658 }
659 zval_ptr_dtor(&zv);
660 }
661 }
662 smart_str_appends(str, " ]");
663 }
664 /* }}} */
665
666 /* {{{ _function_parameter_string */
_function_parameter_string(smart_str * str,zend_function * fptr,char * indent)667 static void _function_parameter_string(smart_str *str, zend_function *fptr, char* indent)
668 {
669 struct _zend_arg_info *arg_info = fptr->common.arg_info;
670 uint32_t i, num_args, num_required = fptr->common.required_num_args;
671
672 if (!arg_info) {
673 return;
674 }
675
676 num_args = fptr->common.num_args;
677 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
678 num_args++;
679 }
680 smart_str_appendc(str, '\n');
681 smart_str_append_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
682 for (i = 0; i < num_args; i++) {
683 smart_str_append_printf(str, "%s ", indent);
684 _parameter_string(str, fptr, arg_info, i, i < num_required, indent);
685 smart_str_appendc(str, '\n');
686 arg_info++;
687 }
688 smart_str_append_printf(str, "%s}\n", indent);
689 }
690 /* }}} */
691
692 /* {{{ _function_closure_string */
_function_closure_string(smart_str * str,zend_function * fptr,char * indent)693 static void _function_closure_string(smart_str *str, zend_function *fptr, char* indent)
694 {
695 uint32_t i, count;
696 zend_string *key;
697 HashTable *static_variables;
698
699 if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
700 return;
701 }
702
703 static_variables = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
704 count = zend_hash_num_elements(static_variables);
705
706 if (!count) {
707 return;
708 }
709
710 smart_str_append_printf(str, "\n");
711 smart_str_append_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
712 i = 0;
713 ZEND_HASH_FOREACH_STR_KEY(static_variables, key) {
714 smart_str_append_printf(str, "%s Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key));
715 } ZEND_HASH_FOREACH_END();
716 smart_str_append_printf(str, "%s}\n", indent);
717 }
718 /* }}} */
719
720 /* {{{ _function_string */
_function_string(smart_str * str,zend_function * fptr,zend_class_entry * scope,char * indent)721 static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent)
722 {
723 smart_str param_indent = {0};
724 zend_function *overwrites;
725 zend_string *lc_name;
726
727 /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
728 * What's "wrong" is that any whitespace before the doc comment start is
729 * swallowed, leading to an unaligned comment.
730 */
731 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
732 smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->op_array.doc_comment));
733 }
734
735 smart_str_appendl(str, indent, strlen(indent));
736 smart_str_append_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
737 smart_str_append_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
738 if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
739 smart_str_appends(str, ", deprecated");
740 }
741 if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
742 smart_str_append_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
743 }
744
745 if (scope && fptr->common.scope) {
746 if (fptr->common.scope != scope) {
747 smart_str_append_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
748 } else if (fptr->common.scope->parent) {
749 lc_name = zend_string_tolower(fptr->common.function_name);
750 if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
751 if (fptr->common.scope != overwrites->common.scope) {
752 smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
753 }
754 }
755 zend_string_release_ex(lc_name, 0);
756 }
757 }
758 if (fptr->common.prototype && fptr->common.prototype->common.scope) {
759 smart_str_append_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name));
760 }
761 if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
762 smart_str_appends(str, ", ctor");
763 }
764 if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
765 smart_str_appends(str, ", dtor");
766 }
767 smart_str_appends(str, "> ");
768
769 if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
770 smart_str_appends(str, "abstract ");
771 }
772 if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
773 smart_str_appends(str, "final ");
774 }
775 if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
776 smart_str_appends(str, "static ");
777 }
778
779 if (fptr->common.scope) {
780 /* These are mutually exclusive */
781 switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
782 case ZEND_ACC_PUBLIC:
783 smart_str_appends(str, "public ");
784 break;
785 case ZEND_ACC_PRIVATE:
786 smart_str_appends(str, "private ");
787 break;
788 case ZEND_ACC_PROTECTED:
789 smart_str_appends(str, "protected ");
790 break;
791 default:
792 smart_str_appends(str, "<visibility error> ");
793 break;
794 }
795 smart_str_appends(str, "method ");
796 } else {
797 smart_str_appends(str, "function ");
798 }
799
800 if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
801 smart_str_appendc(str, '&');
802 }
803 smart_str_append_printf(str, "%s ] {\n", ZSTR_VAL(fptr->common.function_name));
804 /* The information where a function is declared is only available for user classes */
805 if (fptr->type == ZEND_USER_FUNCTION) {
806 smart_str_append_printf(str, "%s @@ %s %d - %d\n", indent,
807 ZSTR_VAL(fptr->op_array.filename),
808 fptr->op_array.line_start,
809 fptr->op_array.line_end);
810 }
811 smart_str_append_printf(¶m_indent, "%s ", indent);
812 smart_str_0(¶m_indent);
813 if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
814 _function_closure_string(str, fptr, ZSTR_VAL(param_indent.s));
815 }
816 _function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
817 smart_str_free(¶m_indent);
818 if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
819 smart_str_append_printf(str, " %s- Return [ ", indent);
820 if (ZEND_TYPE_IS_CLASS(fptr->common.arg_info[-1].type)) {
821 smart_str_append_printf(str, "%s ",
822 ZSTR_VAL(ZEND_TYPE_NAME(fptr->common.arg_info[-1].type)));
823 if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
824 smart_str_appends(str, "or NULL ");
825 }
826 } else if (ZEND_TYPE_IS_CODE(fptr->common.arg_info[-1].type)) {
827 smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(fptr->common.arg_info[-1].type)));
828 if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
829 smart_str_appends(str, "or NULL ");
830 }
831 }
832 smart_str_appends(str, "]\n");
833 }
834 smart_str_append_printf(str, "%s}\n", indent);
835 }
836 /* }}} */
837
838 /* {{{ _property_string */
_property_string(smart_str * str,zend_property_info * prop,const char * prop_name,char * indent,zend_bool dynamic)839 static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent, zend_bool dynamic)
840 {
841 smart_str_append_printf(str, "%sProperty [ ", indent);
842 if (!prop) {
843 smart_str_append_printf(str, "<dynamic> public $%s", prop_name);
844 } else {
845 if (!(prop->flags & ZEND_ACC_STATIC)) {
846 if (dynamic) {
847 smart_str_appends(str, "<implicit> ");
848 } else {
849 smart_str_appends(str, "<default> ");
850 }
851 }
852
853 /* These are mutually exclusive */
854 switch (prop->flags & ZEND_ACC_PPP_MASK) {
855 case ZEND_ACC_PUBLIC:
856 smart_str_appends(str, "public ");
857 break;
858 case ZEND_ACC_PRIVATE:
859 smart_str_appends(str, "private ");
860 break;
861 case ZEND_ACC_PROTECTED:
862 smart_str_appends(str, "protected ");
863 break;
864 }
865 if (prop->flags & ZEND_ACC_STATIC) {
866 smart_str_appends(str, "static ");
867 }
868 if (!prop_name) {
869 const char *class_name;
870 zend_unmangle_property_name(prop->name, &class_name, &prop_name);
871 }
872 smart_str_append_printf(str, "$%s", prop_name);
873 }
874
875 smart_str_appends(str, " ]\n");
876 }
877 /* }}} */
878
_extension_ini_string(zend_ini_entry * ini_entry,smart_str * str,char * indent,int number)879 static void _extension_ini_string(zend_ini_entry *ini_entry, smart_str *str, char *indent, int number) /* {{{ */
880 {
881 char *comma = "";
882
883 if (number == ini_entry->module_number) {
884 smart_str_append_printf(str, " %sEntry [ %s <", indent, ZSTR_VAL(ini_entry->name));
885 if (ini_entry->modifiable == ZEND_INI_ALL) {
886 smart_str_appends(str, "ALL");
887 } else {
888 if (ini_entry->modifiable & ZEND_INI_USER) {
889 smart_str_appends(str, "USER");
890 comma = ",";
891 }
892 if (ini_entry->modifiable & ZEND_INI_PERDIR) {
893 smart_str_append_printf(str, "%sPERDIR", comma);
894 comma = ",";
895 }
896 if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
897 smart_str_append_printf(str, "%sSYSTEM", comma);
898 }
899 }
900
901 smart_str_appends(str, "> ]\n");
902 smart_str_append_printf(str, " %s Current = '%s'\n", indent, ini_entry->value ? ZSTR_VAL(ini_entry->value) : "");
903 if (ini_entry->modified) {
904 smart_str_append_printf(str, " %s Default = '%s'\n", indent, ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : "");
905 }
906 smart_str_append_printf(str, " %s}\n", indent);
907 }
908 }
909 /* }}} */
910
_extension_class_string(zend_class_entry * ce,zend_string * key,smart_str * str,char * indent,zend_module_entry * module,int * num_classes)911 static void _extension_class_string(zend_class_entry *ce, zend_string *key, smart_str *str, char *indent, zend_module_entry *module, int *num_classes) /* {{{ */
912 {
913 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
914 /* dump class if it is not an alias */
915 if (zend_string_equals_ci(ce->name, key)) {
916 smart_str_append_printf(str, "\n");
917 _class_string(str, ce, NULL, indent);
918 (*num_classes)++;
919 }
920 }
921 }
922 /* }}} */
923
_extension_string(smart_str * str,zend_module_entry * module,char * indent)924 static void _extension_string(smart_str *str, zend_module_entry *module, char *indent) /* {{{ */
925 {
926 smart_str_append_printf(str, "%sExtension [ ", indent);
927 if (module->type == MODULE_PERSISTENT) {
928 smart_str_appends(str, "<persistent>");
929 }
930 if (module->type == MODULE_TEMPORARY) {
931 smart_str_appends(str, "<temporary>" );
932 }
933 smart_str_append_printf(str, " extension #%d %s version %s ] {\n",
934 module->module_number, module->name,
935 (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
936
937 if (module->deps) {
938 const zend_module_dep* dep = module->deps;
939
940 smart_str_appends(str, "\n - Dependencies {\n");
941
942 while(dep->name) {
943 smart_str_append_printf(str, "%s Dependency [ %s (", indent, dep->name);
944
945 switch(dep->type) {
946 case MODULE_DEP_REQUIRED:
947 smart_str_appends(str, "Required");
948 break;
949 case MODULE_DEP_CONFLICTS:
950 smart_str_appends(str, "Conflicts");
951 break;
952 case MODULE_DEP_OPTIONAL:
953 smart_str_appends(str, "Optional");
954 break;
955 default:
956 smart_str_appends(str, "Error"); /* shouldn't happen */
957 break;
958 }
959
960 if (dep->rel) {
961 smart_str_append_printf(str, " %s", dep->rel);
962 }
963 if (dep->version) {
964 smart_str_append_printf(str, " %s", dep->version);
965 }
966 smart_str_appends(str, ") ]\n");
967 dep++;
968 }
969 smart_str_append_printf(str, "%s }\n", indent);
970 }
971
972 {
973 smart_str str_ini = {0};
974 zend_ini_entry *ini_entry;
975 ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) {
976 _extension_ini_string(ini_entry, &str_ini, indent, module->module_number);
977 } ZEND_HASH_FOREACH_END();
978 if (smart_str_get_len(&str_ini) > 0) {
979 smart_str_append_printf(str, "\n - INI {\n");
980 smart_str_append_smart_str(str, &str_ini);
981 smart_str_append_printf(str, "%s }\n", indent);
982 }
983 smart_str_free(&str_ini);
984 }
985
986 {
987 smart_str str_constants = {0};
988 zend_constant *constant;
989 int num_constants = 0;
990
991 ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) {
992 if (ZEND_CONSTANT_MODULE_NUMBER(constant) == module->module_number) {
993 _const_string(&str_constants, ZSTR_VAL(constant->name), &constant->value, indent);
994 num_constants++;
995 }
996 } ZEND_HASH_FOREACH_END();
997
998 if (num_constants) {
999 smart_str_append_printf(str, "\n - Constants [%d] {\n", num_constants);
1000 smart_str_append_smart_str(str, &str_constants);
1001 smart_str_append_printf(str, "%s }\n", indent);
1002 }
1003 smart_str_free(&str_constants);
1004 }
1005
1006 {
1007 zend_function *fptr;
1008 int first = 1;
1009
1010 ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
1011 if (fptr->common.type==ZEND_INTERNAL_FUNCTION
1012 && fptr->internal_function.module == module) {
1013 if (first) {
1014 smart_str_append_printf(str, "\n - Functions {\n");
1015 first = 0;
1016 }
1017 _function_string(str, fptr, NULL, " ");
1018 }
1019 } ZEND_HASH_FOREACH_END();
1020 if (!first) {
1021 smart_str_append_printf(str, "%s }\n", indent);
1022 }
1023 }
1024
1025 {
1026 zend_string *sub_indent = strpprintf(0, "%s ", indent);
1027 smart_str str_classes = {0};
1028 zend_string *key;
1029 zend_class_entry *ce;
1030 int num_classes = 0;
1031
1032 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
1033 _extension_class_string(ce, key, &str_classes, ZSTR_VAL(sub_indent), module, &num_classes);
1034 } ZEND_HASH_FOREACH_END();
1035 if (num_classes) {
1036 smart_str_append_printf(str, "\n - Classes [%d] {", num_classes);
1037 smart_str_append_smart_str(str, &str_classes);
1038 smart_str_append_printf(str, "%s }\n", indent);
1039 }
1040 smart_str_free(&str_classes);
1041 zend_string_release_ex(sub_indent, 0);
1042 }
1043
1044 smart_str_append_printf(str, "%s}\n", indent);
1045 }
1046 /* }}} */
1047
_zend_extension_string(smart_str * str,zend_extension * extension,char * indent)1048 static void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent) /* {{{ */
1049 {
1050 smart_str_append_printf(str, "%sZend Extension [ %s ", indent, extension->name);
1051
1052 if (extension->version) {
1053 smart_str_append_printf(str, "%s ", extension->version);
1054 }
1055 if (extension->copyright) {
1056 smart_str_append_printf(str, "%s ", extension->copyright);
1057 }
1058 if (extension->author) {
1059 smart_str_append_printf(str, "by %s ", extension->author);
1060 }
1061 if (extension->URL) {
1062 smart_str_append_printf(str, "<%s> ", extension->URL);
1063 }
1064
1065 smart_str_appends(str, "]\n");
1066 }
1067 /* }}} */
1068
1069 /* {{{ _function_check_flag */
_function_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)1070 static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
1071 {
1072 reflection_object *intern;
1073 zend_function *mptr;
1074
1075 if (zend_parse_parameters_none() == FAILURE) {
1076 return;
1077 }
1078 GET_REFLECTION_OBJECT_PTR(mptr);
1079 RETURN_BOOL(mptr->common.fn_flags & mask);
1080 }
1081 /* }}} */
1082
1083 /* {{{ zend_reflection_class_factory */
zend_reflection_class_factory(zend_class_entry * ce,zval * object)1084 PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object)
1085 {
1086 reflection_object *intern;
1087
1088 reflection_instantiate(reflection_class_ptr, object);
1089 intern = Z_REFLECTION_P(object);
1090 intern->ptr = ce;
1091 intern->ref_type = REF_TYPE_OTHER;
1092 intern->ce = ce;
1093 ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
1094 }
1095 /* }}} */
1096
1097 /* {{{ reflection_extension_factory */
reflection_extension_factory(zval * object,const char * name_str)1098 static void reflection_extension_factory(zval *object, const char *name_str)
1099 {
1100 reflection_object *intern;
1101 size_t name_len = strlen(name_str);
1102 zend_string *lcname;
1103 struct _zend_module_entry *module;
1104
1105 lcname = zend_string_alloc(name_len, 0);
1106 zend_str_tolower_copy(ZSTR_VAL(lcname), name_str, name_len);
1107 module = zend_hash_find_ptr(&module_registry, lcname);
1108 zend_string_efree(lcname);
1109 if (!module) {
1110 return;
1111 }
1112
1113 reflection_instantiate(reflection_extension_ptr, object);
1114 intern = Z_REFLECTION_P(object);
1115 intern->ptr = module;
1116 intern->ref_type = REF_TYPE_OTHER;
1117 intern->ce = NULL;
1118 ZVAL_STRINGL(reflection_prop_name(object), module->name, name_len);
1119 }
1120 /* }}} */
1121
1122 /* {{{ reflection_parameter_factory */
reflection_parameter_factory(zend_function * fptr,zval * closure_object,struct _zend_arg_info * arg_info,uint32_t offset,zend_bool required,zval * object)1123 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)
1124 {
1125 reflection_object *intern;
1126 parameter_reference *reference;
1127 zval *prop_name;
1128
1129 reflection_instantiate(reflection_parameter_ptr, object);
1130 intern = Z_REFLECTION_P(object);
1131 reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
1132 reference->arg_info = arg_info;
1133 reference->offset = offset;
1134 reference->required = required;
1135 reference->fptr = fptr;
1136 intern->ptr = reference;
1137 intern->ref_type = REF_TYPE_PARAMETER;
1138 intern->ce = fptr->common.scope;
1139 if (closure_object) {
1140 Z_ADDREF_P(closure_object);
1141 ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
1142 }
1143
1144 prop_name = reflection_prop_name(object);
1145 if (arg_info->name) {
1146 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
1147 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
1148 ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)->name);
1149 } else {
1150 ZVAL_STR_COPY(prop_name, arg_info->name);
1151 }
1152 } else {
1153 ZVAL_NULL(prop_name);
1154 }
1155 }
1156 /* }}} */
1157
1158 /* {{{ reflection_type_factory */
reflection_type_factory(zend_type type,zval * object)1159 static void reflection_type_factory(zend_type type, zval *object)
1160 {
1161 reflection_object *intern;
1162 type_reference *reference;
1163
1164 reflection_instantiate(reflection_named_type_ptr, object);
1165 intern = Z_REFLECTION_P(object);
1166 reference = (type_reference*) emalloc(sizeof(type_reference));
1167 reference->type = type;
1168 intern->ptr = reference;
1169 intern->ref_type = REF_TYPE_TYPE;
1170
1171 /* Property types may be resolved during the lifetime of the ReflectionType,
1172 * so we need to make sure that the strings we reference are not released. */
1173 if (ZEND_TYPE_IS_NAME(type)) {
1174 zend_string_addref(ZEND_TYPE_NAME(type));
1175 }
1176 }
1177 /* }}} */
1178
1179 /* {{{ reflection_function_factory */
reflection_function_factory(zend_function * function,zval * closure_object,zval * object)1180 static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
1181 {
1182 reflection_object *intern;
1183 reflection_instantiate(reflection_function_ptr, object);
1184 intern = Z_REFLECTION_P(object);
1185 intern->ptr = function;
1186 intern->ref_type = REF_TYPE_FUNCTION;
1187 intern->ce = NULL;
1188 if (closure_object) {
1189 Z_ADDREF_P(closure_object);
1190 ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
1191 }
1192 ZVAL_STR_COPY(reflection_prop_name(object), function->common.function_name);
1193 }
1194 /* }}} */
1195
1196 /* {{{ reflection_method_factory */
reflection_method_factory(zend_class_entry * ce,zend_function * method,zval * closure_object,zval * object)1197 static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object)
1198 {
1199 reflection_object *intern;
1200
1201 reflection_instantiate(reflection_method_ptr, object);
1202 intern = Z_REFLECTION_P(object);
1203 intern->ptr = method;
1204 intern->ref_type = REF_TYPE_FUNCTION;
1205 intern->ce = ce;
1206 if (closure_object) {
1207 Z_ADDREF_P(closure_object);
1208 ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure_object));
1209 }
1210
1211 ZVAL_STR_COPY(reflection_prop_name(object),
1212 (method->common.scope && method->common.scope->trait_aliases)
1213 ? zend_resolve_method_name(ce, method) : method->common.function_name);
1214 ZVAL_STR_COPY(reflection_prop_class(object), method->common.scope->name);
1215 }
1216 /* }}} */
1217
1218 /* {{{ reflection_property_factory */
reflection_property_factory(zend_class_entry * ce,zend_string * name,zend_property_info * prop,zval * object,zend_bool dynamic)1219 static void reflection_property_factory(zend_class_entry *ce, zend_string *name, zend_property_info *prop, zval *object, zend_bool dynamic)
1220 {
1221 reflection_object *intern;
1222 property_reference *reference;
1223
1224 if (!(prop->flags & ZEND_ACC_PRIVATE)) {
1225 /* we have to search the class hierarchy for this (implicit) public or protected property */
1226 zend_class_entry *tmp_ce = ce, *store_ce = ce;
1227 zend_property_info *tmp_info = NULL;
1228
1229 while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, name)) == NULL) {
1230 ce = tmp_ce;
1231 tmp_ce = tmp_ce->parent;
1232 }
1233
1234 if (tmp_info && (!(tmp_info->flags & ZEND_ACC_PRIVATE) || tmp_info->ce == tmp_ce)) { /* found something and it's not a parent's private */
1235 prop = tmp_info;
1236 } else { /* not found, use initial value */
1237 ce = store_ce;
1238 }
1239 }
1240
1241 reflection_instantiate(reflection_property_ptr, object);
1242 intern = Z_REFLECTION_P(object);
1243 reference = (property_reference*) emalloc(sizeof(property_reference));
1244 reference->prop = *prop;
1245
1246 if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
1247 zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
1248 }
1249
1250 reference->unmangled_name = zend_string_copy(name);
1251 reference->dynamic = dynamic;
1252 intern->ptr = reference;
1253 intern->ref_type = REF_TYPE_PROPERTY;
1254 intern->ce = ce;
1255 intern->ignore_visibility = 0;
1256 ZVAL_STR_COPY(reflection_prop_name(object), name);
1257 ZVAL_STR_COPY(reflection_prop_class(object), prop->ce->name);
1258 }
1259 /* }}} */
1260
reflection_property_factory_str(zend_class_entry * ce,const char * name_str,size_t name_len,zend_property_info * prop,zval * object)1261 static void reflection_property_factory_str(zend_class_entry *ce, const char *name_str, size_t name_len, zend_property_info *prop, zval *object)
1262 {
1263 zend_string *name = zend_string_init(name_str, name_len, 0);
1264 reflection_property_factory(ce, name, prop, object, 0);
1265 zend_string_release(name);
1266 }
1267
1268 /* {{{ reflection_class_constant_factory */
reflection_class_constant_factory(zend_class_entry * ce,zend_string * name_str,zend_class_constant * constant,zval * object)1269 static void reflection_class_constant_factory(zend_class_entry *ce, zend_string *name_str, zend_class_constant *constant, zval *object)
1270 {
1271 reflection_object *intern;
1272
1273 reflection_instantiate(reflection_class_constant_ptr, object);
1274 intern = Z_REFLECTION_P(object);
1275 intern->ptr = constant;
1276 intern->ref_type = REF_TYPE_CLASS_CONSTANT;
1277 intern->ce = constant->ce;
1278 intern->ignore_visibility = 0;
1279
1280 ZVAL_STR_COPY(reflection_prop_name(object), name_str);
1281 ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
1282 }
1283 /* }}} */
1284
reflection_export_impl(zval * return_value,zval * object,zend_bool return_output)1285 static void reflection_export_impl(zval *return_value, zval *object, zend_bool return_output) {
1286 zval fname, retval;
1287 int result;
1288
1289 /* Invoke the __toString() method */
1290 ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring") - 1);
1291 result = call_user_function(NULL, object, &fname, &retval, 0, NULL);
1292 zval_ptr_dtor_str(&fname);
1293
1294 if (result == FAILURE) {
1295 _DO_THROW("Invocation of method __toString() failed");
1296 return;
1297 }
1298
1299 if (Z_TYPE(retval) == IS_UNDEF) {
1300 php_error_docref(NULL, E_WARNING, "%s::__toString() did not return anything", ZSTR_VAL(Z_OBJCE_P(object)->name));
1301 RETURN_FALSE;
1302 }
1303
1304 if (return_output) {
1305 ZVAL_COPY_VALUE(return_value, &retval);
1306 } else {
1307 /* No need for _r variant, return of __toString should always be a string */
1308 zend_print_zval(&retval, 0);
1309 zend_printf("\n");
1310 zval_ptr_dtor(&retval);
1311 }
1312 }
1313
1314 /* {{{ _reflection_export */
_reflection_export(INTERNAL_FUNCTION_PARAMETERS,zend_class_entry * ce_ptr,int ctor_argc)1315 static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
1316 {
1317 zval reflector;
1318 zval *argument_ptr, *argument2_ptr;
1319 zval retval, params[2];
1320 int result;
1321 int return_output = 0;
1322 zend_fcall_info fci;
1323 zend_fcall_info_cache fcc;
1324
1325 if (ctor_argc == 1) {
1326 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &argument_ptr, &return_output) == FAILURE) {
1327 return;
1328 }
1329 ZVAL_COPY_VALUE(¶ms[0], argument_ptr);
1330 ZVAL_NULL(¶ms[1]);
1331 } else {
1332 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|b", &argument_ptr, &argument2_ptr, &return_output) == FAILURE) {
1333 return;
1334 }
1335 ZVAL_COPY_VALUE(¶ms[0], argument_ptr);
1336 ZVAL_COPY_VALUE(¶ms[1], argument2_ptr);
1337 }
1338
1339 /* Create object */
1340 if (object_init_ex(&reflector, ce_ptr) == FAILURE) {
1341 _DO_THROW("Could not create reflector");
1342 return;
1343 }
1344
1345 /* Call __construct() */
1346
1347 fci.size = sizeof(fci);
1348 ZVAL_UNDEF(&fci.function_name);
1349 fci.object = Z_OBJ(reflector);
1350 fci.retval = &retval;
1351 fci.param_count = ctor_argc;
1352 fci.params = params;
1353 fci.no_separation = 1;
1354
1355 fcc.function_handler = ce_ptr->constructor;
1356 fcc.called_scope = Z_OBJCE(reflector);
1357 fcc.object = Z_OBJ(reflector);
1358
1359 result = zend_call_function(&fci, &fcc);
1360
1361 zval_ptr_dtor(&retval);
1362
1363 if (EG(exception)) {
1364 zval_ptr_dtor(&reflector);
1365 return;
1366 }
1367 if (result == FAILURE) {
1368 zval_ptr_dtor(&reflector);
1369 _DO_THROW("Could not create reflector");
1370 return;
1371 }
1372
1373 reflection_export_impl(return_value, &reflector, return_output);
1374
1375 /* Destruct reflector which is no longer needed */
1376 zval_ptr_dtor(&reflector);
1377 }
1378 /* }}} */
1379
1380 /* {{{ _reflection_param_get_default_param */
_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)1381 static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)
1382 {
1383 reflection_object *intern;
1384 parameter_reference *param;
1385
1386 intern = Z_REFLECTION_P(ZEND_THIS);
1387 if (intern->ptr == NULL) {
1388 if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) {
1389 return NULL;
1390 }
1391 zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object");
1392 return NULL;
1393 }
1394
1395 param = intern->ptr;
1396 if (param->fptr->type != ZEND_USER_FUNCTION) {
1397 zend_throw_exception_ex(reflection_exception_ptr, 0, "Cannot determine default value for internal functions");
1398 return NULL;
1399 }
1400
1401 return param;
1402 }
1403 /* }}} */
1404
1405 /* {{{ _reflection_param_get_default_precv */
_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS,parameter_reference * param)1406 static zend_op *_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS, parameter_reference *param)
1407 {
1408 zend_op *precv;
1409
1410 if (param == NULL) {
1411 return NULL;
1412 }
1413
1414 precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
1415 if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
1416 zend_throw_exception_ex(reflection_exception_ptr, 0, "Internal error: Failed to retrieve the default value");
1417 return NULL;
1418 }
1419
1420 return precv;
1421 }
1422 /* }}} */
1423
1424 /* {{{ Preventing __clone from being called */
ZEND_METHOD(reflection,__clone)1425 ZEND_METHOD(reflection, __clone)
1426 {
1427 /* Should never be executable */
1428 _DO_THROW("Cannot clone object using __clone()");
1429 }
1430 /* }}} */
1431
1432 /* {{{ proto public static mixed Reflection::export(Reflector r [, bool return])
1433 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection,export)1434 ZEND_METHOD(reflection, export)
1435 {
1436 zval *object;
1437 zend_bool return_output = 0;
1438
1439 ZEND_PARSE_PARAMETERS_START(1, 2)
1440 Z_PARAM_OBJECT_OF_CLASS(object, reflector_ptr)
1441 Z_PARAM_OPTIONAL
1442 Z_PARAM_BOOL(return_output)
1443 ZEND_PARSE_PARAMETERS_END();
1444
1445 reflection_export_impl(return_value, object, return_output);
1446 }
1447 /* }}} */
1448
1449 /* {{{ proto public static array Reflection::getModifierNames(int modifiers)
1450 Returns an array of modifier names */
ZEND_METHOD(reflection,getModifierNames)1451 ZEND_METHOD(reflection, getModifierNames)
1452 {
1453 zend_long modifiers;
1454
1455 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &modifiers) == FAILURE) {
1456 return;
1457 }
1458
1459 array_init(return_value);
1460
1461 if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1462 add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1);
1463 }
1464 if (modifiers & ZEND_ACC_FINAL) {
1465 add_next_index_stringl(return_value, "final", sizeof("final")-1);
1466 }
1467
1468 /* These are mutually exclusive */
1469 switch (modifiers & ZEND_ACC_PPP_MASK) {
1470 case ZEND_ACC_PUBLIC:
1471 add_next_index_stringl(return_value, "public", sizeof("public")-1);
1472 break;
1473 case ZEND_ACC_PRIVATE:
1474 add_next_index_stringl(return_value, "private", sizeof("private")-1);
1475 break;
1476 case ZEND_ACC_PROTECTED:
1477 add_next_index_stringl(return_value, "protected", sizeof("protected")-1);
1478 break;
1479 }
1480
1481 if (modifiers & ZEND_ACC_STATIC) {
1482 add_next_index_stringl(return_value, "static", sizeof("static")-1);
1483 }
1484 }
1485 /* }}} */
1486
1487 /* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return])
1488 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_function,export)1489 ZEND_METHOD(reflection_function, export)
1490 {
1491 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_function_ptr, 1);
1492 }
1493 /* }}} */
1494
1495 /* {{{ proto public void ReflectionFunction::__construct(string name)
1496 Constructor. Throws an Exception in case the given function does not exist */
ZEND_METHOD(reflection_function,__construct)1497 ZEND_METHOD(reflection_function, __construct)
1498 {
1499 zval *object;
1500 zval *closure = NULL;
1501 reflection_object *intern;
1502 zend_function *fptr;
1503 zend_string *fname, *lcname;
1504
1505 object = ZEND_THIS;
1506 intern = Z_REFLECTION_P(object);
1507
1508 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &closure, zend_ce_closure) == SUCCESS) {
1509 fptr = (zend_function*)zend_get_closure_method_def(closure);
1510 Z_ADDREF_P(closure);
1511 } else {
1512 ALLOCA_FLAG(use_heap)
1513
1514 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "S", &fname) == FAILURE) {
1515 return;
1516 }
1517
1518 if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
1519 /* Ignore leading "\" */
1520 ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
1521 zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
1522 fptr = zend_fetch_function(lcname);
1523 ZSTR_ALLOCA_FREE(lcname, use_heap);
1524 } else {
1525 lcname = zend_string_tolower(fname);
1526 fptr = zend_fetch_function(lcname);
1527 zend_string_release(lcname);
1528 }
1529
1530 if (fptr == NULL) {
1531 zend_throw_exception_ex(reflection_exception_ptr, 0,
1532 "Function %s() does not exist", ZSTR_VAL(fname));
1533 return;
1534 }
1535 }
1536
1537 if (intern->ptr) {
1538 zval_ptr_dtor(&intern->obj);
1539 zval_ptr_dtor(reflection_prop_name(object));
1540 }
1541
1542 ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name);
1543 intern->ptr = fptr;
1544 intern->ref_type = REF_TYPE_FUNCTION;
1545 if (closure) {
1546 ZVAL_OBJ(&intern->obj, Z_OBJ_P(closure));
1547 } else {
1548 ZVAL_UNDEF(&intern->obj);
1549 }
1550 intern->ce = NULL;
1551 }
1552 /* }}} */
1553
1554 /* {{{ proto public string ReflectionFunction::__toString()
1555 Returns a string representation */
ZEND_METHOD(reflection_function,__toString)1556 ZEND_METHOD(reflection_function, __toString)
1557 {
1558 reflection_object *intern;
1559 zend_function *fptr;
1560 smart_str str = {0};
1561
1562 if (zend_parse_parameters_none() == FAILURE) {
1563 return;
1564 }
1565 GET_REFLECTION_OBJECT_PTR(fptr);
1566 _function_string(&str, fptr, intern->ce, "");
1567 RETURN_STR(smart_str_extract(&str));
1568 }
1569 /* }}} */
1570
1571 /* {{{ proto public string ReflectionFunction::getName()
1572 Returns this function's name */
ZEND_METHOD(reflection_function,getName)1573 ZEND_METHOD(reflection_function, getName)
1574 {
1575 if (zend_parse_parameters_none() == FAILURE) {
1576 return;
1577 }
1578 _default_get_name(ZEND_THIS, return_value);
1579 }
1580 /* }}} */
1581
1582 /* {{{ proto public bool ReflectionFunction::isClosure()
1583 Returns whether this is a closure */
ZEND_METHOD(reflection_function,isClosure)1584 ZEND_METHOD(reflection_function, isClosure)
1585 {
1586 reflection_object *intern;
1587 zend_function *fptr;
1588
1589 if (zend_parse_parameters_none() == FAILURE) {
1590 return;
1591 }
1592 GET_REFLECTION_OBJECT_PTR(fptr);
1593 RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
1594 }
1595 /* }}} */
1596
1597 /* {{{ proto public bool ReflectionFunction::getClosureThis()
1598 Returns this pointer bound to closure */
ZEND_METHOD(reflection_function,getClosureThis)1599 ZEND_METHOD(reflection_function, getClosureThis)
1600 {
1601 reflection_object *intern;
1602 zval* closure_this;
1603
1604 if (zend_parse_parameters_none() == FAILURE) {
1605 return;
1606 }
1607 GET_REFLECTION_OBJECT();
1608 if (!Z_ISUNDEF(intern->obj)) {
1609 closure_this = zend_get_closure_this_ptr(&intern->obj);
1610 if (!Z_ISUNDEF_P(closure_this)) {
1611 Z_ADDREF_P(closure_this);
1612 ZVAL_OBJ(return_value, Z_OBJ_P(closure_this));
1613 }
1614 }
1615 }
1616 /* }}} */
1617
1618 /* {{{ proto public ReflectionClass ReflectionFunction::getClosureScopeClass()
1619 Returns the scope associated to the closure */
ZEND_METHOD(reflection_function,getClosureScopeClass)1620 ZEND_METHOD(reflection_function, getClosureScopeClass)
1621 {
1622 reflection_object *intern;
1623 const zend_function *closure_func;
1624
1625 if (zend_parse_parameters_none() == FAILURE) {
1626 return;
1627 }
1628 GET_REFLECTION_OBJECT();
1629 if (!Z_ISUNDEF(intern->obj)) {
1630 closure_func = zend_get_closure_method_def(&intern->obj);
1631 if (closure_func && closure_func->common.scope) {
1632 zend_reflection_class_factory(closure_func->common.scope, return_value);
1633 }
1634 }
1635 }
1636 /* }}} */
1637
1638 /* {{{ proto public mixed ReflectionFunction::getClosure()
1639 Returns a dynamically created closure for the function */
ZEND_METHOD(reflection_function,getClosure)1640 ZEND_METHOD(reflection_function, getClosure)
1641 {
1642 reflection_object *intern;
1643 zend_function *fptr;
1644
1645 if (zend_parse_parameters_none() == FAILURE) {
1646 return;
1647 }
1648 GET_REFLECTION_OBJECT_PTR(fptr);
1649
1650 if (!Z_ISUNDEF(intern->obj)) {
1651 /* Closures are immutable objects */
1652 Z_ADDREF(intern->obj);
1653 ZVAL_OBJ(return_value, Z_OBJ(intern->obj));
1654 } else {
1655 zend_create_fake_closure(return_value, fptr, NULL, NULL, NULL);
1656 }
1657 }
1658 /* }}} */
1659
1660 /* {{{ proto public bool ReflectionFunction::isInternal()
1661 Returns whether this is an internal function */
ZEND_METHOD(reflection_function,isInternal)1662 ZEND_METHOD(reflection_function, isInternal)
1663 {
1664 reflection_object *intern;
1665 zend_function *fptr;
1666
1667 if (zend_parse_parameters_none() == FAILURE) {
1668 return;
1669 }
1670 GET_REFLECTION_OBJECT_PTR(fptr);
1671 RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
1672 }
1673 /* }}} */
1674
1675 /* {{{ proto public bool ReflectionFunction::isUserDefined()
1676 Returns whether this is a user-defined function */
ZEND_METHOD(reflection_function,isUserDefined)1677 ZEND_METHOD(reflection_function, isUserDefined)
1678 {
1679 reflection_object *intern;
1680 zend_function *fptr;
1681
1682 if (zend_parse_parameters_none() == FAILURE) {
1683 return;
1684 }
1685 GET_REFLECTION_OBJECT_PTR(fptr);
1686 RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
1687 }
1688 /* }}} */
1689
1690 /* {{{ proto public bool ReflectionFunction::isDisabled()
1691 Returns whether this function has been disabled or not */
ZEND_METHOD(reflection_function,isDisabled)1692 ZEND_METHOD(reflection_function, isDisabled)
1693 {
1694 reflection_object *intern;
1695 zend_function *fptr;
1696
1697 GET_REFLECTION_OBJECT_PTR(fptr);
1698 RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
1699 }
1700 /* }}} */
1701
1702 /* {{{ proto public string ReflectionFunction::getFileName()
1703 Returns the filename of the file this function was declared in */
ZEND_METHOD(reflection_function,getFileName)1704 ZEND_METHOD(reflection_function, getFileName)
1705 {
1706 reflection_object *intern;
1707 zend_function *fptr;
1708
1709 if (zend_parse_parameters_none() == FAILURE) {
1710 return;
1711 }
1712 GET_REFLECTION_OBJECT_PTR(fptr);
1713 if (fptr->type == ZEND_USER_FUNCTION) {
1714 RETURN_STR_COPY(fptr->op_array.filename);
1715 }
1716 RETURN_FALSE;
1717 }
1718 /* }}} */
1719
1720 /* {{{ proto public int ReflectionFunction::getStartLine()
1721 Returns the line this function's declaration starts at */
ZEND_METHOD(reflection_function,getStartLine)1722 ZEND_METHOD(reflection_function, getStartLine)
1723 {
1724 reflection_object *intern;
1725 zend_function *fptr;
1726
1727 if (zend_parse_parameters_none() == FAILURE) {
1728 return;
1729 }
1730 GET_REFLECTION_OBJECT_PTR(fptr);
1731 if (fptr->type == ZEND_USER_FUNCTION) {
1732 RETURN_LONG(fptr->op_array.line_start);
1733 }
1734 RETURN_FALSE;
1735 }
1736 /* }}} */
1737
1738 /* {{{ proto public int ReflectionFunction::getEndLine()
1739 Returns the line this function's declaration ends at */
ZEND_METHOD(reflection_function,getEndLine)1740 ZEND_METHOD(reflection_function, getEndLine)
1741 {
1742 reflection_object *intern;
1743 zend_function *fptr;
1744
1745 if (zend_parse_parameters_none() == FAILURE) {
1746 return;
1747 }
1748 GET_REFLECTION_OBJECT_PTR(fptr);
1749 if (fptr->type == ZEND_USER_FUNCTION) {
1750 RETURN_LONG(fptr->op_array.line_end);
1751 }
1752 RETURN_FALSE;
1753 }
1754 /* }}} */
1755
1756 /* {{{ proto public string ReflectionFunction::getDocComment()
1757 Returns the doc comment for this function */
ZEND_METHOD(reflection_function,getDocComment)1758 ZEND_METHOD(reflection_function, getDocComment)
1759 {
1760 reflection_object *intern;
1761 zend_function *fptr;
1762
1763 if (zend_parse_parameters_none() == FAILURE) {
1764 return;
1765 }
1766 GET_REFLECTION_OBJECT_PTR(fptr);
1767 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
1768 RETURN_STR_COPY(fptr->op_array.doc_comment);
1769 }
1770 RETURN_FALSE;
1771 }
1772 /* }}} */
1773
1774 /* {{{ proto public array ReflectionFunction::getStaticVariables()
1775 Returns an associative array containing this function's static variables and their values */
ZEND_METHOD(reflection_function,getStaticVariables)1776 ZEND_METHOD(reflection_function, getStaticVariables)
1777 {
1778 reflection_object *intern;
1779 zend_function *fptr;
1780 zval *val;
1781
1782 if (zend_parse_parameters_none() == FAILURE) {
1783 return;
1784 }
1785 GET_REFLECTION_OBJECT_PTR(fptr);
1786
1787 /* Return an empty array in case no static variables exist */
1788 if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
1789 HashTable *ht;
1790
1791 array_init(return_value);
1792 ht = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
1793 if (!ht) {
1794 ZEND_ASSERT(fptr->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
1795 ht = zend_array_dup(fptr->op_array.static_variables);
1796 ZEND_MAP_PTR_SET(fptr->op_array.static_variables_ptr, ht);
1797 }
1798 ZEND_HASH_FOREACH_VAL(ht, val) {
1799 if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) {
1800 return;
1801 }
1802 } ZEND_HASH_FOREACH_END();
1803 zend_hash_copy(Z_ARRVAL_P(return_value), ht, zval_add_ref);
1804 } else {
1805 RETURN_EMPTY_ARRAY();
1806 }
1807 }
1808 /* }}} */
1809
1810 /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args])
1811 Invokes the function */
ZEND_METHOD(reflection_function,invoke)1812 ZEND_METHOD(reflection_function, invoke)
1813 {
1814 zval retval;
1815 zval *params = NULL;
1816 int result, num_args = 0;
1817 zend_fcall_info fci;
1818 zend_fcall_info_cache fcc;
1819 reflection_object *intern;
1820 zend_function *fptr;
1821
1822 GET_REFLECTION_OBJECT_PTR(fptr);
1823
1824 if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", ¶ms, &num_args) == FAILURE) {
1825 return;
1826 }
1827
1828 fci.size = sizeof(fci);
1829 ZVAL_UNDEF(&fci.function_name);
1830 fci.object = NULL;
1831 fci.retval = &retval;
1832 fci.param_count = num_args;
1833 fci.params = params;
1834 fci.no_separation = 1;
1835
1836 fcc.function_handler = fptr;
1837 fcc.called_scope = NULL;
1838 fcc.object = NULL;
1839
1840 if (!Z_ISUNDEF(intern->obj)) {
1841 Z_OBJ_HT(intern->obj)->get_closure(
1842 &intern->obj, &fcc.called_scope, &fcc.function_handler, &fcc.object);
1843 }
1844
1845 result = zend_call_function(&fci, &fcc);
1846
1847 if (result == FAILURE) {
1848 zend_throw_exception_ex(reflection_exception_ptr, 0,
1849 "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
1850 return;
1851 }
1852
1853 if (Z_TYPE(retval) != IS_UNDEF) {
1854 if (Z_ISREF(retval)) {
1855 zend_unwrap_reference(&retval);
1856 }
1857 ZVAL_COPY_VALUE(return_value, &retval);
1858 }
1859 }
1860 /* }}} */
1861
1862 /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args)
1863 Invokes the function and pass its arguments as array. */
ZEND_METHOD(reflection_function,invokeArgs)1864 ZEND_METHOD(reflection_function, invokeArgs)
1865 {
1866 zval retval;
1867 zval *params, *val;
1868 int result;
1869 int i, argc;
1870 zend_fcall_info fci;
1871 zend_fcall_info_cache fcc;
1872 reflection_object *intern;
1873 zend_function *fptr;
1874 zval *param_array;
1875
1876 GET_REFLECTION_OBJECT_PTR(fptr);
1877
1878 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", ¶m_array) == FAILURE) {
1879 return;
1880 }
1881
1882 argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
1883
1884 params = safe_emalloc(sizeof(zval), argc, 0);
1885 argc = 0;
1886 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
1887 ZVAL_COPY(¶ms[argc], val);
1888 argc++;
1889 } ZEND_HASH_FOREACH_END();
1890
1891 fci.size = sizeof(fci);
1892 ZVAL_UNDEF(&fci.function_name);
1893 fci.object = NULL;
1894 fci.retval = &retval;
1895 fci.param_count = argc;
1896 fci.params = params;
1897 fci.no_separation = 1;
1898
1899 fcc.function_handler = fptr;
1900 fcc.called_scope = NULL;
1901 fcc.object = NULL;
1902
1903 if (!Z_ISUNDEF(intern->obj)) {
1904 Z_OBJ_HT(intern->obj)->get_closure(
1905 &intern->obj, &fcc.called_scope, &fcc.function_handler, &fcc.object);
1906 }
1907
1908 result = zend_call_function(&fci, &fcc);
1909
1910 for (i = 0; i < argc; i++) {
1911 zval_ptr_dtor(¶ms[i]);
1912 }
1913 efree(params);
1914
1915 if (result == FAILURE) {
1916 zend_throw_exception_ex(reflection_exception_ptr, 0,
1917 "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
1918 return;
1919 }
1920
1921 if (Z_TYPE(retval) != IS_UNDEF) {
1922 if (Z_ISREF(retval)) {
1923 zend_unwrap_reference(&retval);
1924 }
1925 ZVAL_COPY_VALUE(return_value, &retval);
1926 }
1927 }
1928 /* }}} */
1929
1930 /* {{{ proto public bool ReflectionFunction::returnsReference()
1931 Gets whether this function returns a reference */
ZEND_METHOD(reflection_function,returnsReference)1932 ZEND_METHOD(reflection_function, returnsReference)
1933 {
1934 reflection_object *intern;
1935 zend_function *fptr;
1936
1937 GET_REFLECTION_OBJECT_PTR(fptr);
1938
1939 RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
1940 }
1941 /* }}} */
1942
1943 /* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
1944 Gets the number of parameters */
ZEND_METHOD(reflection_function,getNumberOfParameters)1945 ZEND_METHOD(reflection_function, getNumberOfParameters)
1946 {
1947 reflection_object *intern;
1948 zend_function *fptr;
1949 uint32_t num_args;
1950
1951 GET_REFLECTION_OBJECT_PTR(fptr);
1952
1953 num_args = fptr->common.num_args;
1954 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
1955 num_args++;
1956 }
1957
1958 RETURN_LONG(num_args);
1959 }
1960 /* }}} */
1961
1962 /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
1963 Gets the number of required parameters */
ZEND_METHOD(reflection_function,getNumberOfRequiredParameters)1964 ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
1965 {
1966 reflection_object *intern;
1967 zend_function *fptr;
1968
1969 GET_REFLECTION_OBJECT_PTR(fptr);
1970
1971 RETURN_LONG(fptr->common.required_num_args);
1972 }
1973 /* }}} */
1974
1975 /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
1976 Returns an array of parameter objects for this function */
ZEND_METHOD(reflection_function,getParameters)1977 ZEND_METHOD(reflection_function, getParameters)
1978 {
1979 reflection_object *intern;
1980 zend_function *fptr;
1981 uint32_t i, num_args;
1982 struct _zend_arg_info *arg_info;
1983
1984 GET_REFLECTION_OBJECT_PTR(fptr);
1985
1986 arg_info= fptr->common.arg_info;
1987 num_args = fptr->common.num_args;
1988 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
1989 num_args++;
1990 }
1991
1992 if (!num_args) {
1993 RETURN_EMPTY_ARRAY();
1994 }
1995
1996 array_init(return_value);
1997 for (i = 0; i < num_args; i++) {
1998 zval parameter;
1999
2000 reflection_parameter_factory(
2001 _copy_function(fptr),
2002 Z_ISUNDEF(intern->obj) ? NULL : &intern->obj,
2003 arg_info,
2004 i,
2005 i < fptr->common.required_num_args,
2006 ¶meter
2007 );
2008 add_next_index_zval(return_value, ¶meter);
2009
2010 arg_info++;
2011 }
2012 }
2013 /* }}} */
2014
2015 /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension()
2016 Returns NULL or the extension the function belongs to */
ZEND_METHOD(reflection_function,getExtension)2017 ZEND_METHOD(reflection_function, getExtension)
2018 {
2019 reflection_object *intern;
2020 zend_function *fptr;
2021 zend_internal_function *internal;
2022
2023 GET_REFLECTION_OBJECT_PTR(fptr);
2024
2025 if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2026 RETURN_NULL();
2027 }
2028
2029 internal = (zend_internal_function *)fptr;
2030 if (internal->module) {
2031 reflection_extension_factory(return_value, internal->module->name);
2032 } else {
2033 RETURN_NULL();
2034 }
2035 }
2036 /* }}} */
2037
2038 /* {{{ proto public string|false ReflectionFunction::getExtensionName()
2039 Returns false or the name of the extension the function belongs to */
ZEND_METHOD(reflection_function,getExtensionName)2040 ZEND_METHOD(reflection_function, getExtensionName)
2041 {
2042 reflection_object *intern;
2043 zend_function *fptr;
2044 zend_internal_function *internal;
2045
2046 GET_REFLECTION_OBJECT_PTR(fptr);
2047
2048 if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2049 RETURN_FALSE;
2050 }
2051
2052 internal = (zend_internal_function *)fptr;
2053 if (internal->module) {
2054 RETURN_STRING(internal->module->name);
2055 } else {
2056 RETURN_FALSE;
2057 }
2058 }
2059 /* }}} */
2060
2061 /* {{{ proto public void ReflectionGenerator::__construct(object Generator) */
ZEND_METHOD(reflection_generator,__construct)2062 ZEND_METHOD(reflection_generator, __construct)
2063 {
2064 zval *generator, *object;
2065 reflection_object *intern;
2066 zend_execute_data *ex;
2067
2068 object = ZEND_THIS;
2069 intern = Z_REFLECTION_P(object);
2070
2071 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O", &generator, zend_ce_generator) == FAILURE) {
2072 return;
2073 }
2074
2075 ex = ((zend_generator *) Z_OBJ_P(generator))->execute_data;
2076 if (!ex) {
2077 _DO_THROW("Cannot create ReflectionGenerator based on a terminated Generator");
2078 return;
2079 }
2080
2081 if (intern->ce) {
2082 zval_ptr_dtor(&intern->obj);
2083 }
2084
2085 intern->ref_type = REF_TYPE_GENERATOR;
2086 Z_ADDREF_P(generator);
2087 ZVAL_OBJ(&intern->obj, Z_OBJ_P(generator));
2088 intern->ce = zend_ce_generator;
2089 }
2090 /* }}} */
2091
2092 #define REFLECTION_CHECK_VALID_GENERATOR(ex) \
2093 if (!ex) { \
2094 _DO_THROW("Cannot fetch information from a terminated Generator"); \
2095 return; \
2096 }
2097
2098 /* {{{ proto public array ReflectionGenerator::getTrace($options = DEBUG_BACKTRACE_PROVIDE_OBJECT) */
ZEND_METHOD(reflection_generator,getTrace)2099 ZEND_METHOD(reflection_generator, getTrace)
2100 {
2101 zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
2102 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2103 zend_generator *root_generator;
2104 zend_execute_data *ex_backup = EG(current_execute_data);
2105 zend_execute_data *ex = generator->execute_data;
2106 zend_execute_data *root_prev = NULL, *cur_prev;
2107
2108 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &options) == FAILURE) {
2109 return;
2110 }
2111
2112 REFLECTION_CHECK_VALID_GENERATOR(ex)
2113
2114 root_generator = zend_generator_get_current(generator);
2115
2116 cur_prev = generator->execute_data->prev_execute_data;
2117 if (generator == root_generator) {
2118 generator->execute_data->prev_execute_data = NULL;
2119 } else {
2120 root_prev = root_generator->execute_data->prev_execute_data;
2121 generator->execute_fake.prev_execute_data = NULL;
2122 root_generator->execute_data->prev_execute_data = &generator->execute_fake;
2123 }
2124
2125 EG(current_execute_data) = root_generator->execute_data;
2126 zend_fetch_debug_backtrace(return_value, 0, options, 0);
2127 EG(current_execute_data) = ex_backup;
2128
2129 root_generator->execute_data->prev_execute_data = root_prev;
2130 generator->execute_data->prev_execute_data = cur_prev;
2131 }
2132 /* }}} */
2133
2134 /* {{{ proto public int ReflectionGenerator::getExecutingLine() */
ZEND_METHOD(reflection_generator,getExecutingLine)2135 ZEND_METHOD(reflection_generator, getExecutingLine)
2136 {
2137 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2138 zend_execute_data *ex = generator->execute_data;
2139
2140 if (zend_parse_parameters_none() == FAILURE) {
2141 return;
2142 }
2143
2144 REFLECTION_CHECK_VALID_GENERATOR(ex)
2145
2146 ZVAL_LONG(return_value, ex->opline->lineno);
2147 }
2148 /* }}} */
2149
2150 /* {{{ proto public string ReflectionGenerator::getExecutingFile() */
ZEND_METHOD(reflection_generator,getExecutingFile)2151 ZEND_METHOD(reflection_generator, getExecutingFile)
2152 {
2153 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2154 zend_execute_data *ex = generator->execute_data;
2155
2156 if (zend_parse_parameters_none() == FAILURE) {
2157 return;
2158 }
2159
2160 REFLECTION_CHECK_VALID_GENERATOR(ex)
2161
2162 ZVAL_STR_COPY(return_value, ex->func->op_array.filename);
2163 }
2164 /* }}} */
2165
2166 /* {{{ proto public ReflectionFunctionAbstract ReflectionGenerator::getFunction() */
ZEND_METHOD(reflection_generator,getFunction)2167 ZEND_METHOD(reflection_generator, getFunction)
2168 {
2169 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2170 zend_execute_data *ex = generator->execute_data;
2171
2172 if (zend_parse_parameters_none() == FAILURE) {
2173 return;
2174 }
2175
2176 REFLECTION_CHECK_VALID_GENERATOR(ex)
2177
2178 if (ex->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2179 zval closure;
2180 ZVAL_OBJ(&closure, ZEND_CLOSURE_OBJECT(ex->func));
2181 reflection_function_factory(ex->func, &closure, return_value);
2182 } else if (ex->func->op_array.scope) {
2183 reflection_method_factory(ex->func->op_array.scope, ex->func, NULL, return_value);
2184 } else {
2185 reflection_function_factory(ex->func, NULL, return_value);
2186 }
2187 }
2188 /* }}} */
2189
2190 /* {{{ proto public object ReflectionGenerator::getThis() */
ZEND_METHOD(reflection_generator,getThis)2191 ZEND_METHOD(reflection_generator, getThis)
2192 {
2193 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2194 zend_execute_data *ex = generator->execute_data;
2195
2196 if (zend_parse_parameters_none() == FAILURE) {
2197 return;
2198 }
2199
2200 REFLECTION_CHECK_VALID_GENERATOR(ex)
2201
2202 if (Z_TYPE(ex->This) == IS_OBJECT) {
2203 Z_ADDREF(ex->This);
2204 ZVAL_OBJ(return_value, Z_OBJ(ex->This));
2205 } else {
2206 ZVAL_NULL(return_value);
2207 }
2208 }
2209 /* }}} */
2210
2211 /* {{{ proto public Generator ReflectionGenerator::getExecutingGenerator() */
ZEND_METHOD(reflection_generator,getExecutingGenerator)2212 ZEND_METHOD(reflection_generator, getExecutingGenerator)
2213 {
2214 zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(ZEND_THIS)->obj);
2215 zend_execute_data *ex = generator->execute_data;
2216 zend_generator *current;
2217
2218 if (zend_parse_parameters_none() == FAILURE) {
2219 return;
2220 }
2221
2222 REFLECTION_CHECK_VALID_GENERATOR(ex)
2223
2224 current = zend_generator_get_current(generator);
2225 GC_ADDREF(¤t->std);
2226
2227 ZVAL_OBJ(return_value, (zend_object *) current);
2228 }
2229 /* }}} */
2230
2231 /* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException
2232 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_parameter,export)2233 ZEND_METHOD(reflection_parameter, export)
2234 {
2235 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_parameter_ptr, 2);
2236 }
2237 /* }}} */
2238
2239 /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter)
2240 Constructor. Throws an Exception in case the given method does not exist */
ZEND_METHOD(reflection_parameter,__construct)2241 ZEND_METHOD(reflection_parameter, __construct)
2242 {
2243 parameter_reference *ref;
2244 zval *reference, *parameter;
2245 zval *object;
2246 zval *prop_name;
2247 reflection_object *intern;
2248 zend_function *fptr;
2249 struct _zend_arg_info *arg_info;
2250 int position;
2251 uint32_t num_args;
2252 zend_class_entry *ce = NULL;
2253 zend_bool is_closure = 0;
2254
2255 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zz", &reference, ¶meter) == FAILURE) {
2256 return;
2257 }
2258
2259 object = ZEND_THIS;
2260 intern = Z_REFLECTION_P(object);
2261
2262 /* First, find the function */
2263 switch (Z_TYPE_P(reference)) {
2264 case IS_STRING:
2265 {
2266 zend_string *lcname = zend_string_tolower(Z_STR_P(reference));
2267 fptr = zend_hash_find_ptr(EG(function_table), lcname);
2268 zend_string_release(lcname);
2269 if (!fptr) {
2270 zend_throw_exception_ex(reflection_exception_ptr, 0,
2271 "Function %s() does not exist", Z_STRVAL_P(reference));
2272 return;
2273 }
2274 ce = fptr->common.scope;
2275 }
2276 break;
2277
2278 case IS_ARRAY: {
2279 zval *classref;
2280 zval *method;
2281 zend_string *name, *lcname;
2282
2283 if (((classref = zend_hash_index_find(Z_ARRVAL_P(reference), 0)) == NULL)
2284 || ((method = zend_hash_index_find(Z_ARRVAL_P(reference), 1)) == NULL))
2285 {
2286 _DO_THROW("Expected array($object, $method) or array($classname, $method)");
2287 return;
2288 }
2289
2290 if (Z_TYPE_P(classref) == IS_OBJECT) {
2291 ce = Z_OBJCE_P(classref);
2292 } else {
2293 name = zval_try_get_string(classref);
2294 if (UNEXPECTED(!name)) {
2295 return;
2296 }
2297 if ((ce = zend_lookup_class(name)) == NULL) {
2298 zend_throw_exception_ex(reflection_exception_ptr, 0,
2299 "Class %s does not exist", ZSTR_VAL(name));
2300 zend_string_release(name);
2301 return;
2302 }
2303 zend_string_release(name);
2304 }
2305
2306 name = zval_try_get_string(method);
2307 if (UNEXPECTED(!name)) {
2308 return;
2309 }
2310
2311 lcname = zend_string_tolower(name);
2312 if (Z_TYPE_P(classref) == IS_OBJECT && is_closure_invoke(ce, lcname)
2313 && (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref))) != NULL)
2314 {
2315 /* nothing to do. don't set is_closure since is the invoke handler,
2316 not the closure itself */
2317 } else if ((fptr = zend_hash_find_ptr(&ce->function_table, lcname)) == NULL) {
2318 zend_throw_exception_ex(reflection_exception_ptr, 0,
2319 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
2320 zend_string_release(name);
2321 zend_string_release(lcname);
2322 return;
2323 }
2324 zend_string_release(name);
2325 zend_string_release(lcname);
2326 }
2327 break;
2328
2329 case IS_OBJECT: {
2330 ce = Z_OBJCE_P(reference);
2331
2332 if (instanceof_function(ce, zend_ce_closure)) {
2333 fptr = (zend_function *)zend_get_closure_method_def(reference);
2334 Z_ADDREF_P(reference);
2335 is_closure = 1;
2336 } else if ((fptr = zend_hash_find_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE))) == NULL) {
2337 zend_throw_exception_ex(reflection_exception_ptr, 0,
2338 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZEND_INVOKE_FUNC_NAME);
2339 return;
2340 }
2341 }
2342 break;
2343
2344 default:
2345 _DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
2346 return;
2347 }
2348
2349 /* Now, search for the parameter */
2350 arg_info = fptr->common.arg_info;
2351 num_args = fptr->common.num_args;
2352 if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2353 num_args++;
2354 }
2355 if (Z_TYPE_P(parameter) == IS_LONG) {
2356 position= (int)Z_LVAL_P(parameter);
2357 if (position < 0 || (uint32_t)position >= num_args) {
2358 _DO_THROW("The parameter specified by its offset could not be found");
2359 goto failure;
2360 }
2361 } else {
2362 uint32_t i;
2363
2364 position = -1;
2365 if (!try_convert_to_string(parameter)) {
2366 goto failure;
2367 }
2368
2369 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2370 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2371 for (i = 0; i < num_args; i++) {
2372 if (arg_info[i].name) {
2373 if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
2374 position = i;
2375 break;
2376 }
2377
2378 }
2379 }
2380 } else {
2381 for (i = 0; i < num_args; i++) {
2382 if (arg_info[i].name) {
2383 if (strcmp(ZSTR_VAL(arg_info[i].name), Z_STRVAL_P(parameter)) == 0) {
2384 position = i;
2385 break;
2386 }
2387 }
2388 }
2389 }
2390 if (position == -1) {
2391 _DO_THROW("The parameter specified by its name could not be found");
2392 goto failure;
2393 }
2394 }
2395
2396 ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
2397 ref->arg_info = &arg_info[position];
2398 ref->offset = (uint32_t)position;
2399 ref->required = (uint32_t)position < fptr->common.required_num_args;
2400 ref->fptr = fptr;
2401 /* TODO: copy fptr */
2402 intern->ptr = ref;
2403 intern->ref_type = REF_TYPE_PARAMETER;
2404 intern->ce = ce;
2405 if (reference && is_closure) {
2406 ZVAL_COPY_VALUE(&intern->obj, reference);
2407 }
2408
2409 prop_name = reflection_prop_name(object);
2410 if (arg_info[position].name) {
2411 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2412 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2413 ZVAL_STRING(prop_name, ((zend_internal_arg_info*)arg_info)[position].name);
2414 } else {
2415 ZVAL_STR_COPY(prop_name, arg_info[position].name);
2416 }
2417 } else {
2418 ZVAL_NULL(prop_name);
2419 }
2420 return;
2421
2422 failure:
2423 if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2424 if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
2425 zend_string_release_ex(fptr->common.function_name, 0);
2426 }
2427 zend_free_trampoline(fptr);
2428 }
2429 if (is_closure) {
2430 zval_ptr_dtor(reference);
2431 }
2432 }
2433 /* }}} */
2434
2435 /* {{{ proto public string ReflectionParameter::__toString()
2436 Returns a string representation */
ZEND_METHOD(reflection_parameter,__toString)2437 ZEND_METHOD(reflection_parameter, __toString)
2438 {
2439 reflection_object *intern;
2440 parameter_reference *param;
2441 smart_str str = {0};
2442
2443 if (zend_parse_parameters_none() == FAILURE) {
2444 return;
2445 }
2446 GET_REFLECTION_OBJECT_PTR(param);
2447 _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "");
2448 RETURN_STR(smart_str_extract(&str));
2449 }
2450
2451 /* }}} */
2452
2453 /* {{{ proto public string ReflectionParameter::getName()
2454 Returns this parameters's name */
ZEND_METHOD(reflection_parameter,getName)2455 ZEND_METHOD(reflection_parameter, getName)
2456 {
2457 if (zend_parse_parameters_none() == FAILURE) {
2458 return;
2459 }
2460 _default_get_name(ZEND_THIS, return_value);
2461 }
2462 /* }}} */
2463
2464 /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction()
2465 Returns the ReflectionFunction for the function of this parameter */
ZEND_METHOD(reflection_parameter,getDeclaringFunction)2466 ZEND_METHOD(reflection_parameter, getDeclaringFunction)
2467 {
2468 reflection_object *intern;
2469 parameter_reference *param;
2470
2471 if (zend_parse_parameters_none() == FAILURE) {
2472 return;
2473 }
2474 GET_REFLECTION_OBJECT_PTR(param);
2475
2476 if (!param->fptr->common.scope) {
2477 reflection_function_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2478 } else {
2479 reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2480 }
2481 }
2482 /* }}} */
2483
2484 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
2485 Returns in which class this parameter is defined (not the type of the parameter) */
ZEND_METHOD(reflection_parameter,getDeclaringClass)2486 ZEND_METHOD(reflection_parameter, getDeclaringClass)
2487 {
2488 reflection_object *intern;
2489 parameter_reference *param;
2490
2491 if (zend_parse_parameters_none() == FAILURE) {
2492 return;
2493 }
2494 GET_REFLECTION_OBJECT_PTR(param);
2495
2496 if (param->fptr->common.scope) {
2497 zend_reflection_class_factory(param->fptr->common.scope, return_value);
2498 }
2499 }
2500 /* }}} */
2501
2502 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass()
2503 Returns this parameters's class hint or NULL if there is none */
ZEND_METHOD(reflection_parameter,getClass)2504 ZEND_METHOD(reflection_parameter, getClass)
2505 {
2506 reflection_object *intern;
2507 parameter_reference *param;
2508 zend_class_entry *ce;
2509
2510 if (zend_parse_parameters_none() == FAILURE) {
2511 return;
2512 }
2513 GET_REFLECTION_OBJECT_PTR(param);
2514
2515 if (ZEND_TYPE_IS_CLASS(param->arg_info->type)) {
2516 /* Class name is stored as a string, we might also get "self" or "parent"
2517 * - For "self", simply use the function scope. If scope is NULL then
2518 * the function is global and thus self does not make any sense
2519 *
2520 * - For "parent", use the function scope's parent. If scope is NULL then
2521 * the function is global and thus parent does not make any sense.
2522 * If the parent is NULL then the class does not extend anything and
2523 * thus parent does not make any sense, either.
2524 *
2525 * TODO: Think about moving these checks to the compiler or some sort of
2526 * lint-mode.
2527 */
2528 zend_string *class_name;
2529
2530 class_name = ZEND_TYPE_NAME(param->arg_info->type);
2531 if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "self", sizeof("self")- 1)) {
2532 ce = param->fptr->common.scope;
2533 if (!ce) {
2534 zend_throw_exception_ex(reflection_exception_ptr, 0,
2535 "Parameter uses 'self' as type hint but function is not a class member!");
2536 return;
2537 }
2538 } else if (0 == zend_binary_strcasecmp(ZSTR_VAL(class_name), ZSTR_LEN(class_name), "parent", sizeof("parent")- 1)) {
2539 ce = param->fptr->common.scope;
2540 if (!ce) {
2541 zend_throw_exception_ex(reflection_exception_ptr, 0,
2542 "Parameter uses 'parent' as type hint but function is not a class member!");
2543 return;
2544 }
2545 if (!ce->parent) {
2546 zend_throw_exception_ex(reflection_exception_ptr, 0,
2547 "Parameter uses 'parent' as type hint although class does not have a parent!");
2548 return;
2549 }
2550 ce = ce->parent;
2551 } else {
2552 ce = zend_lookup_class(class_name);
2553 if (!ce) {
2554 zend_throw_exception_ex(reflection_exception_ptr, 0,
2555 "Class %s does not exist", ZSTR_VAL(class_name));
2556 return;
2557 }
2558 }
2559 zend_reflection_class_factory(ce, return_value);
2560 }
2561 }
2562 /* }}} */
2563
2564 /* {{{ proto public bool ReflectionParameter::hasType()
2565 Returns whether parameter has a type */
ZEND_METHOD(reflection_parameter,hasType)2566 ZEND_METHOD(reflection_parameter, hasType)
2567 {
2568 reflection_object *intern;
2569 parameter_reference *param;
2570
2571 if (zend_parse_parameters_none() == FAILURE) {
2572 return;
2573 }
2574 GET_REFLECTION_OBJECT_PTR(param);
2575
2576 RETVAL_BOOL(ZEND_TYPE_IS_SET(param->arg_info->type));
2577 }
2578 /* }}} */
2579
2580 /* {{{ proto public ReflectionType ReflectionParameter::getType()
2581 Returns the type associated with the parameter */
ZEND_METHOD(reflection_parameter,getType)2582 ZEND_METHOD(reflection_parameter, getType)
2583 {
2584 reflection_object *intern;
2585 parameter_reference *param;
2586
2587 if (zend_parse_parameters_none() == FAILURE) {
2588 return;
2589 }
2590 GET_REFLECTION_OBJECT_PTR(param);
2591
2592 if (!ZEND_TYPE_IS_SET(param->arg_info->type)) {
2593 RETURN_NULL();
2594 }
2595 reflection_type_factory(param->arg_info->type, return_value);
2596 }
2597 /* }}} */
2598
2599 /* {{{ proto public bool ReflectionParameter::isArray()
2600 Returns whether parameter MUST be an array */
ZEND_METHOD(reflection_parameter,isArray)2601 ZEND_METHOD(reflection_parameter, isArray)
2602 {
2603 reflection_object *intern;
2604 parameter_reference *param;
2605
2606 if (zend_parse_parameters_none() == FAILURE) {
2607 return;
2608 }
2609 GET_REFLECTION_OBJECT_PTR(param);
2610
2611 RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_ARRAY);
2612 }
2613 /* }}} */
2614
2615 /* {{{ proto public bool ReflectionParameter::isCallable()
2616 Returns whether parameter MUST be callable */
ZEND_METHOD(reflection_parameter,isCallable)2617 ZEND_METHOD(reflection_parameter, isCallable)
2618 {
2619 reflection_object *intern;
2620 parameter_reference *param;
2621
2622 if (zend_parse_parameters_none() == FAILURE) {
2623 return;
2624 }
2625 GET_REFLECTION_OBJECT_PTR(param);
2626
2627 RETVAL_BOOL(ZEND_TYPE_CODE(param->arg_info->type) == IS_CALLABLE);
2628 }
2629 /* }}} */
2630
2631 /* {{{ proto public bool ReflectionParameter::allowsNull()
2632 Returns whether NULL is allowed as this parameters's value */
ZEND_METHOD(reflection_parameter,allowsNull)2633 ZEND_METHOD(reflection_parameter, allowsNull)
2634 {
2635 reflection_object *intern;
2636 parameter_reference *param;
2637
2638 if (zend_parse_parameters_none() == FAILURE) {
2639 return;
2640 }
2641 GET_REFLECTION_OBJECT_PTR(param);
2642
2643 RETVAL_BOOL(ZEND_TYPE_ALLOW_NULL(param->arg_info->type));
2644 }
2645 /* }}} */
2646
2647 /* {{{ proto public bool ReflectionParameter::isPassedByReference()
2648 Returns whether this parameters is passed to by reference */
ZEND_METHOD(reflection_parameter,isPassedByReference)2649 ZEND_METHOD(reflection_parameter, isPassedByReference)
2650 {
2651 reflection_object *intern;
2652 parameter_reference *param;
2653
2654 if (zend_parse_parameters_none() == FAILURE) {
2655 return;
2656 }
2657 GET_REFLECTION_OBJECT_PTR(param);
2658
2659 RETVAL_BOOL(param->arg_info->pass_by_reference);
2660 }
2661 /* }}} */
2662
2663 /* {{{ proto public bool ReflectionParameter::canBePassedByValue()
2664 Returns whether this parameter can be passed by value */
ZEND_METHOD(reflection_parameter,canBePassedByValue)2665 ZEND_METHOD(reflection_parameter, canBePassedByValue)
2666 {
2667 reflection_object *intern;
2668 parameter_reference *param;
2669
2670 if (zend_parse_parameters_none() == FAILURE) {
2671 return;
2672 }
2673 GET_REFLECTION_OBJECT_PTR(param);
2674
2675 /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
2676 RETVAL_BOOL(param->arg_info->pass_by_reference != ZEND_SEND_BY_REF);
2677 }
2678 /* }}} */
2679
2680 /* {{{ proto public bool ReflectionParameter::getPosition()
2681 Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter,getPosition)2682 ZEND_METHOD(reflection_parameter, getPosition)
2683 {
2684 reflection_object *intern;
2685 parameter_reference *param;
2686
2687 if (zend_parse_parameters_none() == FAILURE) {
2688 return;
2689 }
2690 GET_REFLECTION_OBJECT_PTR(param);
2691
2692 RETVAL_LONG(param->offset);
2693 }
2694 /* }}} */
2695
2696 /* {{{ proto public bool ReflectionParameter::isOptional()
2697 Returns whether this parameter is an optional parameter */
ZEND_METHOD(reflection_parameter,isOptional)2698 ZEND_METHOD(reflection_parameter, isOptional)
2699 {
2700 reflection_object *intern;
2701 parameter_reference *param;
2702
2703 if (zend_parse_parameters_none() == FAILURE) {
2704 return;
2705 }
2706 GET_REFLECTION_OBJECT_PTR(param);
2707
2708 RETVAL_BOOL(!param->required);
2709 }
2710 /* }}} */
2711
2712 /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
2713 Returns whether the default value of this parameter is available */
ZEND_METHOD(reflection_parameter,isDefaultValueAvailable)2714 ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
2715 {
2716 reflection_object *intern;
2717 parameter_reference *param;
2718 zend_op *precv;
2719
2720 if (zend_parse_parameters_none() == FAILURE) {
2721 return;
2722 }
2723 GET_REFLECTION_OBJECT_PTR(param);
2724
2725 if (param->fptr->type != ZEND_USER_FUNCTION)
2726 {
2727 RETURN_FALSE;
2728 }
2729
2730 precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
2731 if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
2732 RETURN_FALSE;
2733 }
2734 RETURN_TRUE;
2735 }
2736 /* }}} */
2737
2738 /* {{{ proto public bool ReflectionParameter::getDefaultValue()
2739 Returns the default value of this parameter or throws an exception */
ZEND_METHOD(reflection_parameter,getDefaultValue)2740 ZEND_METHOD(reflection_parameter, getDefaultValue)
2741 {
2742 parameter_reference *param;
2743 zend_op *precv;
2744
2745 if (zend_parse_parameters_none() == FAILURE) {
2746 return;
2747 }
2748
2749 param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2750 if (!param) {
2751 return;
2752 }
2753
2754 precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2755 if (!precv) {
2756 return;
2757 }
2758
2759 ZVAL_COPY(return_value, RT_CONSTANT(precv, precv->op2));
2760 if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
2761 zval_update_constant_ex(return_value, param->fptr->common.scope);
2762 }
2763 }
2764 /* }}} */
2765
2766 /* {{{ proto public bool ReflectionParameter::isDefaultValueConstant()
2767 Returns whether the default value of this parameter is constant */
ZEND_METHOD(reflection_parameter,isDefaultValueConstant)2768 ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
2769 {
2770 zend_op *precv;
2771 parameter_reference *param;
2772
2773 if (zend_parse_parameters_none() == FAILURE) {
2774 return;
2775 }
2776
2777 param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2778 if (!param) {
2779 RETURN_FALSE;
2780 }
2781
2782 precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2783 if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) {
2784 zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2));
2785
2786 if (ast->kind == ZEND_AST_CONSTANT
2787 || ast->kind == ZEND_AST_CONSTANT_CLASS) {
2788 RETURN_TRUE;
2789 }
2790 }
2791
2792 RETURN_FALSE;
2793 }
2794 /* }}} */
2795
2796 /* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName()
2797 Returns the default value's constant name if default value is constant or null */
ZEND_METHOD(reflection_parameter,getDefaultValueConstantName)2798 ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
2799 {
2800 zend_op *precv;
2801 parameter_reference *param;
2802
2803 if (zend_parse_parameters_none() == FAILURE) {
2804 return;
2805 }
2806
2807 param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2808 if (!param) {
2809 return;
2810 }
2811
2812 precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2813 if (precv && Z_TYPE_P(RT_CONSTANT(precv, precv->op2)) == IS_CONSTANT_AST) {
2814 zend_ast *ast = Z_ASTVAL_P(RT_CONSTANT(precv, precv->op2));
2815
2816 if (ast->kind == ZEND_AST_CONSTANT) {
2817 RETURN_STR_COPY(zend_ast_get_constant_name(ast));
2818 } else if (ast->kind == ZEND_AST_CONSTANT_CLASS) {
2819 RETURN_STRINGL("__CLASS__", sizeof("__CLASS__")-1);
2820 }
2821 }
2822 }
2823 /* }}} */
2824
2825 /* {{{ proto public bool ReflectionParameter::isVariadic()
2826 Returns whether this parameter is a variadic parameter */
ZEND_METHOD(reflection_parameter,isVariadic)2827 ZEND_METHOD(reflection_parameter, isVariadic)
2828 {
2829 reflection_object *intern;
2830 parameter_reference *param;
2831
2832 if (zend_parse_parameters_none() == FAILURE) {
2833 return;
2834 }
2835 GET_REFLECTION_OBJECT_PTR(param);
2836
2837 RETVAL_BOOL(param->arg_info->is_variadic);
2838 }
2839 /* }}} */
2840
2841 /* {{{ proto public bool ReflectionType::allowsNull()
2842 Returns whether parameter MAY be null */
ZEND_METHOD(reflection_type,allowsNull)2843 ZEND_METHOD(reflection_type, allowsNull)
2844 {
2845 reflection_object *intern;
2846 type_reference *param;
2847
2848 if (zend_parse_parameters_none() == FAILURE) {
2849 return;
2850 }
2851 GET_REFLECTION_OBJECT_PTR(param);
2852
2853 RETVAL_BOOL(ZEND_TYPE_ALLOW_NULL(param->type));
2854 }
2855 /* }}} */
2856
2857 /* {{{ proto public bool ReflectionType::isBuiltin()
2858 Returns whether parameter is a builtin type */
ZEND_METHOD(reflection_type,isBuiltin)2859 ZEND_METHOD(reflection_type, isBuiltin)
2860 {
2861 reflection_object *intern;
2862 type_reference *param;
2863
2864 if (zend_parse_parameters_none() == FAILURE) {
2865 return;
2866 }
2867 GET_REFLECTION_OBJECT_PTR(param);
2868
2869 RETVAL_BOOL(ZEND_TYPE_IS_CODE(param->type));
2870 }
2871 /* }}} */
2872
2873 /* {{{ reflection_type_name */
reflection_type_name(type_reference * param)2874 static zend_string *reflection_type_name(type_reference *param) {
2875 if (ZEND_TYPE_IS_NAME(param->type)) {
2876 return zend_string_copy(ZEND_TYPE_NAME(param->type));
2877 } else if (ZEND_TYPE_IS_CE(param->type)) {
2878 return zend_string_copy(ZEND_TYPE_CE(param->type)->name);
2879 } else {
2880 char *name = zend_get_type_by_const(ZEND_TYPE_CODE(param->type));
2881 return zend_string_init(name, strlen(name), 0);
2882 }
2883 }
2884 /* }}} */
2885
2886 /* {{{ proto public string ReflectionType::__toString()
2887 Return the text of the type hint */
ZEND_METHOD(reflection_type,__toString)2888 ZEND_METHOD(reflection_type, __toString)
2889 {
2890 reflection_object *intern;
2891 type_reference *param;
2892
2893 if (zend_parse_parameters_none() == FAILURE) {
2894 return;
2895 }
2896 GET_REFLECTION_OBJECT_PTR(param);
2897
2898 RETURN_STR(reflection_type_name(param));
2899 }
2900 /* }}} */
2901
2902 /* {{{ proto public string ReflectionNamedType::getName()
2903 Return the text of the type hint */
ZEND_METHOD(reflection_named_type,getName)2904 ZEND_METHOD(reflection_named_type, getName)
2905 {
2906 reflection_object *intern;
2907 type_reference *param;
2908
2909 if (zend_parse_parameters_none() == FAILURE) {
2910 return;
2911 }
2912 GET_REFLECTION_OBJECT_PTR(param);
2913
2914 RETURN_STR(reflection_type_name(param));
2915 }
2916 /* }}} */
2917
2918 /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
2919 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_method,export)2920 ZEND_METHOD(reflection_method, export)
2921 {
2922 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_method_ptr, 2);
2923 }
2924 /* }}} */
2925
2926 /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name])
2927 Constructor. Throws an Exception in case the given method does not exist */
ZEND_METHOD(reflection_method,__construct)2928 ZEND_METHOD(reflection_method, __construct)
2929 {
2930 zval *classname;
2931 zval *object, *orig_obj;
2932 reflection_object *intern;
2933 char *lcname;
2934 zend_class_entry *ce;
2935 zend_function *mptr;
2936 char *name_str, *tmp;
2937 size_t name_len, tmp_len;
2938 zval ztmp;
2939
2940 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
2941 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
2942 return;
2943 }
2944
2945 if ((tmp = strstr(name_str, "::")) == NULL) {
2946 zend_throw_exception_ex(reflection_exception_ptr, 0,
2947 "Invalid method name %s", name_str);
2948 return;
2949 }
2950 classname = &ztmp;
2951 tmp_len = tmp - name_str;
2952 ZVAL_STRINGL(classname, name_str, tmp_len);
2953 name_len = name_len - (tmp_len + 2);
2954 name_str = tmp + 2;
2955 orig_obj = NULL;
2956 } else if (Z_TYPE_P(classname) == IS_OBJECT) {
2957 orig_obj = classname;
2958 } else {
2959 orig_obj = NULL;
2960 }
2961
2962 object = ZEND_THIS;
2963 intern = Z_REFLECTION_P(object);
2964
2965 /* Find the class entry */
2966 switch (Z_TYPE_P(classname)) {
2967 case IS_STRING:
2968 if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
2969 if (!EG(exception)) {
2970 zend_throw_exception_ex(reflection_exception_ptr, 0,
2971 "Class %s does not exist", Z_STRVAL_P(classname));
2972 }
2973 if (classname == &ztmp) {
2974 zval_ptr_dtor_str(&ztmp);
2975 }
2976 return;
2977 }
2978 break;
2979
2980 case IS_OBJECT:
2981 ce = Z_OBJCE_P(classname);
2982 break;
2983
2984 default:
2985 if (classname == &ztmp) {
2986 zval_ptr_dtor_str(&ztmp);
2987 }
2988 _DO_THROW("The parameter class is expected to be either a string or an object");
2989 return;
2990 }
2991
2992 if (classname == &ztmp) {
2993 zval_ptr_dtor_str(&ztmp);
2994 }
2995
2996 lcname = zend_str_tolower_dup(name_str, name_len);
2997
2998 if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
2999 && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
3000 && (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
3001 {
3002 /* do nothing, mptr already set */
3003 } else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
3004 efree(lcname);
3005 zend_throw_exception_ex(reflection_exception_ptr, 0,
3006 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), name_str);
3007 return;
3008 }
3009 efree(lcname);
3010
3011 ZVAL_STR_COPY(reflection_prop_name(object), mptr->common.function_name);
3012 ZVAL_STR_COPY(reflection_prop_class(object), mptr->common.scope->name);
3013 intern->ptr = mptr;
3014 intern->ref_type = REF_TYPE_FUNCTION;
3015 intern->ce = ce;
3016 }
3017 /* }}} */
3018
3019 /* {{{ proto public string ReflectionMethod::__toString()
3020 Returns a string representation */
ZEND_METHOD(reflection_method,__toString)3021 ZEND_METHOD(reflection_method, __toString)
3022 {
3023 reflection_object *intern;
3024 zend_function *mptr;
3025 smart_str str = {0};
3026
3027 if (zend_parse_parameters_none() == FAILURE) {
3028 return;
3029 }
3030 GET_REFLECTION_OBJECT_PTR(mptr);
3031 _function_string(&str, mptr, intern->ce, "");
3032 RETURN_STR(smart_str_extract(&str));
3033 }
3034 /* }}} */
3035
3036 /* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
3037 Invokes the function */
ZEND_METHOD(reflection_method,getClosure)3038 ZEND_METHOD(reflection_method, getClosure)
3039 {
3040 reflection_object *intern;
3041 zval *obj;
3042 zend_function *mptr;
3043
3044 GET_REFLECTION_OBJECT_PTR(mptr);
3045
3046 if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3047 zend_create_fake_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL);
3048 } else {
3049 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
3050 return;
3051 }
3052
3053 if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope)) {
3054 _DO_THROW("Given object is not an instance of the class this method was declared in");
3055 return;
3056 }
3057
3058 /* This is an original closure object and __invoke is to be called. */
3059 if (Z_OBJCE_P(obj) == zend_ce_closure &&
3060 (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
3061 {
3062 Z_ADDREF_P(obj);
3063 ZVAL_OBJ(return_value, Z_OBJ_P(obj));
3064 } else {
3065 zend_create_fake_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
3066 }
3067 }
3068 }
3069 /* }}} */
3070
3071 /* {{{ reflection_method_invoke */
reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS,int variadic)3072 static void reflection_method_invoke(INTERNAL_FUNCTION_PARAMETERS, int variadic)
3073 {
3074 zval retval;
3075 zval *params = NULL, *val, *object;
3076 reflection_object *intern;
3077 zend_function *mptr;
3078 int i, argc = 0, result;
3079 zend_fcall_info fci;
3080 zend_fcall_info_cache fcc;
3081 zend_class_entry *obj_ce;
3082 zval *param_array;
3083
3084 GET_REFLECTION_OBJECT_PTR(mptr);
3085
3086 if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
3087 zend_throw_exception_ex(reflection_exception_ptr, 0,
3088 "Trying to invoke abstract method %s::%s()",
3089 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3090 return;
3091 }
3092
3093 if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
3094 zend_throw_exception_ex(reflection_exception_ptr, 0,
3095 "Trying to invoke %s method %s::%s() from scope %s",
3096 mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
3097 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name),
3098 ZSTR_VAL(Z_OBJCE_P(ZEND_THIS)->name));
3099 return;
3100 }
3101
3102 if (variadic) {
3103 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!*", &object, ¶ms, &argc) == FAILURE) {
3104 return;
3105 }
3106 } else {
3107 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, ¶m_array) == FAILURE) {
3108 return;
3109 }
3110
3111 argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
3112
3113 params = safe_emalloc(sizeof(zval), argc, 0);
3114 argc = 0;
3115 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
3116 ZVAL_COPY(¶ms[argc], val);
3117 argc++;
3118 } ZEND_HASH_FOREACH_END();
3119 }
3120
3121 /* In case this is a static method, we shouldn't pass an object_ptr
3122 * (which is used as calling context aka $this). We can thus ignore the
3123 * first parameter.
3124 *
3125 * Else, we verify that the given object is an instance of the class.
3126 */
3127 if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3128 object = NULL;
3129 obj_ce = mptr->common.scope;
3130 } else {
3131 if (!object) {
3132 zend_throw_exception_ex(reflection_exception_ptr, 0,
3133 "Trying to invoke non static method %s::%s() without an object",
3134 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3135 return;
3136 }
3137
3138 obj_ce = Z_OBJCE_P(object);
3139
3140 if (!instanceof_function(obj_ce, mptr->common.scope)) {
3141 if (!variadic) {
3142 efree(params);
3143 }
3144 _DO_THROW("Given object is not an instance of the class this method was declared in");
3145 return;
3146 }
3147 }
3148
3149 fci.size = sizeof(fci);
3150 ZVAL_UNDEF(&fci.function_name);
3151 fci.object = object ? Z_OBJ_P(object) : NULL;
3152 fci.retval = &retval;
3153 fci.param_count = argc;
3154 fci.params = params;
3155 fci.no_separation = 1;
3156
3157 fcc.function_handler = mptr;
3158 fcc.called_scope = intern->ce;
3159 fcc.object = object ? Z_OBJ_P(object) : NULL;
3160
3161 /*
3162 * Copy the zend_function when calling via handler (e.g. Closure::__invoke())
3163 */
3164 if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3165 fcc.function_handler = _copy_function(mptr);
3166 }
3167
3168 result = zend_call_function(&fci, &fcc);
3169
3170 if (!variadic) {
3171 for (i = 0; i < argc; i++) {
3172 zval_ptr_dtor(¶ms[i]);
3173 }
3174 efree(params);
3175 }
3176
3177 if (result == FAILURE) {
3178 zend_throw_exception_ex(reflection_exception_ptr, 0,
3179 "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3180 return;
3181 }
3182
3183 if (Z_TYPE(retval) != IS_UNDEF) {
3184 if (Z_ISREF(retval)) {
3185 zend_unwrap_reference(&retval);
3186 }
3187 ZVAL_COPY_VALUE(return_value, &retval);
3188 }
3189 }
3190 /* }}} */
3191
3192 /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
3193 Invokes the method. */
ZEND_METHOD(reflection_method,invoke)3194 ZEND_METHOD(reflection_method, invoke)
3195 {
3196 reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3197 }
3198 /* }}} */
3199
3200 /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
3201 Invokes the function and pass its arguments as array. */
ZEND_METHOD(reflection_method,invokeArgs)3202 ZEND_METHOD(reflection_method, invokeArgs)
3203 {
3204 reflection_method_invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3205 }
3206 /* }}} */
3207
3208 /* {{{ proto public bool ReflectionMethod::isFinal()
3209 Returns whether this method is final */
ZEND_METHOD(reflection_method,isFinal)3210 ZEND_METHOD(reflection_method, isFinal)
3211 {
3212 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
3213 }
3214 /* }}} */
3215
3216 /* {{{ proto public bool ReflectionMethod::isAbstract()
3217 Returns whether this method is abstract */
ZEND_METHOD(reflection_method,isAbstract)3218 ZEND_METHOD(reflection_method, isAbstract)
3219 {
3220 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
3221 }
3222 /* }}} */
3223
3224 /* {{{ proto public bool ReflectionMethod::isPublic()
3225 Returns whether this method is public */
ZEND_METHOD(reflection_method,isPublic)3226 ZEND_METHOD(reflection_method, isPublic)
3227 {
3228 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
3229 }
3230 /* }}} */
3231
3232 /* {{{ proto public bool ReflectionMethod::isPrivate()
3233 Returns whether this method is private */
ZEND_METHOD(reflection_method,isPrivate)3234 ZEND_METHOD(reflection_method, isPrivate)
3235 {
3236 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
3237 }
3238 /* }}} */
3239
3240 /* {{{ proto public bool ReflectionMethod::isProtected()
3241 Returns whether this method is protected */
ZEND_METHOD(reflection_method,isProtected)3242 ZEND_METHOD(reflection_method, isProtected)
3243 {
3244 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
3245 }
3246 /* }}} */
3247
3248 /* {{{ proto public bool ReflectionMethod::isStatic()
3249 Returns whether this method is static */
ZEND_METHOD(reflection_method,isStatic)3250 ZEND_METHOD(reflection_method, isStatic)
3251 {
3252 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
3253 }
3254 /* }}} */
3255
3256 /* {{{ proto public bool ReflectionFunction::isDeprecated()
3257 Returns whether this function is deprecated */
ZEND_METHOD(reflection_function,isDeprecated)3258 ZEND_METHOD(reflection_function, isDeprecated)
3259 {
3260 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
3261 }
3262 /* }}} */
3263
3264 /* {{{ proto public bool ReflectionFunction::isGenerator()
3265 Returns whether this function is a generator */
ZEND_METHOD(reflection_function,isGenerator)3266 ZEND_METHOD(reflection_function, isGenerator)
3267 {
3268 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_GENERATOR);
3269 }
3270 /* }}} */
3271
3272 /* {{{ proto public bool ReflectionFunction::isVariadic()
3273 Returns whether this function is variadic */
ZEND_METHOD(reflection_function,isVariadic)3274 ZEND_METHOD(reflection_function, isVariadic)
3275 {
3276 _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_VARIADIC);
3277 }
3278 /* }}} */
3279
3280 /* {{{ proto public bool ReflectionFunction::inNamespace()
3281 Returns whether this function is defined in namespace */
ZEND_METHOD(reflection_function,inNamespace)3282 ZEND_METHOD(reflection_function, inNamespace)
3283 {
3284 zval *name;
3285 const char *backslash;
3286
3287 if (zend_parse_parameters_none() == FAILURE) {
3288 return;
3289 }
3290 if ((name = _default_load_name(ZEND_THIS)) == NULL) {
3291 RETURN_FALSE;
3292 }
3293 if (Z_TYPE_P(name) == IS_STRING
3294 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3295 && backslash > Z_STRVAL_P(name))
3296 {
3297 RETURN_TRUE;
3298 }
3299 RETURN_FALSE;
3300 }
3301 /* }}} */
3302
3303 /* {{{ proto public string ReflectionFunction::getNamespaceName()
3304 Returns the name of namespace where this function is defined */
ZEND_METHOD(reflection_function,getNamespaceName)3305 ZEND_METHOD(reflection_function, getNamespaceName)
3306 {
3307 zval *name;
3308 const char *backslash;
3309
3310 if (zend_parse_parameters_none() == FAILURE) {
3311 return;
3312 }
3313 if ((name = _default_load_name(ZEND_THIS)) == NULL) {
3314 RETURN_FALSE;
3315 }
3316 if (Z_TYPE_P(name) == IS_STRING
3317 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3318 && backslash > Z_STRVAL_P(name))
3319 {
3320 RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
3321 }
3322 RETURN_EMPTY_STRING();
3323 }
3324 /* }}} */
3325
3326 /* {{{ proto public string ReflectionFunction::getShortName()
3327 Returns the short name of the function (without namespace part) */
ZEND_METHOD(reflection_function,getShortName)3328 ZEND_METHOD(reflection_function, getShortName)
3329 {
3330 zval *name;
3331 const char *backslash;
3332
3333 if (zend_parse_parameters_none() == FAILURE) {
3334 return;
3335 }
3336 if ((name = _default_load_name(ZEND_THIS)) == NULL) {
3337 RETURN_FALSE;
3338 }
3339 if (Z_TYPE_P(name) == IS_STRING
3340 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3341 && backslash > Z_STRVAL_P(name))
3342 {
3343 RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
3344 }
3345 ZVAL_COPY_DEREF(return_value, name);
3346 }
3347 /* }}} */
3348
3349 /* {{{ proto public bool ReflectionFunctionAbstract:hasReturnType()
3350 Return whether the function has a return type */
ZEND_METHOD(reflection_function,hasReturnType)3351 ZEND_METHOD(reflection_function, hasReturnType)
3352 {
3353 reflection_object *intern;
3354 zend_function *fptr;
3355
3356 if (zend_parse_parameters_none() == FAILURE) {
3357 return;
3358 }
3359
3360 GET_REFLECTION_OBJECT_PTR(fptr);
3361
3362 RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
3363 }
3364 /* }}} */
3365
3366 /* {{{ proto public string ReflectionFunctionAbstract::getReturnType()
3367 Returns the return type associated with the function */
ZEND_METHOD(reflection_function,getReturnType)3368 ZEND_METHOD(reflection_function, getReturnType)
3369 {
3370 reflection_object *intern;
3371 zend_function *fptr;
3372
3373 if (zend_parse_parameters_none() == FAILURE) {
3374 return;
3375 }
3376
3377 GET_REFLECTION_OBJECT_PTR(fptr);
3378
3379 if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3380 RETURN_NULL();
3381 }
3382
3383 reflection_type_factory(fptr->common.arg_info[-1].type, return_value);
3384 }
3385 /* }}} */
3386
3387 /* {{{ proto public bool ReflectionMethod::isConstructor()
3388 Returns whether this method is the constructor */
ZEND_METHOD(reflection_method,isConstructor)3389 ZEND_METHOD(reflection_method, isConstructor)
3390 {
3391 reflection_object *intern;
3392 zend_function *mptr;
3393
3394 if (zend_parse_parameters_none() == FAILURE) {
3395 return;
3396 }
3397 GET_REFLECTION_OBJECT_PTR(mptr);
3398 /* we need to check if the ctor is the ctor of the class level we we
3399 * looking at since we might be looking at an inherited old style ctor
3400 * defined in base class. */
3401 RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
3402 }
3403 /* }}} */
3404
3405 /* {{{ proto public bool ReflectionMethod::isDestructor()
3406 Returns whether this method is static */
ZEND_METHOD(reflection_method,isDestructor)3407 ZEND_METHOD(reflection_method, isDestructor)
3408 {
3409 reflection_object *intern;
3410 zend_function *mptr;
3411
3412 if (zend_parse_parameters_none() == FAILURE) {
3413 return;
3414 }
3415 GET_REFLECTION_OBJECT_PTR(mptr);
3416 RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR);
3417 }
3418 /* }}} */
3419
3420 /* {{{ proto public int ReflectionMethod::getModifiers()
3421 Returns a bitfield of the access modifiers for this method */
ZEND_METHOD(reflection_method,getModifiers)3422 ZEND_METHOD(reflection_method, getModifiers)
3423 {
3424 reflection_object *intern;
3425 zend_function *mptr;
3426 uint32_t keep_flags = ZEND_ACC_PPP_MASK
3427 | ZEND_ACC_STATIC | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL;
3428
3429 if (zend_parse_parameters_none() == FAILURE) {
3430 return;
3431 }
3432 GET_REFLECTION_OBJECT_PTR(mptr);
3433
3434 RETURN_LONG((mptr->common.fn_flags & keep_flags));
3435 }
3436 /* }}} */
3437
3438 /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
3439 Get the declaring class */
ZEND_METHOD(reflection_method,getDeclaringClass)3440 ZEND_METHOD(reflection_method, getDeclaringClass)
3441 {
3442 reflection_object *intern;
3443 zend_function *mptr;
3444
3445 GET_REFLECTION_OBJECT_PTR(mptr);
3446
3447 if (zend_parse_parameters_none() == FAILURE) {
3448 return;
3449 }
3450
3451 zend_reflection_class_factory(mptr->common.scope, return_value);
3452 }
3453 /* }}} */
3454
3455 /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype()
3456 Get the prototype */
ZEND_METHOD(reflection_method,getPrototype)3457 ZEND_METHOD(reflection_method, getPrototype)
3458 {
3459 reflection_object *intern;
3460 zend_function *mptr;
3461
3462 GET_REFLECTION_OBJECT_PTR(mptr);
3463
3464 if (zend_parse_parameters_none() == FAILURE) {
3465 return;
3466 }
3467
3468 if (!mptr->common.prototype) {
3469 zend_throw_exception_ex(reflection_exception_ptr, 0,
3470 "Method %s::%s does not have a prototype", ZSTR_VAL(intern->ce->name), ZSTR_VAL(mptr->common.function_name));
3471 return;
3472 }
3473
3474 reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value);
3475 }
3476 /* }}} */
3477
3478 /* {{{ proto public void ReflectionMethod::setAccessible(bool visible)
3479 Sets whether non-public methods can be invoked */
ZEND_METHOD(reflection_method,setAccessible)3480 ZEND_METHOD(reflection_method, setAccessible)
3481 {
3482 reflection_object *intern;
3483 zend_bool visible;
3484
3485 if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
3486 return;
3487 }
3488
3489 intern = Z_REFLECTION_P(ZEND_THIS);
3490
3491 intern->ignore_visibility = visible;
3492 }
3493 /* }}} */
3494
3495 /* {{{ proto public void ReflectionClassConstant::__construct(mixed class, string name)
3496 Constructor. Throws an Exception in case the given class constant does not exist */
ZEND_METHOD(reflection_class_constant,__construct)3497 ZEND_METHOD(reflection_class_constant, __construct)
3498 {
3499 zval *classname, *object;
3500 zend_string *constname;
3501 reflection_object *intern;
3502 zend_class_entry *ce;
3503 zend_class_constant *constant = NULL;
3504
3505 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &constname) == FAILURE) {
3506 return;
3507 }
3508
3509 object = ZEND_THIS;
3510 intern = Z_REFLECTION_P(object);
3511
3512 /* Find the class entry */
3513 switch (Z_TYPE_P(classname)) {
3514 case IS_STRING:
3515 if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
3516 zend_throw_exception_ex(reflection_exception_ptr, 0,
3517 "Class %s does not exist", Z_STRVAL_P(classname));
3518 return;
3519 }
3520 break;
3521
3522 case IS_OBJECT:
3523 ce = Z_OBJCE_P(classname);
3524 break;
3525
3526 default:
3527 _DO_THROW("The parameter class is expected to be either a string or an object");
3528 return;
3529 }
3530
3531 if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
3532 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
3533 return;
3534 }
3535
3536 intern->ptr = constant;
3537 intern->ref_type = REF_TYPE_CLASS_CONSTANT;
3538 intern->ce = constant->ce;
3539 intern->ignore_visibility = 0;
3540 ZVAL_STR_COPY(reflection_prop_name(object), constname);
3541 ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
3542 }
3543 /* }}} */
3544
3545 /* {{{ proto public string ReflectionClassConstant::__toString()
3546 Returns a string representation */
ZEND_METHOD(reflection_class_constant,__toString)3547 ZEND_METHOD(reflection_class_constant, __toString)
3548 {
3549 reflection_object *intern;
3550 zend_class_constant *ref;
3551 smart_str str = {0};
3552 zval name;
3553
3554 if (zend_parse_parameters_none() == FAILURE) {
3555 return;
3556 }
3557 GET_REFLECTION_OBJECT_PTR(ref);
3558 _default_get_name(ZEND_THIS, &name);
3559 _class_const_string(&str, Z_STRVAL(name), ref, "");
3560 zval_ptr_dtor(&name);
3561 RETURN_STR(smart_str_extract(&str));
3562 }
3563 /* }}} */
3564
3565 /* {{{ proto public string ReflectionClassConstant::getName()
3566 Returns the constant' name */
ZEND_METHOD(reflection_class_constant,getName)3567 ZEND_METHOD(reflection_class_constant, getName)
3568 {
3569 if (zend_parse_parameters_none() == FAILURE) {
3570 return;
3571 }
3572 _default_get_name(ZEND_THIS, return_value);
3573 }
3574 /* }}} */
3575
_class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)3576 static void _class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
3577 {
3578 reflection_object *intern;
3579 zend_class_constant *ref;
3580
3581 if (zend_parse_parameters_none() == FAILURE) {
3582 return;
3583 }
3584 GET_REFLECTION_OBJECT_PTR(ref);
3585 RETURN_BOOL(Z_ACCESS_FLAGS(ref->value) & mask);
3586 }
3587 /* }}} */
3588
3589 /* {{{ proto public bool ReflectionClassConstant::isPublic()
3590 Returns whether this constant is public */
ZEND_METHOD(reflection_class_constant,isPublic)3591 ZEND_METHOD(reflection_class_constant, isPublic)
3592 {
3593 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
3594 }
3595 /* }}} */
3596
3597 /* {{{ proto public bool ReflectionClassConstant::isPrivate()
3598 Returns whether this constant is private */
ZEND_METHOD(reflection_class_constant,isPrivate)3599 ZEND_METHOD(reflection_class_constant, isPrivate)
3600 {
3601 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
3602 }
3603 /* }}} */
3604
3605 /* {{{ proto public bool ReflectionClassConstant::isProtected()
3606 Returns whether this constant is protected */
ZEND_METHOD(reflection_class_constant,isProtected)3607 ZEND_METHOD(reflection_class_constant, isProtected)
3608 {
3609 _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
3610 }
3611 /* }}} */
3612
3613 /* {{{ proto public int ReflectionClassConstant::getModifiers()
3614 Returns a bitfield of the access modifiers for this constant */
ZEND_METHOD(reflection_class_constant,getModifiers)3615 ZEND_METHOD(reflection_class_constant, getModifiers)
3616 {
3617 reflection_object *intern;
3618 zend_class_constant *ref;
3619
3620 if (zend_parse_parameters_none() == FAILURE) {
3621 return;
3622 }
3623 GET_REFLECTION_OBJECT_PTR(ref);
3624
3625 RETURN_LONG(Z_ACCESS_FLAGS(ref->value));
3626 }
3627 /* }}} */
3628
3629 /* {{{ proto public mixed ReflectionClassConstant::getValue()
3630 Returns this constant's value */
ZEND_METHOD(reflection_class_constant,getValue)3631 ZEND_METHOD(reflection_class_constant, getValue)
3632 {
3633 reflection_object *intern;
3634 zend_class_constant *ref;
3635
3636 if (zend_parse_parameters_none() == FAILURE) {
3637 return;
3638 }
3639 GET_REFLECTION_OBJECT_PTR(ref);
3640
3641 ZVAL_COPY_OR_DUP(return_value, &ref->value);
3642 if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
3643 zval_update_constant_ex(return_value, ref->ce);
3644 }
3645 }
3646 /* }}} */
3647
3648 /* {{{ proto public ReflectionClass ReflectionClassConstant::getDeclaringClass()
3649 Get the declaring class */
ZEND_METHOD(reflection_class_constant,getDeclaringClass)3650 ZEND_METHOD(reflection_class_constant, getDeclaringClass)
3651 {
3652 reflection_object *intern;
3653 zend_class_constant *ref;
3654
3655 if (zend_parse_parameters_none() == FAILURE) {
3656 return;
3657 }
3658 GET_REFLECTION_OBJECT_PTR(ref);
3659
3660 zend_reflection_class_factory(ref->ce, return_value);
3661 }
3662 /* }}} */
3663
3664 /* {{{ proto public string ReflectionClassConstant::getDocComment()
3665 Returns the doc comment for this constant */
ZEND_METHOD(reflection_class_constant,getDocComment)3666 ZEND_METHOD(reflection_class_constant, getDocComment)
3667 {
3668 reflection_object *intern;
3669 zend_class_constant *ref;
3670
3671 if (zend_parse_parameters_none() == FAILURE) {
3672 return;
3673 }
3674 GET_REFLECTION_OBJECT_PTR(ref);
3675 if (ref->doc_comment) {
3676 RETURN_STR_COPY(ref->doc_comment);
3677 }
3678 RETURN_FALSE;
3679 }
3680 /* }}} */
3681
3682 /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
3683 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class,export)3684 ZEND_METHOD(reflection_class, export)
3685 {
3686 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_ptr, 1);
3687 }
3688 /* }}} */
3689
3690 /* {{{ reflection_class_object_ctor */
reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS,int is_object)3691 static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
3692 {
3693 zval *argument;
3694 zval *object;
3695 reflection_object *intern;
3696 zend_class_entry *ce;
3697
3698 if (is_object) {
3699 ZEND_PARSE_PARAMETERS_START(1, 1)
3700 Z_PARAM_OBJECT(argument)
3701 ZEND_PARSE_PARAMETERS_END();
3702 } else {
3703 ZEND_PARSE_PARAMETERS_START(1, 1)
3704 Z_PARAM_ZVAL(argument)
3705 ZEND_PARSE_PARAMETERS_END();
3706 }
3707
3708 object = ZEND_THIS;
3709 intern = Z_REFLECTION_P(object);
3710
3711 if (Z_TYPE_P(argument) == IS_OBJECT) {
3712 ZVAL_STR_COPY(reflection_prop_name(object), Z_OBJCE_P(argument)->name);
3713 intern->ptr = Z_OBJCE_P(argument);
3714 if (is_object) {
3715 ZVAL_COPY(&intern->obj, argument);
3716 }
3717 } else {
3718 if (!try_convert_to_string(argument)) {
3719 return;
3720 }
3721
3722 if ((ce = zend_lookup_class(Z_STR_P(argument))) == NULL) {
3723 if (!EG(exception)) {
3724 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", Z_STRVAL_P(argument));
3725 }
3726 return;
3727 }
3728
3729 ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
3730 intern->ptr = ce;
3731 }
3732 intern->ref_type = REF_TYPE_OTHER;
3733 }
3734 /* }}} */
3735
3736 /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException
3737 Constructor. Takes a string or an instance as an argument */
ZEND_METHOD(reflection_class,__construct)3738 ZEND_METHOD(reflection_class, __construct)
3739 {
3740 reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3741 }
3742 /* }}} */
3743
3744 /* {{{ add_class_vars */
add_class_vars(zend_class_entry * ce,int statics,zval * return_value)3745 static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value)
3746 {
3747 zend_property_info *prop_info;
3748 zval *prop, prop_copy;
3749 zend_string *key;
3750
3751 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
3752 if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
3753 prop_info->ce != ce)) {
3754 continue;
3755 }
3756 prop = NULL;
3757 if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
3758 prop = &ce->default_static_members_table[prop_info->offset];
3759 ZVAL_DEINDIRECT(prop);
3760 } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
3761 prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
3762 }
3763 if (!prop || (prop_info->type && Z_ISUNDEF_P(prop))) {
3764 continue;
3765 }
3766
3767 /* copy: enforce read only access */
3768 ZVAL_DEREF(prop);
3769 ZVAL_COPY_OR_DUP(&prop_copy, prop);
3770
3771 /* this is necessary to make it able to work with default array
3772 * properties, returned to user */
3773 if (Z_TYPE(prop_copy) == IS_CONSTANT_AST) {
3774 if (UNEXPECTED(zval_update_constant_ex(&prop_copy, ce) != SUCCESS)) {
3775 return;
3776 }
3777 }
3778
3779 zend_hash_update(Z_ARRVAL_P(return_value), key, &prop_copy);
3780 } ZEND_HASH_FOREACH_END();
3781 }
3782 /* }}} */
3783
3784 /* {{{ proto public array ReflectionClass::getStaticProperties()
3785 Returns an associative array containing all static property values of the class */
ZEND_METHOD(reflection_class,getStaticProperties)3786 ZEND_METHOD(reflection_class, getStaticProperties)
3787 {
3788 reflection_object *intern;
3789 zend_class_entry *ce;
3790 zend_property_info *prop_info;
3791 zval *prop;
3792 zend_string *key;
3793
3794 if (zend_parse_parameters_none() == FAILURE) {
3795 return;
3796 }
3797
3798 GET_REFLECTION_OBJECT_PTR(ce);
3799
3800 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3801 return;
3802 }
3803
3804 if (ce->default_static_members_count && !CE_STATIC_MEMBERS(ce)) {
3805 zend_class_init_statics(ce);
3806 }
3807
3808 array_init(return_value);
3809
3810 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
3811 if (((prop_info->flags & ZEND_ACC_PRIVATE) &&
3812 prop_info->ce != ce)) {
3813 continue;
3814 }
3815 if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
3816 continue;
3817 }
3818
3819 prop = &CE_STATIC_MEMBERS(ce)[prop_info->offset];
3820 ZVAL_DEINDIRECT(prop);
3821
3822 if (prop_info->type && Z_ISUNDEF_P(prop)) {
3823 continue;
3824 }
3825
3826 /* enforce read only access */
3827 ZVAL_DEREF(prop);
3828 Z_TRY_ADDREF_P(prop);
3829
3830 zend_hash_update(Z_ARRVAL_P(return_value), key, prop);
3831 } ZEND_HASH_FOREACH_END();
3832 }
3833 /* }}} */
3834
3835 /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default])
3836 Returns the value of a static property */
ZEND_METHOD(reflection_class,getStaticPropertyValue)3837 ZEND_METHOD(reflection_class, getStaticPropertyValue)
3838 {
3839 reflection_object *intern;
3840 zend_class_entry *ce, *old_scope;
3841 zend_string *name;
3842 zval *prop, *def_value = NULL;
3843
3844 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &name, &def_value) == FAILURE) {
3845 return;
3846 }
3847
3848 GET_REFLECTION_OBJECT_PTR(ce);
3849
3850 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3851 return;
3852 }
3853
3854 old_scope = EG(fake_scope);
3855 EG(fake_scope) = ce;
3856 prop = zend_std_get_static_property(ce, name, BP_VAR_IS);
3857 EG(fake_scope) = old_scope;
3858
3859 if (!prop) {
3860 if (def_value) {
3861 ZVAL_COPY(return_value, def_value);
3862 } else {
3863 zend_throw_exception_ex(reflection_exception_ptr, 0,
3864 "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3865 }
3866 return;
3867 } else {
3868 ZVAL_COPY_DEREF(return_value, prop);
3869 }
3870 }
3871 /* }}} */
3872
3873 /* {{{ proto public void ReflectionClass::setStaticPropertyValue(string $name, mixed $value)
3874 Sets the value of a static property */
ZEND_METHOD(reflection_class,setStaticPropertyValue)3875 ZEND_METHOD(reflection_class, setStaticPropertyValue)
3876 {
3877 reflection_object *intern;
3878 zend_class_entry *ce, *old_scope;
3879 zend_property_info *prop_info;
3880 zend_string *name;
3881 zval *variable_ptr, *value;
3882
3883 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &name, &value) == FAILURE) {
3884 return;
3885 }
3886
3887 GET_REFLECTION_OBJECT_PTR(ce);
3888
3889 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3890 return;
3891 }
3892 old_scope = EG(fake_scope);
3893 EG(fake_scope) = ce;
3894 variable_ptr = zend_std_get_static_property_with_info(ce, name, BP_VAR_W, &prop_info);
3895 EG(fake_scope) = old_scope;
3896 if (!variable_ptr) {
3897 zend_clear_exception();
3898 zend_throw_exception_ex(reflection_exception_ptr, 0,
3899 "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3900 return;
3901 }
3902
3903 if (Z_ISREF_P(variable_ptr)) {
3904 zend_reference *ref = Z_REF_P(variable_ptr);
3905 variable_ptr = Z_REFVAL_P(variable_ptr);
3906
3907 if (!zend_verify_ref_assignable_zval(ref, value, 0)) {
3908 return;
3909 }
3910 }
3911
3912 if (prop_info->type && !zend_verify_property_type(prop_info, value, 0)) {
3913 return;
3914 }
3915
3916 zval_ptr_dtor(variable_ptr);
3917 ZVAL_COPY(variable_ptr, value);
3918
3919 }
3920 /* }}} */
3921
3922 /* {{{ proto public array ReflectionClass::getDefaultProperties()
3923 Returns an associative array containing copies of all default property values of the class */
ZEND_METHOD(reflection_class,getDefaultProperties)3924 ZEND_METHOD(reflection_class, getDefaultProperties)
3925 {
3926 reflection_object *intern;
3927 zend_class_entry *ce;
3928
3929 if (zend_parse_parameters_none() == FAILURE) {
3930 return;
3931 }
3932 GET_REFLECTION_OBJECT_PTR(ce);
3933 array_init(return_value);
3934 if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3935 return;
3936 }
3937 add_class_vars(ce, 1, return_value);
3938 add_class_vars(ce, 0, return_value);
3939 }
3940 /* }}} */
3941
3942 /* {{{ proto public string ReflectionClass::__toString()
3943 Returns a string representation */
ZEND_METHOD(reflection_class,__toString)3944 ZEND_METHOD(reflection_class, __toString)
3945 {
3946 reflection_object *intern;
3947 zend_class_entry *ce;
3948 smart_str str = {0};
3949
3950 if (zend_parse_parameters_none() == FAILURE) {
3951 return;
3952 }
3953 GET_REFLECTION_OBJECT_PTR(ce);
3954 _class_string(&str, ce, &intern->obj, "");
3955 RETURN_STR(smart_str_extract(&str));
3956 }
3957 /* }}} */
3958
3959 /* {{{ proto public string ReflectionClass::getName()
3960 Returns the class' name */
ZEND_METHOD(reflection_class,getName)3961 ZEND_METHOD(reflection_class, getName)
3962 {
3963 if (zend_parse_parameters_none() == FAILURE) {
3964 return;
3965 }
3966 _default_get_name(ZEND_THIS, return_value);
3967 }
3968 /* }}} */
3969
3970 /* {{{ proto public bool ReflectionClass::isInternal()
3971 Returns whether this class is an internal class */
ZEND_METHOD(reflection_class,isInternal)3972 ZEND_METHOD(reflection_class, isInternal)
3973 {
3974 reflection_object *intern;
3975 zend_class_entry *ce;
3976
3977 if (zend_parse_parameters_none() == FAILURE) {
3978 return;
3979 }
3980 GET_REFLECTION_OBJECT_PTR(ce);
3981 RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
3982 }
3983 /* }}} */
3984
3985 /* {{{ proto public bool ReflectionClass::isUserDefined()
3986 Returns whether this class is user-defined */
ZEND_METHOD(reflection_class,isUserDefined)3987 ZEND_METHOD(reflection_class, isUserDefined)
3988 {
3989 reflection_object *intern;
3990 zend_class_entry *ce;
3991
3992 if (zend_parse_parameters_none() == FAILURE) {
3993 return;
3994 }
3995 GET_REFLECTION_OBJECT_PTR(ce);
3996 RETURN_BOOL(ce->type == ZEND_USER_CLASS);
3997 }
3998 /* }}} */
3999
4000 /* {{{ proto public bool ReflectionClass::isAnonymous()
4001 Returns whether this class is anonymous */
ZEND_METHOD(reflection_class,isAnonymous)4002 ZEND_METHOD(reflection_class, isAnonymous)
4003 {
4004 reflection_object *intern;
4005 zend_class_entry *ce;
4006
4007 if (zend_parse_parameters_none() == FAILURE) {
4008 return;
4009 }
4010 GET_REFLECTION_OBJECT_PTR(ce);
4011 RETURN_BOOL(ce->ce_flags & ZEND_ACC_ANON_CLASS);
4012 }
4013 /* }}} */
4014
4015 /* {{{ proto public string ReflectionClass::getFileName()
4016 Returns the filename of the file this class was declared in */
ZEND_METHOD(reflection_class,getFileName)4017 ZEND_METHOD(reflection_class, getFileName)
4018 {
4019 reflection_object *intern;
4020 zend_class_entry *ce;
4021
4022 if (zend_parse_parameters_none() == FAILURE) {
4023 return;
4024 }
4025 GET_REFLECTION_OBJECT_PTR(ce);
4026 if (ce->type == ZEND_USER_CLASS) {
4027 RETURN_STR_COPY(ce->info.user.filename);
4028 }
4029 RETURN_FALSE;
4030 }
4031 /* }}} */
4032
4033 /* {{{ proto public int ReflectionClass::getStartLine()
4034 Returns the line this class' declaration starts at */
ZEND_METHOD(reflection_class,getStartLine)4035 ZEND_METHOD(reflection_class, getStartLine)
4036 {
4037 reflection_object *intern;
4038 zend_class_entry *ce;
4039
4040 if (zend_parse_parameters_none() == FAILURE) {
4041 return;
4042 }
4043 GET_REFLECTION_OBJECT_PTR(ce);
4044 if (ce->type == ZEND_USER_CLASS) {
4045 RETURN_LONG(ce->info.user.line_start);
4046 }
4047 RETURN_FALSE;
4048 }
4049 /* }}} */
4050
4051 /* {{{ proto public int ReflectionClass::getEndLine()
4052 Returns the line this class' declaration ends at */
ZEND_METHOD(reflection_class,getEndLine)4053 ZEND_METHOD(reflection_class, getEndLine)
4054 {
4055 reflection_object *intern;
4056 zend_class_entry *ce;
4057
4058 if (zend_parse_parameters_none() == FAILURE) {
4059 return;
4060 }
4061 GET_REFLECTION_OBJECT_PTR(ce);
4062 if (ce->type == ZEND_USER_CLASS) {
4063 RETURN_LONG(ce->info.user.line_end);
4064 }
4065 RETURN_FALSE;
4066 }
4067 /* }}} */
4068
4069 /* {{{ proto public string ReflectionClass::getDocComment()
4070 Returns the doc comment for this class */
ZEND_METHOD(reflection_class,getDocComment)4071 ZEND_METHOD(reflection_class, getDocComment)
4072 {
4073 reflection_object *intern;
4074 zend_class_entry *ce;
4075
4076 if (zend_parse_parameters_none() == FAILURE) {
4077 return;
4078 }
4079 GET_REFLECTION_OBJECT_PTR(ce);
4080 if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
4081 RETURN_STR_COPY(ce->info.user.doc_comment);
4082 }
4083 RETURN_FALSE;
4084 }
4085 /* }}} */
4086
4087 /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
4088 Returns the class' constructor if there is one, NULL otherwise */
ZEND_METHOD(reflection_class,getConstructor)4089 ZEND_METHOD(reflection_class, getConstructor)
4090 {
4091 reflection_object *intern;
4092 zend_class_entry *ce;
4093
4094 if (zend_parse_parameters_none() == FAILURE) {
4095 return;
4096 }
4097 GET_REFLECTION_OBJECT_PTR(ce);
4098
4099 if (ce->constructor) {
4100 reflection_method_factory(ce, ce->constructor, NULL, return_value);
4101 } else {
4102 RETURN_NULL();
4103 }
4104 }
4105 /* }}} */
4106
4107 /* {{{ proto public bool ReflectionClass::hasMethod(string name)
4108 Returns whether a method exists or not */
ZEND_METHOD(reflection_class,hasMethod)4109 ZEND_METHOD(reflection_class, hasMethod)
4110 {
4111 reflection_object *intern;
4112 zend_class_entry *ce;
4113 zend_string *name, *lc_name;
4114
4115 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4116 return;
4117 }
4118
4119 GET_REFLECTION_OBJECT_PTR(ce);
4120 lc_name = zend_string_tolower(name);
4121 RETVAL_BOOL(zend_hash_exists(&ce->function_table, lc_name) || is_closure_invoke(ce, lc_name));
4122 zend_string_release(lc_name);
4123 }
4124 /* }}} */
4125
4126 /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
4127 Returns the class' method specified by its name */
ZEND_METHOD(reflection_class,getMethod)4128 ZEND_METHOD(reflection_class, getMethod)
4129 {
4130 reflection_object *intern;
4131 zend_class_entry *ce;
4132 zend_function *mptr;
4133 zval obj_tmp;
4134 zend_string *name, *lc_name;
4135
4136 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4137 return;
4138 }
4139
4140 GET_REFLECTION_OBJECT_PTR(ce);
4141 lc_name = zend_string_tolower(name);
4142 if (!Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
4143 && (mptr = zend_get_closure_invoke_method(Z_OBJ(intern->obj))) != NULL)
4144 {
4145 /* don't assign closure_object since we only reflect the invoke handler
4146 method and not the closure definition itself */
4147 reflection_method_factory(ce, mptr, NULL, return_value);
4148 } else if (Z_ISUNDEF(intern->obj) && is_closure_invoke(ce, lc_name)
4149 && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(Z_OBJ(obj_tmp))) != NULL) {
4150 /* don't assign closure_object since we only reflect the invoke handler
4151 method and not the closure definition itself */
4152 reflection_method_factory(ce, mptr, NULL, return_value);
4153 zval_ptr_dtor(&obj_tmp);
4154 } else if ((mptr = zend_hash_find_ptr(&ce->function_table, lc_name)) != NULL) {
4155 reflection_method_factory(ce, mptr, NULL, return_value);
4156 } else {
4157 zend_throw_exception_ex(reflection_exception_ptr, 0,
4158 "Method %s does not exist", ZSTR_VAL(name));
4159 }
4160 zend_string_release(lc_name);
4161 }
4162 /* }}} */
4163
4164 /* {{{ _addmethod */
_addmethod(zend_function * mptr,zend_class_entry * ce,zval * retval,zend_long filter)4165 static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter)
4166 {
4167 if (mptr->common.fn_flags & filter) {
4168 zval method;
4169 reflection_method_factory(ce, mptr, NULL, &method);
4170 add_next_index_zval(retval, &method);
4171 }
4172 }
4173 /* }}} */
4174
4175 /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter])
4176 Returns an array of this class' methods */
ZEND_METHOD(reflection_class,getMethods)4177 ZEND_METHOD(reflection_class, getMethods)
4178 {
4179 reflection_object *intern;
4180 zend_class_entry *ce;
4181 zend_function *mptr;
4182 zend_long filter = 0;
4183 zend_bool filter_is_null = 1;
4184
4185 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4186 return;
4187 }
4188
4189 if (filter_is_null) {
4190 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
4191 }
4192
4193 GET_REFLECTION_OBJECT_PTR(ce);
4194
4195 array_init(return_value);
4196 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
4197 _addmethod(mptr, ce, return_value, filter);
4198 } ZEND_HASH_FOREACH_END();
4199
4200 if (instanceof_function(ce, zend_ce_closure)) {
4201 zend_bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
4202 zval obj_tmp;
4203 zend_object *obj;
4204 if (!has_obj) {
4205 object_init_ex(&obj_tmp, ce);
4206 obj = Z_OBJ(obj_tmp);
4207 } else {
4208 obj = Z_OBJ(intern->obj);
4209 }
4210 zend_function *closure = zend_get_closure_invoke_method(obj);
4211 if (closure) {
4212 _addmethod(closure, ce, return_value, filter);
4213 }
4214 if (!has_obj) {
4215 zval_ptr_dtor(&obj_tmp);
4216 }
4217 }
4218 }
4219 /* }}} */
4220
4221 /* {{{ proto public bool ReflectionClass::hasProperty(string name)
4222 Returns whether a property exists or not */
ZEND_METHOD(reflection_class,hasProperty)4223 ZEND_METHOD(reflection_class, hasProperty)
4224 {
4225 reflection_object *intern;
4226 zend_property_info *property_info;
4227 zend_class_entry *ce;
4228 zend_string *name;
4229 zval property;
4230
4231 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4232 return;
4233 }
4234
4235 GET_REFLECTION_OBJECT_PTR(ce);
4236 if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4237 if ((property_info->flags & ZEND_ACC_PRIVATE) && property_info->ce != ce) {
4238 RETURN_FALSE;
4239 }
4240 RETURN_TRUE;
4241 } else {
4242 if (Z_TYPE(intern->obj) != IS_UNDEF) {
4243 ZVAL_STR_COPY(&property, name);
4244 if (Z_OBJ_HANDLER(intern->obj, has_property)(&intern->obj, &property, 2, NULL)) {
4245 zval_ptr_dtor(&property);
4246 RETURN_TRUE;
4247 }
4248 zval_ptr_dtor(&property);
4249 }
4250 RETURN_FALSE;
4251 }
4252 }
4253 /* }}} */
4254
4255 /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
4256 Returns the class' property specified by its name */
ZEND_METHOD(reflection_class,getProperty)4257 ZEND_METHOD(reflection_class, getProperty)
4258 {
4259 reflection_object *intern;
4260 zend_class_entry *ce, *ce2;
4261 zend_property_info *property_info;
4262 zend_string *name, *classname;
4263 char *tmp, *str_name;
4264 size_t classname_len, str_name_len;
4265
4266 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4267 return;
4268 }
4269
4270 GET_REFLECTION_OBJECT_PTR(ce);
4271 if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4272 if (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce) {
4273 reflection_property_factory(ce, name, property_info, return_value, 0);
4274 return;
4275 }
4276 } else if (Z_TYPE(intern->obj) != IS_UNDEF) {
4277 /* Check for dynamic properties */
4278 if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(&intern->obj), name)) {
4279 zend_property_info property_info_tmp;
4280 property_info_tmp.flags = ZEND_ACC_PUBLIC;
4281 property_info_tmp.name = name;
4282 property_info_tmp.doc_comment = NULL;
4283 property_info_tmp.ce = ce;
4284 property_info_tmp.type = 0;
4285
4286 reflection_property_factory(ce, name, &property_info_tmp, return_value, 1);
4287 return;
4288 }
4289 }
4290 str_name = ZSTR_VAL(name);
4291 if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) {
4292 classname_len = tmp - ZSTR_VAL(name);
4293 classname = zend_string_alloc(classname_len, 0);
4294 zend_str_tolower_copy(ZSTR_VAL(classname), ZSTR_VAL(name), classname_len);
4295 ZSTR_VAL(classname)[classname_len] = '\0';
4296 str_name_len = ZSTR_LEN(name) - (classname_len + 2);
4297 str_name = tmp + 2;
4298
4299 ce2 = zend_lookup_class(classname);
4300 if (!ce2) {
4301 if (!EG(exception)) {
4302 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", ZSTR_VAL(classname));
4303 }
4304 zend_string_release_ex(classname, 0);
4305 return;
4306 }
4307 zend_string_release_ex(classname, 0);
4308
4309 if (!instanceof_function(ce, ce2)) {
4310 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));
4311 return;
4312 }
4313 ce = ce2;
4314
4315 property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len);
4316 if (property_info != NULL
4317 && (!(property_info->flags & ZEND_ACC_PRIVATE)
4318 || property_info->ce == ce)) {
4319 reflection_property_factory_str(ce, str_name, str_name_len, property_info, return_value);
4320 return;
4321 }
4322 }
4323 zend_throw_exception_ex(reflection_exception_ptr, 0,
4324 "Property %s does not exist", str_name);
4325 }
4326 /* }}} */
4327
4328 /* {{{ _addproperty */
_addproperty(zend_property_info * pptr,zend_string * key,zend_class_entry * ce,zval * retval,long filter)4329 static void _addproperty(zend_property_info *pptr, zend_string *key, zend_class_entry *ce, zval *retval, long filter)
4330 {
4331 if ((pptr->flags & ZEND_ACC_PRIVATE) && pptr->ce != ce) {
4332 return;
4333 }
4334
4335 if (pptr->flags & filter) {
4336 zval property;
4337 reflection_property_factory(ce, key, pptr, &property, 0);
4338 add_next_index_zval(retval, &property);
4339 }
4340 }
4341 /* }}} */
4342
4343 /* {{{ _adddynproperty */
_adddynproperty(zval * ptr,zend_string * key,zend_class_entry * ce,zval * retval)4344 static void _adddynproperty(zval *ptr, zend_string *key, zend_class_entry *ce, zval *retval)
4345 {
4346 zend_property_info property_info;
4347 zval property;
4348
4349 /* under some circumstances, the properties hash table may contain numeric
4350 * properties (e.g. when casting from array). This is a WON'T FIX bug, at
4351 * least for the moment. Ignore these */
4352 if (key == NULL) {
4353 return;
4354 }
4355
4356 /* Not a dynamic property */
4357 if (Z_TYPE_P(ptr) == IS_INDIRECT) {
4358 return;
4359 }
4360
4361 property_info.doc_comment = NULL;
4362 property_info.flags = ZEND_ACC_PUBLIC;
4363 property_info.name = key;
4364 property_info.ce = ce;
4365 property_info.offset = -1;
4366 property_info.type = 0;
4367 reflection_property_factory(ce, key, &property_info, &property, 1);
4368 add_next_index_zval(retval, &property);
4369 }
4370 /* }}} */
4371
4372 /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter])
4373 Returns an array of this class' properties */
ZEND_METHOD(reflection_class,getProperties)4374 ZEND_METHOD(reflection_class, getProperties)
4375 {
4376 reflection_object *intern;
4377 zend_class_entry *ce;
4378 zend_string *key;
4379 zend_property_info *prop_info;
4380 zend_long filter = 0;
4381 zend_bool filter_is_null = 1;
4382
4383 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
4384 return;
4385 }
4386
4387 if (filter_is_null) {
4388 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
4389 }
4390
4391 GET_REFLECTION_OBJECT_PTR(ce);
4392
4393 array_init(return_value);
4394 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
4395 _addproperty(prop_info, key, ce, return_value, filter);
4396 } ZEND_HASH_FOREACH_END();
4397
4398 if (Z_TYPE(intern->obj) != IS_UNDEF && (filter & ZEND_ACC_PUBLIC) != 0) {
4399 HashTable *properties = Z_OBJ_HT(intern->obj)->get_properties(&intern->obj);
4400 zval *prop;
4401 ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
4402 _adddynproperty(prop, key, ce, return_value);
4403 } ZEND_HASH_FOREACH_END();
4404 }
4405 }
4406 /* }}} */
4407
4408 /* {{{ proto public bool ReflectionClass::hasConstant(string name)
4409 Returns whether a constant exists or not */
ZEND_METHOD(reflection_class,hasConstant)4410 ZEND_METHOD(reflection_class, hasConstant)
4411 {
4412 reflection_object *intern;
4413 zend_class_entry *ce;
4414 zend_string *name;
4415
4416 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4417 return;
4418 }
4419
4420 GET_REFLECTION_OBJECT_PTR(ce);
4421 if (zend_hash_exists(&ce->constants_table, name)) {
4422 RETURN_TRUE;
4423 } else {
4424 RETURN_FALSE;
4425 }
4426 }
4427 /* }}} */
4428
4429 /* {{{ proto public array ReflectionClass::getConstants()
4430 Returns an associative array containing this class' constants and their values */
ZEND_METHOD(reflection_class,getConstants)4431 ZEND_METHOD(reflection_class, getConstants)
4432 {
4433 reflection_object *intern;
4434 zend_class_entry *ce;
4435 zend_string *key;
4436 zend_class_constant *c;
4437 zval val;
4438
4439 if (zend_parse_parameters_none() == FAILURE) {
4440 return;
4441 }
4442 GET_REFLECTION_OBJECT_PTR(ce);
4443 array_init(return_value);
4444 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
4445 if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
4446 zend_array_destroy(Z_ARRVAL_P(return_value));
4447 RETURN_NULL();
4448 }
4449 ZVAL_COPY_OR_DUP(&val, &c->value);
4450 zend_hash_add_new(Z_ARRVAL_P(return_value), key, &val);
4451 } ZEND_HASH_FOREACH_END();
4452 }
4453 /* }}} */
4454
4455 /* {{{ proto public array ReflectionClass::getReflectionConstants()
4456 Returns an associative array containing this class' constants as ReflectionClassConstant objects */
ZEND_METHOD(reflection_class,getReflectionConstants)4457 ZEND_METHOD(reflection_class, getReflectionConstants)
4458 {
4459 reflection_object *intern;
4460 zend_class_entry *ce;
4461 zend_string *name;
4462 zend_class_constant *constant;
4463
4464 if (zend_parse_parameters_none() == FAILURE) {
4465 return;
4466 }
4467 GET_REFLECTION_OBJECT_PTR(ce);
4468 array_init(return_value);
4469 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
4470 zval class_const;
4471 reflection_class_constant_factory(ce, name, constant, &class_const);
4472 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
4473 } ZEND_HASH_FOREACH_END();
4474 }
4475 /* }}} */
4476
4477 /* {{{ proto public mixed ReflectionClass::getConstant(string name)
4478 Returns the class' constant specified by its name */
ZEND_METHOD(reflection_class,getConstant)4479 ZEND_METHOD(reflection_class, getConstant)
4480 {
4481 reflection_object *intern;
4482 zend_class_entry *ce;
4483 zend_class_constant *c;
4484 zend_string *name;
4485
4486 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4487 return;
4488 }
4489
4490 GET_REFLECTION_OBJECT_PTR(ce);
4491 ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
4492 if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
4493 return;
4494 }
4495 } ZEND_HASH_FOREACH_END();
4496 if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
4497 RETURN_FALSE;
4498 }
4499 ZVAL_COPY_OR_DUP(return_value, &c->value);
4500 }
4501 /* }}} */
4502
4503 /* {{{ proto public mixed ReflectionClass::getReflectionConstant(string name)
4504 Returns the class' constant as ReflectionClassConstant objects */
ZEND_METHOD(reflection_class,getReflectionConstant)4505 ZEND_METHOD(reflection_class, getReflectionConstant)
4506 {
4507 reflection_object *intern;
4508 zend_class_entry *ce;
4509 zend_class_constant *constant;
4510 zend_string *name;
4511
4512 GET_REFLECTION_OBJECT_PTR(ce);
4513 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4514 return;
4515 }
4516
4517 if ((constant = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
4518 RETURN_FALSE;
4519 }
4520 reflection_class_constant_factory(ce, name, constant, return_value);
4521 }
4522 /* }}} */
4523
4524 /* {{{ _class_check_flag */
_class_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)4525 static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
4526 {
4527 reflection_object *intern;
4528 zend_class_entry *ce;
4529
4530 if (zend_parse_parameters_none() == FAILURE) {
4531 return;
4532 }
4533 GET_REFLECTION_OBJECT_PTR(ce);
4534 RETVAL_BOOL(ce->ce_flags & mask);
4535 }
4536 /* }}} */
4537
4538 /* {{{ proto public bool ReflectionClass::isInstantiable()
4539 Returns whether this class is instantiable */
ZEND_METHOD(reflection_class,isInstantiable)4540 ZEND_METHOD(reflection_class, isInstantiable)
4541 {
4542 reflection_object *intern;
4543 zend_class_entry *ce;
4544
4545 if (zend_parse_parameters_none() == FAILURE) {
4546 return;
4547 }
4548 GET_REFLECTION_OBJECT_PTR(ce);
4549 if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4550 RETURN_FALSE;
4551 }
4552
4553 /* Basically, the class is instantiable. Though, if there is a constructor
4554 * and it is not publicly accessible, it isn't! */
4555 if (!ce->constructor) {
4556 RETURN_TRUE;
4557 }
4558
4559 RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
4560 }
4561 /* }}} */
4562
4563 /* {{{ proto public bool ReflectionClass::isCloneable()
4564 Returns whether this class is cloneable */
ZEND_METHOD(reflection_class,isCloneable)4565 ZEND_METHOD(reflection_class, isCloneable)
4566 {
4567 reflection_object *intern;
4568 zend_class_entry *ce;
4569 zval obj;
4570
4571 if (zend_parse_parameters_none() == FAILURE) {
4572 return;
4573 }
4574 GET_REFLECTION_OBJECT_PTR(ce);
4575 if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4576 RETURN_FALSE;
4577 }
4578 if (!Z_ISUNDEF(intern->obj)) {
4579 if (ce->clone) {
4580 RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4581 } else {
4582 RETURN_BOOL(Z_OBJ_HANDLER(intern->obj, clone_obj) != NULL);
4583 }
4584 } else {
4585 if (ce->clone) {
4586 RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4587 } else {
4588 if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) {
4589 return;
4590 }
4591 /* We're not calling the constructor, so don't call the destructor either. */
4592 zend_object_store_ctor_failed(Z_OBJ(obj));
4593 RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
4594 zval_ptr_dtor(&obj);
4595 }
4596 }
4597 }
4598 /* }}} */
4599
4600 /* {{{ proto public bool ReflectionClass::isInterface()
4601 Returns whether this is an interface or a class */
ZEND_METHOD(reflection_class,isInterface)4602 ZEND_METHOD(reflection_class, isInterface)
4603 {
4604 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
4605 }
4606 /* }}} */
4607
4608 /* {{{ proto public bool ReflectionClass::isTrait()
4609 Returns whether this is a trait */
ZEND_METHOD(reflection_class,isTrait)4610 ZEND_METHOD(reflection_class, isTrait)
4611 {
4612 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT);
4613 }
4614 /* }}} */
4615
4616 /* {{{ proto public bool ReflectionClass::isFinal()
4617 Returns whether this class is final */
ZEND_METHOD(reflection_class,isFinal)4618 ZEND_METHOD(reflection_class, isFinal)
4619 {
4620 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
4621 }
4622 /* }}} */
4623
4624 /* {{{ proto public bool ReflectionClass::isAbstract()
4625 Returns whether this class is abstract */
ZEND_METHOD(reflection_class,isAbstract)4626 ZEND_METHOD(reflection_class, isAbstract)
4627 {
4628 _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
4629 }
4630 /* }}} */
4631
4632 /* {{{ proto public int ReflectionClass::getModifiers()
4633 Returns a bitfield of the access modifiers for this class */
ZEND_METHOD(reflection_class,getModifiers)4634 ZEND_METHOD(reflection_class, getModifiers)
4635 {
4636 reflection_object *intern;
4637 zend_class_entry *ce;
4638 uint32_t keep_flags = ZEND_ACC_FINAL
4639 | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
4640
4641 if (zend_parse_parameters_none() == FAILURE) {
4642 return;
4643 }
4644 GET_REFLECTION_OBJECT_PTR(ce);
4645
4646 RETURN_LONG((ce->ce_flags & keep_flags));
4647 }
4648 /* }}} */
4649
4650 /* {{{ proto public bool ReflectionClass::isInstance(stdclass object)
4651 Returns whether the given object is an instance of this class */
ZEND_METHOD(reflection_class,isInstance)4652 ZEND_METHOD(reflection_class, isInstance)
4653 {
4654 reflection_object *intern;
4655 zend_class_entry *ce;
4656 zval *object;
4657
4658 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
4659 return;
4660 }
4661 GET_REFLECTION_OBJECT_PTR(ce);
4662 RETURN_BOOL(instanceof_function(Z_OBJCE_P(object), ce));
4663 }
4664 /* }}} */
4665
4666 /* {{{ proto public object ReflectionClass::newInstance(mixed* args, ...)
4667 Returns an instance of this class */
ZEND_METHOD(reflection_class,newInstance)4668 ZEND_METHOD(reflection_class, newInstance)
4669 {
4670 zval retval;
4671 reflection_object *intern;
4672 zend_class_entry *ce, *old_scope;
4673 zend_function *constructor;
4674
4675 GET_REFLECTION_OBJECT_PTR(ce);
4676
4677 if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4678 return;
4679 }
4680
4681 old_scope = EG(fake_scope);
4682 EG(fake_scope) = ce;
4683 constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4684 EG(fake_scope) = old_scope;
4685
4686 /* Run the constructor if there is one */
4687 if (constructor) {
4688 zval *params = NULL;
4689 int ret, i, num_args = 0;
4690 zend_fcall_info fci;
4691 zend_fcall_info_cache fcc;
4692
4693 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4694 zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4695 zval_ptr_dtor(return_value);
4696 RETURN_NULL();
4697 }
4698
4699 if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", ¶ms, &num_args) == FAILURE) {
4700 zval_ptr_dtor(return_value);
4701 RETURN_FALSE;
4702 }
4703
4704 for (i = 0; i < num_args; i++) {
4705 Z_TRY_ADDREF(params[i]);
4706 }
4707
4708 fci.size = sizeof(fci);
4709 ZVAL_UNDEF(&fci.function_name);
4710 fci.object = Z_OBJ_P(return_value);
4711 fci.retval = &retval;
4712 fci.param_count = num_args;
4713 fci.params = params;
4714 fci.no_separation = 1;
4715
4716 fcc.function_handler = constructor;
4717 fcc.called_scope = Z_OBJCE_P(return_value);
4718 fcc.object = Z_OBJ_P(return_value);
4719
4720 ret = zend_call_function(&fci, &fcc);
4721 zval_ptr_dtor(&retval);
4722 for (i = 0; i < num_args; i++) {
4723 zval_ptr_dtor(¶ms[i]);
4724 }
4725
4726 if (EG(exception)) {
4727 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
4728 }
4729 if (ret == FAILURE) {
4730 php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4731 zval_ptr_dtor(return_value);
4732 RETURN_NULL();
4733 }
4734 } else if (ZEND_NUM_ARGS()) {
4735 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));
4736 }
4737 }
4738 /* }}} */
4739
4740 /* {{{ proto public object ReflectionClass::newInstanceWithoutConstructor()
4741 Returns an instance of this class without invoking its constructor */
ZEND_METHOD(reflection_class,newInstanceWithoutConstructor)4742 ZEND_METHOD(reflection_class, newInstanceWithoutConstructor)
4743 {
4744 reflection_object *intern;
4745 zend_class_entry *ce;
4746
4747 GET_REFLECTION_OBJECT_PTR(ce);
4748
4749 if (ce->type == ZEND_INTERNAL_CLASS
4750 && ce->create_object != NULL && (ce->ce_flags & ZEND_ACC_FINAL)) {
4751 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));
4752 return;
4753 }
4754
4755 object_init_ex(return_value, ce);
4756 }
4757 /* }}} */
4758
4759 /* {{{ proto public object ReflectionClass::newInstanceArgs([array args])
4760 Returns an instance of this class */
ZEND_METHOD(reflection_class,newInstanceArgs)4761 ZEND_METHOD(reflection_class, newInstanceArgs)
4762 {
4763 zval retval, *val;
4764 reflection_object *intern;
4765 zend_class_entry *ce, *old_scope;
4766 int ret, i, argc = 0;
4767 HashTable *args;
4768 zend_function *constructor;
4769
4770 GET_REFLECTION_OBJECT_PTR(ce);
4771
4772 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &args) == FAILURE) {
4773 return;
4774 }
4775
4776 if (ZEND_NUM_ARGS() > 0) {
4777 argc = args->nNumOfElements;
4778 }
4779
4780 if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4781 return;
4782 }
4783
4784 old_scope = EG(fake_scope);
4785 EG(fake_scope) = ce;
4786 constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4787 EG(fake_scope) = old_scope;
4788
4789 /* Run the constructor if there is one */
4790 if (constructor) {
4791 zval *params = NULL;
4792 zend_fcall_info fci;
4793 zend_fcall_info_cache fcc;
4794
4795 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4796 zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4797 zval_ptr_dtor(return_value);
4798 RETURN_NULL();
4799 }
4800
4801 if (argc) {
4802 params = safe_emalloc(sizeof(zval), argc, 0);
4803 argc = 0;
4804 ZEND_HASH_FOREACH_VAL(args, val) {
4805 ZVAL_COPY(¶ms[argc], val);
4806 argc++;
4807 } ZEND_HASH_FOREACH_END();
4808 }
4809
4810 fci.size = sizeof(fci);
4811 ZVAL_UNDEF(&fci.function_name);
4812 fci.object = Z_OBJ_P(return_value);
4813 fci.retval = &retval;
4814 fci.param_count = argc;
4815 fci.params = params;
4816 fci.no_separation = 1;
4817
4818 fcc.function_handler = constructor;
4819 fcc.called_scope = Z_OBJCE_P(return_value);
4820 fcc.object = Z_OBJ_P(return_value);
4821
4822 ret = zend_call_function(&fci, &fcc);
4823 zval_ptr_dtor(&retval);
4824 if (params) {
4825 for (i = 0; i < argc; i++) {
4826 zval_ptr_dtor(¶ms[i]);
4827 }
4828 efree(params);
4829 }
4830
4831 if (EG(exception)) {
4832 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
4833 }
4834 if (ret == FAILURE) {
4835 zval_ptr_dtor(&retval);
4836 php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4837 zval_ptr_dtor(return_value);
4838 RETURN_NULL();
4839 }
4840 } else if (argc) {
4841 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));
4842 }
4843 }
4844 /* }}} */
4845
4846 /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
4847 Returns an array of interfaces this class implements */
ZEND_METHOD(reflection_class,getInterfaces)4848 ZEND_METHOD(reflection_class, getInterfaces)
4849 {
4850 reflection_object *intern;
4851 zend_class_entry *ce;
4852
4853 if (zend_parse_parameters_none() == FAILURE) {
4854 return;
4855 }
4856 GET_REFLECTION_OBJECT_PTR(ce);
4857
4858 if (ce->num_interfaces) {
4859 uint32_t i;
4860
4861 ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
4862 array_init(return_value);
4863 for (i=0; i < ce->num_interfaces; i++) {
4864 zval interface;
4865 zend_reflection_class_factory(ce->interfaces[i], &interface);
4866 zend_hash_update(Z_ARRVAL_P(return_value), ce->interfaces[i]->name, &interface);
4867 }
4868 } else {
4869 RETURN_EMPTY_ARRAY();
4870 }
4871 }
4872 /* }}} */
4873
4874 /* {{{ proto public String[] ReflectionClass::getInterfaceNames()
4875 Returns an array of names of interfaces this class implements */
ZEND_METHOD(reflection_class,getInterfaceNames)4876 ZEND_METHOD(reflection_class, getInterfaceNames)
4877 {
4878 reflection_object *intern;
4879 zend_class_entry *ce;
4880 uint32_t i;
4881
4882 if (zend_parse_parameters_none() == FAILURE) {
4883 return;
4884 }
4885 GET_REFLECTION_OBJECT_PTR(ce);
4886
4887 if (!ce->num_interfaces) {
4888 /* Return an empty array if this class implements no interfaces */
4889 RETURN_EMPTY_ARRAY();
4890 }
4891
4892 ZEND_ASSERT(ce->ce_flags & ZEND_ACC_LINKED);
4893 array_init(return_value);
4894
4895 for (i=0; i < ce->num_interfaces; i++) {
4896 add_next_index_str(return_value, zend_string_copy(ce->interfaces[i]->name));
4897 }
4898 }
4899 /* }}} */
4900
4901 /* {{{ proto public ReflectionClass[] ReflectionClass::getTraits()
4902 Returns an array of traits used by this class */
ZEND_METHOD(reflection_class,getTraits)4903 ZEND_METHOD(reflection_class, getTraits)
4904 {
4905 reflection_object *intern;
4906 zend_class_entry *ce;
4907 uint32_t i;
4908
4909 if (zend_parse_parameters_none() == FAILURE) {
4910 return;
4911 }
4912 GET_REFLECTION_OBJECT_PTR(ce);
4913
4914 if (!ce->num_traits) {
4915 RETURN_EMPTY_ARRAY();
4916 }
4917
4918 array_init(return_value);
4919
4920 for (i=0; i < ce->num_traits; i++) {
4921 zval trait;
4922 zend_class_entry *trait_ce;
4923
4924 trait_ce = zend_fetch_class_by_name(ce->trait_names[i].name,
4925 ce->trait_names[i].lc_name, ZEND_FETCH_CLASS_TRAIT);
4926 ZEND_ASSERT(trait_ce);
4927 zend_reflection_class_factory(trait_ce, &trait);
4928 zend_hash_update(Z_ARRVAL_P(return_value), ce->trait_names[i].name, &trait);
4929 }
4930 }
4931 /* }}} */
4932
4933 /* {{{ proto public String[] ReflectionClass::getTraitNames()
4934 Returns an array of names of traits used by this class */
ZEND_METHOD(reflection_class,getTraitNames)4935 ZEND_METHOD(reflection_class, getTraitNames)
4936 {
4937 reflection_object *intern;
4938 zend_class_entry *ce;
4939 uint32_t i;
4940
4941 if (zend_parse_parameters_none() == FAILURE) {
4942 return;
4943 }
4944 GET_REFLECTION_OBJECT_PTR(ce);
4945
4946 if (!ce->num_traits) {
4947 RETURN_EMPTY_ARRAY();
4948 }
4949
4950 array_init(return_value);
4951
4952 for (i=0; i < ce->num_traits; i++) {
4953 add_next_index_str(return_value, zend_string_copy(ce->trait_names[i].name));
4954 }
4955 }
4956 /* }}} */
4957
4958 /* {{{ proto public array ReflectionClass::getTraitAliases()
4959 Returns an array of trait aliases */
ZEND_METHOD(reflection_class,getTraitAliases)4960 ZEND_METHOD(reflection_class, getTraitAliases)
4961 {
4962 reflection_object *intern;
4963 zend_class_entry *ce;
4964
4965 if (zend_parse_parameters_none() == FAILURE) {
4966 return;
4967 }
4968 GET_REFLECTION_OBJECT_PTR(ce);
4969
4970
4971 if (ce->trait_aliases) {
4972 uint32_t i = 0;
4973
4974 array_init(return_value);
4975 while (ce->trait_aliases[i]) {
4976 zend_string *mname;
4977 zend_trait_method_reference *cur_ref = &ce->trait_aliases[i]->trait_method;
4978
4979 if (ce->trait_aliases[i]->alias) {
4980
4981 mname = zend_string_alloc(ZSTR_LEN(cur_ref->class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
4982 snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->class_name), ZSTR_VAL(cur_ref->method_name));
4983 add_assoc_str_ex(return_value, ZSTR_VAL(ce->trait_aliases[i]->alias), ZSTR_LEN(ce->trait_aliases[i]->alias), mname);
4984 }
4985 i++;
4986 }
4987 } else {
4988 RETURN_EMPTY_ARRAY();
4989 }
4990 }
4991 /* }}} */
4992
4993 /* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
4994 Returns the class' parent class, or, if none exists, FALSE */
ZEND_METHOD(reflection_class,getParentClass)4995 ZEND_METHOD(reflection_class, getParentClass)
4996 {
4997 reflection_object *intern;
4998 zend_class_entry *ce;
4999
5000 if (zend_parse_parameters_none() == FAILURE) {
5001 return;
5002 }
5003 GET_REFLECTION_OBJECT_PTR(ce);
5004
5005 if (ce->parent) {
5006 zend_reflection_class_factory(ce->parent, return_value);
5007 } else {
5008 RETURN_FALSE;
5009 }
5010 }
5011 /* }}} */
5012
5013 /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
5014 Returns whether this class is a subclass of another class */
ZEND_METHOD(reflection_class,isSubclassOf)5015 ZEND_METHOD(reflection_class, isSubclassOf)
5016 {
5017 reflection_object *intern, *argument;
5018 zend_class_entry *ce, *class_ce;
5019 zval *class_name;
5020
5021 GET_REFLECTION_OBJECT_PTR(ce);
5022
5023 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE) {
5024 return;
5025 }
5026
5027 switch (Z_TYPE_P(class_name)) {
5028 case IS_STRING:
5029 if ((class_ce = zend_lookup_class(Z_STR_P(class_name))) == NULL) {
5030 zend_throw_exception_ex(reflection_exception_ptr, 0,
5031 "Class %s does not exist", Z_STRVAL_P(class_name));
5032 return;
5033 }
5034 break;
5035 case IS_OBJECT:
5036 if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr)) {
5037 argument = Z_REFLECTION_P(class_name);
5038 if (argument->ptr == NULL) {
5039 zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5040 return;
5041 }
5042 class_ce = argument->ptr;
5043 break;
5044 }
5045 /* no break */
5046 default:
5047 zend_throw_exception_ex(reflection_exception_ptr, 0,
5048 "Parameter one must either be a string or a ReflectionClass object");
5049 return;
5050 }
5051
5052 RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce)));
5053 }
5054 /* }}} */
5055
5056 /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
5057 Returns whether this class is a subclass of another class */
ZEND_METHOD(reflection_class,implementsInterface)5058 ZEND_METHOD(reflection_class, implementsInterface)
5059 {
5060 reflection_object *intern, *argument;
5061 zend_class_entry *ce, *interface_ce;
5062 zval *interface;
5063
5064 GET_REFLECTION_OBJECT_PTR(ce);
5065
5066 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &interface) == FAILURE) {
5067 return;
5068 }
5069
5070 switch (Z_TYPE_P(interface)) {
5071 case IS_STRING:
5072 if ((interface_ce = zend_lookup_class(Z_STR_P(interface))) == NULL) {
5073 zend_throw_exception_ex(reflection_exception_ptr, 0,
5074 "Interface %s does not exist", Z_STRVAL_P(interface));
5075 return;
5076 }
5077 break;
5078 case IS_OBJECT:
5079 if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr)) {
5080 argument = Z_REFLECTION_P(interface);
5081 if (argument->ptr == NULL) {
5082 zend_throw_error(NULL, "Internal error: Failed to retrieve the argument's reflection object");
5083 return;
5084 }
5085 interface_ce = argument->ptr;
5086 break;
5087 }
5088 /* no break */
5089 default:
5090 zend_throw_exception_ex(reflection_exception_ptr, 0,
5091 "Parameter one must either be a string or a ReflectionClass object");
5092 return;
5093 }
5094
5095 if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
5096 zend_throw_exception_ex(reflection_exception_ptr, 0,
5097 "%s is not an interface", ZSTR_VAL(interface_ce->name));
5098 return;
5099 }
5100 RETURN_BOOL(instanceof_function(ce, interface_ce));
5101 }
5102 /* }}} */
5103
5104 /* {{{ proto public bool ReflectionClass::isIterable()
5105 Returns whether this class is iterable (can be used inside foreach) */
ZEND_METHOD(reflection_class,isIterable)5106 ZEND_METHOD(reflection_class, isIterable)
5107 {
5108 reflection_object *intern;
5109 zend_class_entry *ce;
5110
5111 if (zend_parse_parameters_none() == FAILURE) {
5112 return;
5113 }
5114
5115 GET_REFLECTION_OBJECT_PTR(ce);
5116
5117 if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS |
5118 ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
5119 RETURN_FALSE;
5120 }
5121
5122 RETURN_BOOL(ce->get_iterator || instanceof_function(ce, zend_ce_traversable));
5123 }
5124 /* }}} */
5125
5126 /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension()
5127 Returns NULL or the extension the class belongs to */
ZEND_METHOD(reflection_class,getExtension)5128 ZEND_METHOD(reflection_class, getExtension)
5129 {
5130 reflection_object *intern;
5131 zend_class_entry *ce;
5132
5133 if (zend_parse_parameters_none() == FAILURE) {
5134 return;
5135 }
5136
5137 GET_REFLECTION_OBJECT_PTR(ce);
5138
5139 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5140 reflection_extension_factory(return_value, ce->info.internal.module->name);
5141 }
5142 }
5143 /* }}} */
5144
5145 /* {{{ proto public string|false ReflectionClass::getExtensionName()
5146 Returns false or the name of the extension the class belongs to */
ZEND_METHOD(reflection_class,getExtensionName)5147 ZEND_METHOD(reflection_class, getExtensionName)
5148 {
5149 reflection_object *intern;
5150 zend_class_entry *ce;
5151
5152 if (zend_parse_parameters_none() == FAILURE) {
5153 return;
5154 }
5155
5156 GET_REFLECTION_OBJECT_PTR(ce);
5157
5158 if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5159 RETURN_STRING(ce->info.internal.module->name);
5160 } else {
5161 RETURN_FALSE;
5162 }
5163 }
5164 /* }}} */
5165
5166 /* {{{ proto public bool ReflectionClass::inNamespace()
5167 Returns whether this class is defined in namespace */
ZEND_METHOD(reflection_class,inNamespace)5168 ZEND_METHOD(reflection_class, inNamespace)
5169 {
5170 zval *name;
5171 const char *backslash;
5172
5173 if (zend_parse_parameters_none() == FAILURE) {
5174 return;
5175 }
5176 if ((name = _default_load_name(ZEND_THIS)) == NULL) {
5177 RETURN_FALSE;
5178 }
5179 if (Z_TYPE_P(name) == IS_STRING
5180 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5181 && backslash > Z_STRVAL_P(name))
5182 {
5183 RETURN_TRUE;
5184 }
5185 RETURN_FALSE;
5186 }
5187 /* }}} */
5188
5189 /* {{{ proto public string ReflectionClass::getNamespaceName()
5190 Returns the name of namespace where this class is defined */
ZEND_METHOD(reflection_class,getNamespaceName)5191 ZEND_METHOD(reflection_class, getNamespaceName)
5192 {
5193 zval *name;
5194 const char *backslash;
5195
5196 if (zend_parse_parameters_none() == FAILURE) {
5197 return;
5198 }
5199 if ((name = _default_load_name(ZEND_THIS)) == NULL) {
5200 RETURN_FALSE;
5201 }
5202 if (Z_TYPE_P(name) == IS_STRING
5203 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5204 && backslash > Z_STRVAL_P(name))
5205 {
5206 RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
5207 }
5208 RETURN_EMPTY_STRING();
5209 }
5210 /* }}} */
5211
5212 /* {{{ proto public string ReflectionClass::getShortName()
5213 Returns the short name of the class (without namespace part) */
ZEND_METHOD(reflection_class,getShortName)5214 ZEND_METHOD(reflection_class, getShortName)
5215 {
5216 zval *name;
5217 const char *backslash;
5218
5219 if (zend_parse_parameters_none() == FAILURE) {
5220 return;
5221 }
5222 if ((name = _default_load_name(ZEND_THIS)) == NULL) {
5223 RETURN_FALSE;
5224 }
5225 if (Z_TYPE_P(name) == IS_STRING
5226 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5227 && backslash > Z_STRVAL_P(name))
5228 {
5229 RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
5230 }
5231 ZVAL_COPY_DEREF(return_value, name);
5232 }
5233 /* }}} */
5234
5235 /* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException
5236 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_object,export)5237 ZEND_METHOD(reflection_object, export)
5238 {
5239 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_object_ptr, 1);
5240 }
5241 /* }}} */
5242
5243 /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException
5244 Constructor. Takes an instance as an argument */
ZEND_METHOD(reflection_object,__construct)5245 ZEND_METHOD(reflection_object, __construct)
5246 {
5247 reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5248 }
5249 /* }}} */
5250
5251 /* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException
5252 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_property,export)5253 ZEND_METHOD(reflection_property, export)
5254 {
5255 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_property_ptr, 2);
5256 }
5257 /* }}} */
5258
5259 /* {{{ proto public static mixed ReflectionClassConstant::export(mixed class, string name [, bool return]) throws ReflectionException
5260 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class_constant,export)5261 ZEND_METHOD(reflection_class_constant, export)
5262 {
5263 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_constant_ptr, 2);
5264 }
5265 /* }}} */
5266
5267 /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
5268 Constructor. Throws an Exception in case the given property does not exist */
ZEND_METHOD(reflection_property,__construct)5269 ZEND_METHOD(reflection_property, __construct)
5270 {
5271 zval *classname;
5272 zend_string *name;
5273 int dynam_prop = 0;
5274 zval *object;
5275 reflection_object *intern;
5276 zend_class_entry *ce;
5277 zend_property_info *property_info = NULL;
5278 property_reference *reference;
5279
5280 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &name) == FAILURE) {
5281 return;
5282 }
5283
5284 object = ZEND_THIS;
5285 intern = Z_REFLECTION_P(object);
5286
5287 /* Find the class entry */
5288 switch (Z_TYPE_P(classname)) {
5289 case IS_STRING:
5290 if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
5291 zend_throw_exception_ex(reflection_exception_ptr, 0,
5292 "Class %s does not exist", Z_STRVAL_P(classname));
5293 return;
5294 }
5295 break;
5296
5297 case IS_OBJECT:
5298 ce = Z_OBJCE_P(classname);
5299 break;
5300
5301 default:
5302 _DO_THROW("The parameter class is expected to be either a string or an object");
5303 return;
5304 }
5305
5306 property_info = zend_hash_find_ptr(&ce->properties_info, name);
5307 if (property_info == NULL
5308 || ((property_info->flags & ZEND_ACC_PRIVATE)
5309 && property_info->ce != ce)) {
5310 /* Check for dynamic properties */
5311 if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT) {
5312 if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(classname), name)) {
5313 dynam_prop = 1;
5314 }
5315 }
5316 if (dynam_prop == 0) {
5317 zend_throw_exception_ex(reflection_exception_ptr, 0, "Property %s::$%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
5318 return;
5319 }
5320 }
5321
5322 if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
5323 /* we have to search the class hierarchy for this (implicit) public or protected property */
5324 zend_class_entry *tmp_ce = ce;
5325 zend_property_info *tmp_info;
5326
5327 while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, name)) == NULL) {
5328 ce = tmp_ce;
5329 property_info = tmp_info;
5330 tmp_ce = tmp_ce->parent;
5331 }
5332 }
5333
5334 ZVAL_STR_COPY(reflection_prop_name(object), name);
5335 if (dynam_prop == 0) {
5336 ZVAL_STR_COPY(reflection_prop_class(object), property_info->ce->name);
5337 } else {
5338 ZVAL_STR_COPY(reflection_prop_class(object), ce->name);
5339 }
5340
5341 reference = (property_reference*) emalloc(sizeof(property_reference));
5342 if (dynam_prop) {
5343 reference->prop.flags = ZEND_ACC_PUBLIC;
5344 reference->prop.name = name;
5345 reference->prop.doc_comment = NULL;
5346 reference->prop.ce = ce;
5347 reference->prop.type = 0;
5348 reference->dynamic = 1;
5349 } else {
5350 reference->prop = *property_info;
5351 reference->dynamic = 0;
5352
5353 if (ZEND_TYPE_IS_NAME(reference->prop.type)) {
5354 zend_string_addref(ZEND_TYPE_NAME(reference->prop.type));
5355 }
5356 }
5357 reference->unmangled_name = zend_string_copy(name);
5358 intern->ptr = reference;
5359 intern->ref_type = REF_TYPE_PROPERTY;
5360 intern->ce = ce;
5361 intern->ignore_visibility = 0;
5362 }
5363 /* }}} */
5364
5365 /* {{{ proto public string ReflectionProperty::__toString()
5366 Returns a string representation */
ZEND_METHOD(reflection_property,__toString)5367 ZEND_METHOD(reflection_property, __toString)
5368 {
5369 reflection_object *intern;
5370 property_reference *ref;
5371 smart_str str = {0};
5372
5373 if (zend_parse_parameters_none() == FAILURE) {
5374 return;
5375 }
5376 GET_REFLECTION_OBJECT_PTR(ref);
5377 _property_string(&str, &ref->prop, ZSTR_VAL(ref->unmangled_name), "", ref->dynamic);
5378 RETURN_STR(smart_str_extract(&str));
5379 }
5380 /* }}} */
5381
5382 /* {{{ proto public string ReflectionProperty::getName()
5383 Returns the class' name */
ZEND_METHOD(reflection_property,getName)5384 ZEND_METHOD(reflection_property, getName)
5385 {
5386 if (zend_parse_parameters_none() == FAILURE) {
5387 return;
5388 }
5389 _default_get_name(ZEND_THIS, return_value);
5390 }
5391 /* }}} */
5392
_property_check_flag(INTERNAL_FUNCTION_PARAMETERS,int mask)5393 static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
5394 {
5395 reflection_object *intern;
5396 property_reference *ref;
5397
5398 if (zend_parse_parameters_none() == FAILURE) {
5399 return;
5400 }
5401 GET_REFLECTION_OBJECT_PTR(ref);
5402 RETURN_BOOL(ref->prop.flags & mask);
5403 }
5404 /* }}} */
5405
5406 /* {{{ proto public bool ReflectionProperty::isPublic()
5407 Returns whether this property is public */
ZEND_METHOD(reflection_property,isPublic)5408 ZEND_METHOD(reflection_property, isPublic)
5409 {
5410 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
5411 }
5412 /* }}} */
5413
5414 /* {{{ proto public bool ReflectionProperty::isPrivate()
5415 Returns whether this property is private */
ZEND_METHOD(reflection_property,isPrivate)5416 ZEND_METHOD(reflection_property, isPrivate)
5417 {
5418 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
5419 }
5420 /* }}} */
5421
5422 /* {{{ proto public bool ReflectionProperty::isProtected()
5423 Returns whether this property is protected */
ZEND_METHOD(reflection_property,isProtected)5424 ZEND_METHOD(reflection_property, isProtected)
5425 {
5426 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
5427 }
5428 /* }}} */
5429
5430 /* {{{ proto public bool ReflectionProperty::isStatic()
5431 Returns whether this property is static */
ZEND_METHOD(reflection_property,isStatic)5432 ZEND_METHOD(reflection_property, isStatic)
5433 {
5434 _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
5435 }
5436 /* }}} */
5437
5438 /* {{{ proto public bool ReflectionProperty::isDefault()
5439 Returns whether this property is default (declared at compilation time). */
ZEND_METHOD(reflection_property,isDefault)5440 ZEND_METHOD(reflection_property, isDefault)
5441 {
5442 reflection_object *intern;
5443 property_reference *ref;
5444
5445 if (zend_parse_parameters_none() == FAILURE) {
5446 return;
5447 }
5448 GET_REFLECTION_OBJECT_PTR(ref);
5449 RETURN_BOOL(!ref->dynamic);
5450 }
5451 /* }}} */
5452
5453 /* {{{ proto public int ReflectionProperty::getModifiers()
5454 Returns a bitfield of the access modifiers for this property */
ZEND_METHOD(reflection_property,getModifiers)5455 ZEND_METHOD(reflection_property, getModifiers)
5456 {
5457 reflection_object *intern;
5458 property_reference *ref;
5459 uint32_t keep_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
5460
5461 if (zend_parse_parameters_none() == FAILURE) {
5462 return;
5463 }
5464 GET_REFLECTION_OBJECT_PTR(ref);
5465
5466 RETURN_LONG((ref->prop.flags & keep_flags));
5467 }
5468 /* }}} */
5469
5470 /* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
5471 Returns this property's value */
ZEND_METHOD(reflection_property,getValue)5472 ZEND_METHOD(reflection_property, getValue)
5473 {
5474 reflection_object *intern;
5475 property_reference *ref;
5476 zval *object, *name;
5477 zval *member_p = NULL;
5478
5479 GET_REFLECTION_OBJECT_PTR(ref);
5480
5481 if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5482 name = _default_load_name(ZEND_THIS);
5483 zend_throw_exception_ex(reflection_exception_ptr, 0,
5484 "Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5485 return;
5486 }
5487
5488 if (ref->prop.flags & ZEND_ACC_STATIC) {
5489 member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 0);
5490 if (member_p) {
5491 ZVAL_COPY_DEREF(return_value, member_p);
5492 }
5493 } else {
5494 zval rv;
5495
5496 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
5497 return;
5498 }
5499
5500 if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
5501 _DO_THROW("Given object is not an instance of the class this property was declared in");
5502 return;
5503 }
5504
5505 member_p = zend_read_property_ex(intern->ce, object, ref->unmangled_name, 0, &rv);
5506 if (member_p != &rv) {
5507 ZVAL_COPY_DEREF(return_value, member_p);
5508 } else {
5509 if (Z_ISREF_P(member_p)) {
5510 zend_unwrap_reference(member_p);
5511 }
5512 ZVAL_COPY_VALUE(return_value, member_p);
5513 }
5514 }
5515 }
5516 /* }}} */
5517
5518 /* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
5519 Sets this property's value */
ZEND_METHOD(reflection_property,setValue)5520 ZEND_METHOD(reflection_property, setValue)
5521 {
5522 reflection_object *intern;
5523 property_reference *ref;
5524 zval *object, *name;
5525 zval *value;
5526 zval *tmp;
5527
5528 GET_REFLECTION_OBJECT_PTR(ref);
5529
5530 if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5531 name = _default_load_name(ZEND_THIS);
5532 zend_throw_exception_ex(reflection_exception_ptr, 0,
5533 "Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5534 return;
5535 }
5536
5537 if (ref->prop.flags & ZEND_ACC_STATIC) {
5538 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
5539 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
5540 return;
5541 }
5542 }
5543
5544 zend_update_static_property_ex(intern->ce, ref->unmangled_name, value);
5545 } else {
5546 if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
5547 return;
5548 }
5549
5550 zend_update_property_ex(intern->ce, object, ref->unmangled_name, value);
5551 }
5552 }
5553 /* }}} */
5554
5555 /* {{{ proto public mixed ReflectionProperty::isInitialized([stdclass object])
5556 Returns this property's value */
ZEND_METHOD(reflection_property,isInitialized)5557 ZEND_METHOD(reflection_property, isInitialized)
5558 {
5559 reflection_object *intern;
5560 property_reference *ref;
5561 zval *object, *name;
5562 zval *member_p = NULL;
5563
5564 GET_REFLECTION_OBJECT_PTR(ref);
5565
5566 if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5567 name = _default_load_name(getThis());
5568 zend_throw_exception_ex(reflection_exception_ptr, 0,
5569 "Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5570 return;
5571 }
5572
5573 if (ref->prop.flags & ZEND_ACC_STATIC) {
5574 member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 1);
5575 if (member_p) {
5576 RETURN_BOOL(!Z_ISUNDEF_P(member_p))
5577 }
5578 RETURN_FALSE;
5579 } else {
5580 zval name_zv;
5581 zend_class_entry *old_scope;
5582 int retval;
5583
5584 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
5585 return;
5586 }
5587
5588 if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
5589 _DO_THROW("Given object is not an instance of the class this property was declared in");
5590 return;
5591 }
5592
5593 old_scope = EG(fake_scope);
5594 EG(fake_scope) = intern->ce;
5595 ZVAL_STR(&name_zv, ref->unmangled_name);
5596 retval = Z_OBJ_HT_P(object)->has_property(object, &name_zv, ZEND_PROPERTY_EXISTS, NULL);
5597 EG(fake_scope) = old_scope;
5598
5599 RETVAL_BOOL(retval);
5600 }
5601 }
5602 /* }}} */
5603
5604 /* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
5605 Get the declaring class */
ZEND_METHOD(reflection_property,getDeclaringClass)5606 ZEND_METHOD(reflection_property, getDeclaringClass)
5607 {
5608 reflection_object *intern;
5609 property_reference *ref;
5610 zend_class_entry *tmp_ce, *ce;
5611 zend_property_info *tmp_info;
5612
5613 if (zend_parse_parameters_none() == FAILURE) {
5614 return;
5615 }
5616 GET_REFLECTION_OBJECT_PTR(ref);
5617
5618 ce = tmp_ce = intern->ce;
5619 while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, ref->unmangled_name)) != NULL) {
5620 if (tmp_info->flags & ZEND_ACC_PRIVATE) {
5621 /* it's a private property, so it can't be inherited */
5622 break;
5623 }
5624 ce = tmp_ce;
5625 if (tmp_ce == tmp_info->ce) {
5626 /* declared in this class, done */
5627 break;
5628 }
5629 tmp_ce = tmp_ce->parent;
5630 }
5631
5632 zend_reflection_class_factory(ce, return_value);
5633 }
5634 /* }}} */
5635
5636 /* {{{ proto public string ReflectionProperty::getDocComment()
5637 Returns the doc comment for this property */
ZEND_METHOD(reflection_property,getDocComment)5638 ZEND_METHOD(reflection_property, getDocComment)
5639 {
5640 reflection_object *intern;
5641 property_reference *ref;
5642
5643 if (zend_parse_parameters_none() == FAILURE) {
5644 return;
5645 }
5646 GET_REFLECTION_OBJECT_PTR(ref);
5647 if (ref->prop.doc_comment) {
5648 RETURN_STR_COPY(ref->prop.doc_comment);
5649 }
5650 RETURN_FALSE;
5651 }
5652 /* }}} */
5653
5654 /* {{{ proto public int ReflectionProperty::setAccessible(bool visible)
5655 Sets whether non-public properties can be requested */
ZEND_METHOD(reflection_property,setAccessible)5656 ZEND_METHOD(reflection_property, setAccessible)
5657 {
5658 reflection_object *intern;
5659 zend_bool visible;
5660
5661 if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
5662 return;
5663 }
5664
5665 intern = Z_REFLECTION_P(ZEND_THIS);
5666
5667 intern->ignore_visibility = visible;
5668 }
5669 /* }}} */
5670
5671 /* {{{ proto public ReflectionType ReflectionProperty::getType()
5672 Returns the type associated with the property */
ZEND_METHOD(reflection_property,getType)5673 ZEND_METHOD(reflection_property, getType)
5674 {
5675 reflection_object *intern;
5676 property_reference *ref;
5677
5678 if (zend_parse_parameters_none() == FAILURE) {
5679 return;
5680 }
5681
5682 GET_REFLECTION_OBJECT_PTR(ref);
5683
5684 if (!ZEND_TYPE_IS_SET(ref->prop.type)) {
5685 RETURN_NULL();
5686 }
5687
5688 reflection_type_factory(ref->prop.type, return_value);
5689 }
5690 /* }}} */
5691
5692 /* {{{ proto public bool ReflectionProperty::hasType()
5693 Returns whether property has a type */
ZEND_METHOD(reflection_property,hasType)5694 ZEND_METHOD(reflection_property, hasType)
5695 {
5696 reflection_object *intern;
5697 property_reference *ref;
5698
5699 if (zend_parse_parameters_none() == FAILURE) {
5700 return;
5701 }
5702
5703 GET_REFLECTION_OBJECT_PTR(ref);
5704
5705 RETVAL_BOOL(ZEND_TYPE_IS_SET(ref->prop.type));
5706 }
5707 /* }}} */
5708
5709 /* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
5710 Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_extension,export)5711 ZEND_METHOD(reflection_extension, export)
5712 {
5713 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_extension_ptr, 1);
5714 }
5715 /* }}} */
5716
5717 /* {{{ proto public void ReflectionExtension::__construct(string name)
5718 Constructor. Throws an Exception in case the given extension does not exist */
ZEND_METHOD(reflection_extension,__construct)5719 ZEND_METHOD(reflection_extension, __construct)
5720 {
5721 zval *object;
5722 char *lcname;
5723 reflection_object *intern;
5724 zend_module_entry *module;
5725 char *name_str;
5726 size_t name_len;
5727 ALLOCA_FLAG(use_heap)
5728
5729 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
5730 return;
5731 }
5732
5733 object = ZEND_THIS;
5734 intern = Z_REFLECTION_P(object);
5735 lcname = do_alloca(name_len + 1, use_heap);
5736 zend_str_tolower_copy(lcname, name_str, name_len);
5737 if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) {
5738 free_alloca(lcname, use_heap);
5739 zend_throw_exception_ex(reflection_exception_ptr, 0,
5740 "Extension %s does not exist", name_str);
5741 return;
5742 }
5743 free_alloca(lcname, use_heap);
5744 ZVAL_STRING(reflection_prop_name(object), module->name);
5745 intern->ptr = module;
5746 intern->ref_type = REF_TYPE_OTHER;
5747 intern->ce = NULL;
5748 }
5749 /* }}} */
5750
5751 /* {{{ proto public string ReflectionExtension::__toString()
5752 Returns a string representation */
ZEND_METHOD(reflection_extension,__toString)5753 ZEND_METHOD(reflection_extension, __toString)
5754 {
5755 reflection_object *intern;
5756 zend_module_entry *module;
5757 smart_str str = {0};
5758
5759 if (zend_parse_parameters_none() == FAILURE) {
5760 return;
5761 }
5762 GET_REFLECTION_OBJECT_PTR(module);
5763 _extension_string(&str, module, "");
5764 RETURN_STR(smart_str_extract(&str));
5765 }
5766 /* }}} */
5767
5768 /* {{{ proto public string ReflectionExtension::getName()
5769 Returns this extension's name */
ZEND_METHOD(reflection_extension,getName)5770 ZEND_METHOD(reflection_extension, getName)
5771 {
5772 if (zend_parse_parameters_none() == FAILURE) {
5773 return;
5774 }
5775 _default_get_name(ZEND_THIS, return_value);
5776 }
5777 /* }}} */
5778
5779 /* {{{ proto public string ReflectionExtension::getVersion()
5780 Returns this extension's version */
ZEND_METHOD(reflection_extension,getVersion)5781 ZEND_METHOD(reflection_extension, getVersion)
5782 {
5783 reflection_object *intern;
5784 zend_module_entry *module;
5785
5786 if (zend_parse_parameters_none() == FAILURE) {
5787 return;
5788 }
5789 GET_REFLECTION_OBJECT_PTR(module);
5790
5791 /* An extension does not necessarily have a version number */
5792 if (module->version == NO_VERSION_YET) {
5793 RETURN_NULL();
5794 } else {
5795 RETURN_STRING(module->version);
5796 }
5797 }
5798 /* }}} */
5799
5800 /* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
5801 Returns an array of this extension's functions */
ZEND_METHOD(reflection_extension,getFunctions)5802 ZEND_METHOD(reflection_extension, getFunctions)
5803 {
5804 reflection_object *intern;
5805 zend_module_entry *module;
5806 zval function;
5807 zend_function *fptr;
5808
5809 if (zend_parse_parameters_none() == FAILURE) {
5810 return;
5811 }
5812 GET_REFLECTION_OBJECT_PTR(module);
5813
5814 array_init(return_value);
5815 ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
5816 if (fptr->common.type==ZEND_INTERNAL_FUNCTION
5817 && fptr->internal_function.module == module) {
5818 reflection_function_factory(fptr, NULL, &function);
5819 zend_hash_update(Z_ARRVAL_P(return_value), fptr->common.function_name, &function);
5820 }
5821 } ZEND_HASH_FOREACH_END();
5822 }
5823 /* }}} */
5824
5825 /* {{{ proto public array ReflectionExtension::getConstants()
5826 Returns an associative array containing this extension's constants and their values */
ZEND_METHOD(reflection_extension,getConstants)5827 ZEND_METHOD(reflection_extension, getConstants)
5828 {
5829 reflection_object *intern;
5830 zend_module_entry *module;
5831 zend_constant *constant;
5832
5833 if (zend_parse_parameters_none() == FAILURE) {
5834 return;
5835 }
5836 GET_REFLECTION_OBJECT_PTR(module);
5837
5838 array_init(return_value);
5839 ZEND_HASH_FOREACH_PTR(EG(zend_constants), constant) {
5840 if (module->module_number == ZEND_CONSTANT_MODULE_NUMBER(constant)) {
5841 zval const_val;
5842 ZVAL_COPY_OR_DUP(&const_val, &constant->value);
5843 zend_hash_update(Z_ARRVAL_P(return_value), constant->name, &const_val);
5844 }
5845 } ZEND_HASH_FOREACH_END();
5846 }
5847 /* }}} */
5848
5849 /* {{{ _addinientry */
_addinientry(zend_ini_entry * ini_entry,zval * retval,int number)5850 static void _addinientry(zend_ini_entry *ini_entry, zval *retval, int number)
5851 {
5852 if (number == ini_entry->module_number) {
5853 zval zv;
5854 if (ini_entry->value) {
5855 ZVAL_STR_COPY(&zv, ini_entry->value);
5856 } else {
5857 ZVAL_NULL(&zv);
5858 }
5859 zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &zv);
5860 }
5861 }
5862 /* }}} */
5863
5864 /* {{{ proto public array ReflectionExtension::getINIEntries()
5865 Returns an associative array containing this extension's INI entries and their values */
ZEND_METHOD(reflection_extension,getINIEntries)5866 ZEND_METHOD(reflection_extension, getINIEntries)
5867 {
5868 reflection_object *intern;
5869 zend_module_entry *module;
5870 zend_ini_entry *ini_entry;
5871
5872 if (zend_parse_parameters_none() == FAILURE) {
5873 return;
5874 }
5875 GET_REFLECTION_OBJECT_PTR(module);
5876
5877 array_init(return_value);
5878 ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) {
5879 _addinientry(ini_entry, return_value, module->module_number);
5880 } ZEND_HASH_FOREACH_END();
5881 }
5882 /* }}} */
5883
5884 /* {{{ add_extension_class */
add_extension_class(zend_class_entry * ce,zend_string * key,zval * class_array,zend_module_entry * module,zend_bool add_reflection_class)5885 static void add_extension_class(zend_class_entry *ce, zend_string *key, zval *class_array, zend_module_entry *module, zend_bool add_reflection_class)
5886 {
5887 if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
5888 zend_string *name;
5889
5890 if (!zend_string_equals_ci(ce->name, key)) {
5891 /* This is a class alias, use alias name */
5892 name = key;
5893 } else {
5894 /* Use class name */
5895 name = ce->name;
5896 }
5897 if (add_reflection_class) {
5898 zval zclass;
5899 zend_reflection_class_factory(ce, &zclass);
5900 zend_hash_update(Z_ARRVAL_P(class_array), name, &zclass);
5901 } else {
5902 add_next_index_str(class_array, zend_string_copy(name));
5903 }
5904 }
5905 }
5906 /* }}} */
5907
5908 /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses()
5909 Returns an array containing ReflectionClass objects for all classes of this extension */
ZEND_METHOD(reflection_extension,getClasses)5910 ZEND_METHOD(reflection_extension, getClasses)
5911 {
5912 reflection_object *intern;
5913 zend_module_entry *module;
5914 zend_string *key;
5915 zend_class_entry *ce;
5916
5917 if (zend_parse_parameters_none() == FAILURE) {
5918 return;
5919 }
5920 GET_REFLECTION_OBJECT_PTR(module);
5921
5922 array_init(return_value);
5923 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
5924 add_extension_class(ce, key, return_value, module, 1);
5925 } ZEND_HASH_FOREACH_END();
5926 }
5927 /* }}} */
5928
5929 /* {{{ proto public array ReflectionExtension::getClassNames()
5930 Returns an array containing all names of all classes of this extension */
ZEND_METHOD(reflection_extension,getClassNames)5931 ZEND_METHOD(reflection_extension, getClassNames)
5932 {
5933 reflection_object *intern;
5934 zend_module_entry *module;
5935 zend_string *key;
5936 zend_class_entry *ce;
5937
5938 if (zend_parse_parameters_none() == FAILURE) {
5939 return;
5940 }
5941 GET_REFLECTION_OBJECT_PTR(module);
5942
5943 array_init(return_value);
5944 ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), key, ce) {
5945 add_extension_class(ce, key, return_value, module, 0);
5946 } ZEND_HASH_FOREACH_END();
5947 }
5948 /* }}} */
5949
5950 /* {{{ proto public array ReflectionExtension::getDependencies()
5951 Returns an array containing all names of all extensions this extension depends on */
ZEND_METHOD(reflection_extension,getDependencies)5952 ZEND_METHOD(reflection_extension, getDependencies)
5953 {
5954 reflection_object *intern;
5955 zend_module_entry *module;
5956 const zend_module_dep *dep;
5957
5958 if (zend_parse_parameters_none() == FAILURE) {
5959 return;
5960 }
5961 GET_REFLECTION_OBJECT_PTR(module);
5962
5963 dep = module->deps;
5964
5965 if (!dep)
5966 {
5967 RETURN_EMPTY_ARRAY();
5968 }
5969
5970 array_init(return_value);
5971 while(dep->name) {
5972 zend_string *relation;
5973 char *rel_type;
5974 size_t len = 0;
5975
5976 switch(dep->type) {
5977 case MODULE_DEP_REQUIRED:
5978 rel_type = "Required";
5979 len += sizeof("Required") - 1;
5980 break;
5981 case MODULE_DEP_CONFLICTS:
5982 rel_type = "Conflicts";
5983 len += sizeof("Conflicts") - 1;
5984 break;
5985 case MODULE_DEP_OPTIONAL:
5986 rel_type = "Optional";
5987 len += sizeof("Optional") - 1;
5988 break;
5989 default:
5990 rel_type = "Error"; /* shouldn't happen */
5991 len += sizeof("Error") - 1;
5992 break;
5993 }
5994
5995 if (dep->rel) {
5996 len += strlen(dep->rel) + 1;
5997 }
5998
5999 if (dep->version) {
6000 len += strlen(dep->version) + 1;
6001 }
6002
6003 relation = zend_string_alloc(len, 0);
6004 snprintf(ZSTR_VAL(relation), ZSTR_LEN(relation) + 1, "%s%s%s%s%s",
6005 rel_type,
6006 dep->rel ? " " : "",
6007 dep->rel ? dep->rel : "",
6008 dep->version ? " " : "",
6009 dep->version ? dep->version : "");
6010 add_assoc_str(return_value, dep->name, relation);
6011 dep++;
6012 }
6013 }
6014 /* }}} */
6015
6016 /* {{{ proto public void ReflectionExtension::info()
6017 Prints phpinfo block for the extension */
ZEND_METHOD(reflection_extension,info)6018 ZEND_METHOD(reflection_extension, info)
6019 {
6020 reflection_object *intern;
6021 zend_module_entry *module;
6022
6023 if (zend_parse_parameters_none() == FAILURE) {
6024 return;
6025 }
6026 GET_REFLECTION_OBJECT_PTR(module);
6027
6028 php_info_print_module(module);
6029 }
6030 /* }}} */
6031
6032 /* {{{ proto public bool ReflectionExtension::isPersistent()
6033 Returns whether this extension is persistent */
ZEND_METHOD(reflection_extension,isPersistent)6034 ZEND_METHOD(reflection_extension, isPersistent)
6035 {
6036 reflection_object *intern;
6037 zend_module_entry *module;
6038
6039 if (zend_parse_parameters_none() == FAILURE) {
6040 return;
6041 }
6042 GET_REFLECTION_OBJECT_PTR(module);
6043
6044 RETURN_BOOL(module->type == MODULE_PERSISTENT);
6045 }
6046 /* }}} */
6047
6048 /* {{{ proto public bool ReflectionExtension::isTemporary()
6049 Returns whether this extension is temporary */
ZEND_METHOD(reflection_extension,isTemporary)6050 ZEND_METHOD(reflection_extension, isTemporary)
6051 {
6052 reflection_object *intern;
6053 zend_module_entry *module;
6054
6055 if (zend_parse_parameters_none() == FAILURE) {
6056 return;
6057 }
6058 GET_REFLECTION_OBJECT_PTR(module);
6059
6060 RETURN_BOOL(module->type == MODULE_TEMPORARY);
6061 }
6062 /* }}} */
6063
6064 /* {{{ proto public static mixed ReflectionZendExtension::export(string name [, bool return]) throws ReflectionException
6065 * Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_zend_extension,export)6066 ZEND_METHOD(reflection_zend_extension, export)
6067 {
6068 _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_zend_extension_ptr, 1);
6069 }
6070 /* }}} */
6071
6072 /* {{{ proto public void ReflectionZendExtension::__construct(string name)
6073 Constructor. Throws an Exception in case the given Zend extension does not exist */
ZEND_METHOD(reflection_zend_extension,__construct)6074 ZEND_METHOD(reflection_zend_extension, __construct)
6075 {
6076 zval *object;
6077 reflection_object *intern;
6078 zend_extension *extension;
6079 char *name_str;
6080 size_t name_len;
6081
6082 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
6083 return;
6084 }
6085
6086 object = ZEND_THIS;
6087 intern = Z_REFLECTION_P(object);
6088
6089 extension = zend_get_extension(name_str);
6090 if (!extension) {
6091 zend_throw_exception_ex(reflection_exception_ptr, 0,
6092 "Zend Extension %s does not exist", name_str);
6093 return;
6094 }
6095 ZVAL_STRING(reflection_prop_name(object), extension->name);
6096 intern->ptr = extension;
6097 intern->ref_type = REF_TYPE_OTHER;
6098 intern->ce = NULL;
6099 }
6100 /* }}} */
6101
6102 /* {{{ proto public string ReflectionZendExtension::__toString()
6103 Returns a string representation */
ZEND_METHOD(reflection_zend_extension,__toString)6104 ZEND_METHOD(reflection_zend_extension, __toString)
6105 {
6106 reflection_object *intern;
6107 zend_extension *extension;
6108 smart_str str = {0};
6109
6110 if (zend_parse_parameters_none() == FAILURE) {
6111 return;
6112 }
6113 GET_REFLECTION_OBJECT_PTR(extension);
6114 _zend_extension_string(&str, extension, "");
6115 RETURN_STR(smart_str_extract(&str));
6116 }
6117 /* }}} */
6118
6119 /* {{{ proto public string ReflectionZendExtension::getName()
6120 Returns the name of this Zend extension */
ZEND_METHOD(reflection_zend_extension,getName)6121 ZEND_METHOD(reflection_zend_extension, getName)
6122 {
6123 reflection_object *intern;
6124 zend_extension *extension;
6125
6126 if (zend_parse_parameters_none() == FAILURE) {
6127 return;
6128 }
6129 GET_REFLECTION_OBJECT_PTR(extension);
6130
6131 RETURN_STRING(extension->name);
6132 }
6133 /* }}} */
6134
6135 /* {{{ proto public string ReflectionZendExtension::getVersion()
6136 Returns the version information of this Zend extension */
ZEND_METHOD(reflection_zend_extension,getVersion)6137 ZEND_METHOD(reflection_zend_extension, getVersion)
6138 {
6139 reflection_object *intern;
6140 zend_extension *extension;
6141
6142 if (zend_parse_parameters_none() == FAILURE) {
6143 return;
6144 }
6145 GET_REFLECTION_OBJECT_PTR(extension);
6146
6147 if (extension->version) {
6148 RETURN_STRING(extension->version);
6149 } else {
6150 RETURN_EMPTY_STRING();
6151 }
6152 }
6153 /* }}} */
6154
6155 /* {{{ proto public void ReflectionZendExtension::getAuthor()
6156 * Returns the name of this Zend extension's author */
ZEND_METHOD(reflection_zend_extension,getAuthor)6157 ZEND_METHOD(reflection_zend_extension, getAuthor)
6158 {
6159 reflection_object *intern;
6160 zend_extension *extension;
6161
6162 if (zend_parse_parameters_none() == FAILURE) {
6163 return;
6164 }
6165 GET_REFLECTION_OBJECT_PTR(extension);
6166
6167 if (extension->author) {
6168 RETURN_STRING(extension->author);
6169 } else {
6170 RETURN_EMPTY_STRING();
6171 }
6172 }
6173 /* }}} */
6174
6175 /* {{{ proto public void ReflectionZendExtension::getURL()
6176 Returns this Zend extension's URL*/
ZEND_METHOD(reflection_zend_extension,getURL)6177 ZEND_METHOD(reflection_zend_extension, getURL)
6178 {
6179 reflection_object *intern;
6180 zend_extension *extension;
6181
6182 if (zend_parse_parameters_none() == FAILURE) {
6183 return;
6184 }
6185 GET_REFLECTION_OBJECT_PTR(extension);
6186
6187 if (extension->URL) {
6188 RETURN_STRING(extension->URL);
6189 } else {
6190 RETURN_EMPTY_STRING();
6191 }
6192 }
6193 /* }}} */
6194
6195 /* {{{ proto public void ReflectionZendExtension::getCopyright()
6196 Returns this Zend extension's copyright information */
ZEND_METHOD(reflection_zend_extension,getCopyright)6197 ZEND_METHOD(reflection_zend_extension, getCopyright)
6198 {
6199 reflection_object *intern;
6200 zend_extension *extension;
6201
6202 if (zend_parse_parameters_none() == FAILURE) {
6203 return;
6204 }
6205 GET_REFLECTION_OBJECT_PTR(extension);
6206
6207 if (extension->copyright) {
6208 RETURN_STRING(extension->copyright);
6209 } else {
6210 RETURN_EMPTY_STRING();
6211 }
6212 }
6213 /* }}} */
6214
6215 /* {{{ proto public ReflectionReference::__construct()
6216 * Dummy constructor -- always throws ReflectionExceptions. */
ZEND_METHOD(reflection_reference,__construct)6217 ZEND_METHOD(reflection_reference, __construct)
6218 {
6219 _DO_THROW(
6220 "Cannot directly instantiate ReflectionReference. "
6221 "Use ReflectionReference::fromArrayElement() instead"
6222 );
6223 }
6224 /* }}} */
6225
is_ignorable_reference(HashTable * ht,zval * ref)6226 static zend_bool is_ignorable_reference(HashTable *ht, zval *ref) {
6227 if (Z_REFCOUNT_P(ref) != 1) {
6228 return 0;
6229 }
6230
6231 /* Directly self-referential arrays are treated as proper references
6232 * in zend_array_dup() despite rc=1. */
6233 return Z_TYPE_P(Z_REFVAL_P(ref)) != IS_ARRAY || Z_ARRVAL_P(Z_REFVAL_P(ref)) != ht;
6234 }
6235
6236 /* {{{ proto public ReflectionReference|null ReflectionReference::fromArrayElement(array array, mixed key)
6237 * Create ReflectionReference for array item. Returns null if not a reference. */
ZEND_METHOD(reflection_reference,fromArrayElement)6238 ZEND_METHOD(reflection_reference, fromArrayElement)
6239 {
6240 HashTable *ht;
6241 zval *key, *item;
6242 reflection_object *intern;
6243
6244 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "hz", &ht, &key) == FAILURE) {
6245 return;
6246 }
6247
6248 if (Z_TYPE_P(key) == IS_LONG) {
6249 item = zend_hash_index_find(ht, Z_LVAL_P(key));
6250 } else if (Z_TYPE_P(key) == IS_STRING) {
6251 item = zend_symtable_find(ht, Z_STR_P(key));
6252 } else {
6253 zend_type_error("Key must be array or string");
6254 return;
6255 }
6256
6257 if (!item) {
6258 _DO_THROW("Array key not found");
6259 return;
6260 }
6261
6262 if (Z_TYPE_P(item) != IS_REFERENCE || is_ignorable_reference(ht, item)) {
6263 RETURN_NULL();
6264 }
6265
6266 object_init_ex(return_value, reflection_reference_ptr);
6267 intern = Z_REFLECTION_P(return_value);
6268 ZVAL_COPY(&intern->obj, item);
6269 intern->ref_type = REF_TYPE_OTHER;
6270 }
6271 /* }}} */
6272
6273 /* {{{ proto public int|string ReflectionReference::getId()
6274 * Returns a unique identifier for the reference.
6275 * The format of the return value is unspecified and may change. */
ZEND_METHOD(reflection_reference,getId)6276 ZEND_METHOD(reflection_reference, getId)
6277 {
6278 reflection_object *intern;
6279 unsigned char digest[20];
6280 PHP_SHA1_CTX context;
6281
6282 if (zend_parse_parameters_none() == FAILURE) {
6283 return;
6284 }
6285
6286 intern = Z_REFLECTION_P(getThis());
6287 if (Z_TYPE(intern->obj) != IS_REFERENCE) {
6288 _DO_THROW("Corrupted ReflectionReference object");
6289 return;
6290 }
6291
6292 if (!REFLECTION_G(key_initialized)) {
6293 if (php_random_bytes_throw(&REFLECTION_G(key_initialized), 16) == FAILURE) {
6294 return;
6295 }
6296
6297 REFLECTION_G(key_initialized) = 1;
6298 }
6299
6300 /* SHA1(ref || key) to avoid directly exposing memory addresses. */
6301 PHP_SHA1Init(&context);
6302 PHP_SHA1Update(&context, (unsigned char *) &Z_REF(intern->obj), sizeof(zend_reference *));
6303 PHP_SHA1Update(&context, REFLECTION_G(key), REFLECTION_KEY_LEN);
6304 PHP_SHA1Final(digest, &context);
6305
6306 RETURN_STRINGL((char *) digest, sizeof(digest));
6307 }
6308 /* }}} */
6309
6310 /* {{{ method tables */
6311 static const zend_function_entry reflection_exception_functions[] = {
6312 PHP_FE_END
6313 };
6314
6315 ZEND_BEGIN_ARG_INFO(arginfo_reflection__void, 0)
6316 ZEND_END_ARG_INFO()
6317
6318
6319 ZEND_BEGIN_ARG_INFO(arginfo_reflection_getModifierNames, 0)
6320 ZEND_ARG_INFO(0, modifiers)
6321 ZEND_END_ARG_INFO()
6322
6323 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_export, 0, 0, 1)
6324 ZEND_ARG_OBJ_INFO(0, reflector, Reflector, 0)
6325 ZEND_ARG_INFO(0, return)
6326 ZEND_END_ARG_INFO()
6327
6328 static const zend_function_entry reflection_functions[] = {
6329 ZEND_ME(reflection, getModifierNames, arginfo_reflection_getModifierNames, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6330 ZEND_DEP_ME(reflection, export, arginfo_reflection_export, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6331 PHP_FE_END
6332 };
6333
6334 static const zend_function_entry reflector_functions[] = {
6335 ZEND_ABSTRACT_ME(reflector, __toString, arginfo_reflection__void)
6336 PHP_FE_END
6337 };
6338
6339 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_export, 0, 0, 1)
6340 ZEND_ARG_INFO(0, name)
6341 ZEND_ARG_INFO(0, return)
6342 ZEND_END_ARG_INFO()
6343
6344 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function___construct, 0)
6345 ZEND_ARG_INFO(0, name)
6346 ZEND_END_ARG_INFO()
6347
6348 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_invoke, 0, 0, 0)
6349 ZEND_ARG_INFO(0, args)
6350 ZEND_END_ARG_INFO()
6351
6352 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function_invokeArgs, 0)
6353 ZEND_ARG_ARRAY_INFO(0, args, 0)
6354 ZEND_END_ARG_INFO()
6355
6356 static const zend_function_entry reflection_function_abstract_functions[] = {
6357 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6358 ZEND_ME(reflection_function, inNamespace, arginfo_reflection__void, 0)
6359 ZEND_ME(reflection_function, isClosure, arginfo_reflection__void, 0)
6360 ZEND_ME(reflection_function, isDeprecated, arginfo_reflection__void, 0)
6361 ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0)
6362 ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0)
6363 ZEND_ME(reflection_function, isGenerator, arginfo_reflection__void, 0)
6364 ZEND_ME(reflection_function, isVariadic, arginfo_reflection__void, 0)
6365 ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0)
6366 ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0)
6367 ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
6368 ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
6369 ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
6370 ZEND_ME(reflection_function, getExtensionName, arginfo_reflection__void, 0)
6371 ZEND_ME(reflection_function, getFileName, arginfo_reflection__void, 0)
6372 ZEND_ME(reflection_function, getName, arginfo_reflection__void, 0)
6373 ZEND_ME(reflection_function, getNamespaceName, arginfo_reflection__void, 0)
6374 ZEND_ME(reflection_function, getNumberOfParameters, arginfo_reflection__void, 0)
6375 ZEND_ME(reflection_function, getNumberOfRequiredParameters, arginfo_reflection__void, 0)
6376 ZEND_ME(reflection_function, getParameters, arginfo_reflection__void, 0)
6377 ZEND_ME(reflection_function, getShortName, arginfo_reflection__void, 0)
6378 ZEND_ME(reflection_function, getStartLine, arginfo_reflection__void, 0)
6379 ZEND_ME(reflection_function, getStaticVariables, arginfo_reflection__void, 0)
6380 ZEND_ME(reflection_function, returnsReference, arginfo_reflection__void, 0)
6381 ZEND_ME(reflection_function, hasReturnType, arginfo_reflection__void, 0)
6382 ZEND_ME(reflection_function, getReturnType, arginfo_reflection__void, 0)
6383 PHP_FE_END
6384 };
6385
6386 static const zend_function_entry reflection_function_functions[] = {
6387 ZEND_ME(reflection_function, __construct, arginfo_reflection_function___construct, 0)
6388 ZEND_ME(reflection_function, __toString, arginfo_reflection__void, 0)
6389 ZEND_DEP_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6390 ZEND_ME(reflection_function, isDisabled, arginfo_reflection__void, 0)
6391 ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
6392 ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
6393 ZEND_ME(reflection_function, getClosure, arginfo_reflection__void, 0)
6394 PHP_FE_END
6395 };
6396
6397 ZEND_BEGIN_ARG_INFO(arginfo_reflection_generator___construct, 0)
6398 ZEND_ARG_INFO(0, generator)
6399 ZEND_END_ARG_INFO()
6400
6401 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_generator_trace, 0, 0, 0)
6402 ZEND_ARG_INFO(0, options)
6403 ZEND_END_ARG_INFO()
6404
6405 static const zend_function_entry reflection_generator_functions[] = {
6406 ZEND_ME(reflection_generator, __construct, arginfo_reflection_generator___construct, 0)
6407 ZEND_ME(reflection_generator, getExecutingLine, arginfo_reflection__void, 0)
6408 ZEND_ME(reflection_generator, getExecutingFile, arginfo_reflection__void, 0)
6409 ZEND_ME(reflection_generator, getTrace, arginfo_reflection_generator_trace, 0)
6410 ZEND_ME(reflection_generator, getFunction, arginfo_reflection__void, 0)
6411 ZEND_ME(reflection_generator, getThis, arginfo_reflection__void, 0)
6412 ZEND_ME(reflection_generator, getExecutingGenerator, arginfo_reflection__void, 0)
6413 PHP_FE_END
6414 };
6415
6416 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_export, 0, 0, 2)
6417 ZEND_ARG_INFO(0, class)
6418 ZEND_ARG_INFO(0, name)
6419 ZEND_ARG_INFO(0, return)
6420 ZEND_END_ARG_INFO()
6421
6422 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method___construct, 0, 0, 1)
6423 ZEND_ARG_INFO(0, class_or_method)
6424 ZEND_ARG_INFO(0, name)
6425 ZEND_END_ARG_INFO()
6426
6427 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invoke, 0)
6428 ZEND_ARG_INFO(0, object)
6429 ZEND_ARG_INFO(0, args)
6430 ZEND_END_ARG_INFO()
6431
6432 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invokeArgs, 0)
6433 ZEND_ARG_INFO(0, object)
6434 ZEND_ARG_ARRAY_INFO(0, args, 0)
6435 ZEND_END_ARG_INFO()
6436
6437 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
6438 ZEND_ARG_INFO(0, value)
6439 ZEND_END_ARG_INFO()
6440
6441 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_getClosure, 0, 0, 0)
6442 ZEND_ARG_INFO(0, object)
6443 ZEND_END_ARG_INFO()
6444
6445 static const zend_function_entry reflection_method_functions[] = {
6446 ZEND_DEP_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6447 ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
6448 ZEND_ME(reflection_method, __toString, arginfo_reflection__void, 0)
6449 ZEND_ME(reflection_method, isPublic, arginfo_reflection__void, 0)
6450 ZEND_ME(reflection_method, isPrivate, arginfo_reflection__void, 0)
6451 ZEND_ME(reflection_method, isProtected, arginfo_reflection__void, 0)
6452 ZEND_ME(reflection_method, isAbstract, arginfo_reflection__void, 0)
6453 ZEND_ME(reflection_method, isFinal, arginfo_reflection__void, 0)
6454 ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0)
6455 ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
6456 ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0)
6457 ZEND_ME(reflection_method, getClosure, arginfo_reflection_method_getClosure, 0)
6458 ZEND_ME(reflection_method, getModifiers, arginfo_reflection__void, 0)
6459 ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
6460 ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
6461 ZEND_ME(reflection_method, getDeclaringClass, arginfo_reflection__void, 0)
6462 ZEND_ME(reflection_method, getPrototype, arginfo_reflection__void, 0)
6463 ZEND_ME(reflection_method, setAccessible, arginfo_reflection_method_setAccessible, 0)
6464 PHP_FE_END
6465 };
6466
6467
6468 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_export, 0, 0, 1)
6469 ZEND_ARG_INFO(0, argument)
6470 ZEND_ARG_INFO(0, return)
6471 ZEND_END_ARG_INFO()
6472
6473 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class___construct, 0)
6474 ZEND_ARG_INFO(0, argument)
6475 ZEND_END_ARG_INFO()
6476
6477 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getStaticPropertyValue, 0, 0, 1)
6478 ZEND_ARG_INFO(0, name)
6479 ZEND_ARG_INFO(0, default)
6480 ZEND_END_ARG_INFO()
6481
6482 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_setStaticPropertyValue, 0)
6483 ZEND_ARG_INFO(0, name)
6484 ZEND_ARG_INFO(0, value)
6485 ZEND_END_ARG_INFO()
6486
6487 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasMethod, 0)
6488 ZEND_ARG_INFO(0, name)
6489 ZEND_END_ARG_INFO()
6490
6491 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getMethod, 0)
6492 ZEND_ARG_INFO(0, name)
6493 ZEND_END_ARG_INFO()
6494
6495 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getMethods, 0, 0, 0)
6496 ZEND_ARG_INFO(0, filter)
6497 ZEND_END_ARG_INFO()
6498
6499 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasProperty, 0)
6500 ZEND_ARG_INFO(0, name)
6501 ZEND_END_ARG_INFO()
6502
6503 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getProperty, 0)
6504 ZEND_ARG_INFO(0, name)
6505 ZEND_END_ARG_INFO()
6506
6507 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getProperties, 0, 0, 0)
6508 ZEND_ARG_INFO(0, filter)
6509 ZEND_END_ARG_INFO()
6510
6511 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasConstant, 0)
6512 ZEND_ARG_INFO(0, name)
6513 ZEND_END_ARG_INFO()
6514
6515 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getConstant, 0)
6516 ZEND_ARG_INFO(0, name)
6517 ZEND_END_ARG_INFO()
6518
6519 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isInstance, 0)
6520 ZEND_ARG_INFO(0, object)
6521 ZEND_END_ARG_INFO()
6522
6523 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
6524 ZEND_ARG_INFO(0, args)
6525 ZEND_END_ARG_INFO()
6526
6527 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6528 ZEND_END_ARG_INFO()
6529
6530 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
6531 ZEND_ARG_ARRAY_INFO(0, args, 0)
6532 ZEND_END_ARG_INFO()
6533
6534 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isSubclassOf, 0)
6535 ZEND_ARG_INFO(0, class)
6536 ZEND_END_ARG_INFO()
6537
6538 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_implementsInterface, 0)
6539 ZEND_ARG_INFO(0, interface)
6540 ZEND_END_ARG_INFO()
6541
6542 static const zend_function_entry reflection_class_functions[] = {
6543 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6544 ZEND_DEP_ME(reflection_class, export, arginfo_reflection_class_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6545 ZEND_ME(reflection_class, __construct, arginfo_reflection_class___construct, 0)
6546 ZEND_ME(reflection_class, __toString, arginfo_reflection__void, 0)
6547 ZEND_ME(reflection_class, getName, arginfo_reflection__void, 0)
6548 ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
6549 ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
6550 ZEND_ME(reflection_class, isAnonymous, arginfo_reflection__void, 0)
6551 ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
6552 ZEND_ME(reflection_class, isCloneable, arginfo_reflection__void, 0)
6553 ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
6554 ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0)
6555 ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0)
6556 ZEND_ME(reflection_class, getDocComment, arginfo_reflection__void, 0)
6557 ZEND_ME(reflection_class, getConstructor, arginfo_reflection__void, 0)
6558 ZEND_ME(reflection_class, hasMethod, arginfo_reflection_class_hasMethod, 0)
6559 ZEND_ME(reflection_class, getMethod, arginfo_reflection_class_getMethod, 0)
6560 ZEND_ME(reflection_class, getMethods, arginfo_reflection_class_getMethods, 0)
6561 ZEND_ME(reflection_class, hasProperty, arginfo_reflection_class_hasProperty, 0)
6562 ZEND_ME(reflection_class, getProperty, arginfo_reflection_class_getProperty, 0)
6563 ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
6564 ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
6565 ZEND_ME(reflection_class, getConstants, arginfo_reflection__void, 0)
6566 ZEND_ME(reflection_class, getReflectionConstants, arginfo_reflection__void, 0)
6567 ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
6568 ZEND_ME(reflection_class, getReflectionConstant, arginfo_reflection_class_getConstant, 0)
6569 ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
6570 ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
6571 ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
6572 ZEND_ME(reflection_class, getTraits, arginfo_reflection__void, 0)
6573 ZEND_ME(reflection_class, getTraitNames, arginfo_reflection__void, 0)
6574 ZEND_ME(reflection_class, getTraitAliases, arginfo_reflection__void, 0)
6575 ZEND_ME(reflection_class, isTrait, arginfo_reflection__void, 0)
6576 ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0)
6577 ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0)
6578 ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0)
6579 ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
6580 ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
6581 ZEND_ME(reflection_class, newInstanceWithoutConstructor, arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6582 ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
6583 ZEND_ME(reflection_class, getParentClass, arginfo_reflection__void, 0)
6584 ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
6585 ZEND_ME(reflection_class, getStaticProperties, arginfo_reflection__void, 0)
6586 ZEND_ME(reflection_class, getStaticPropertyValue, arginfo_reflection_class_getStaticPropertyValue, 0)
6587 ZEND_ME(reflection_class, setStaticPropertyValue, arginfo_reflection_class_setStaticPropertyValue, 0)
6588 ZEND_ME(reflection_class, getDefaultProperties, arginfo_reflection__void, 0)
6589 ZEND_ME(reflection_class, isIterable, arginfo_reflection__void, 0)
6590 ZEND_MALIAS(reflection_class, isIterateable, isIterable, arginfo_reflection__void, 0)
6591 ZEND_ME(reflection_class, implementsInterface, arginfo_reflection_class_implementsInterface, 0)
6592 ZEND_ME(reflection_class, getExtension, arginfo_reflection__void, 0)
6593 ZEND_ME(reflection_class, getExtensionName, arginfo_reflection__void, 0)
6594 ZEND_ME(reflection_class, inNamespace, arginfo_reflection__void, 0)
6595 ZEND_ME(reflection_class, getNamespaceName, arginfo_reflection__void, 0)
6596 ZEND_ME(reflection_class, getShortName, arginfo_reflection__void, 0)
6597 PHP_FE_END
6598 };
6599
6600
6601 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_object_export, 0, 0, 1)
6602 ZEND_ARG_INFO(0, argument)
6603 ZEND_ARG_INFO(0, return)
6604 ZEND_END_ARG_INFO()
6605
6606 ZEND_BEGIN_ARG_INFO(arginfo_reflection_object___construct, 0)
6607 ZEND_ARG_INFO(0, argument)
6608 ZEND_END_ARG_INFO()
6609
6610 static const zend_function_entry reflection_object_functions[] = {
6611 ZEND_DEP_ME(reflection_object, export, arginfo_reflection_object_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6612 ZEND_ME(reflection_object, __construct, arginfo_reflection_object___construct, 0)
6613 PHP_FE_END
6614 };
6615
6616
6617 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_export, 0, 0, 2)
6618 ZEND_ARG_INFO(0, class)
6619 ZEND_ARG_INFO(0, name)
6620 ZEND_ARG_INFO(0, return)
6621 ZEND_END_ARG_INFO()
6622
6623 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property___construct, 0, 0, 2)
6624 ZEND_ARG_INFO(0, class)
6625 ZEND_ARG_INFO(0, name)
6626 ZEND_END_ARG_INFO()
6627
6628 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_getValue, 0, 0, 0)
6629 ZEND_ARG_INFO(0, object)
6630 ZEND_END_ARG_INFO()
6631
6632 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_setValue, 0, 0, 1)
6633 ZEND_ARG_INFO(0, object)
6634 ZEND_ARG_INFO(0, value)
6635 ZEND_END_ARG_INFO()
6636
6637 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_isInitialized, 0, 0, 0)
6638 ZEND_ARG_INFO(0, object)
6639 ZEND_END_ARG_INFO()
6640
6641 ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccessible, 0)
6642 ZEND_ARG_INFO(0, visible)
6643 ZEND_END_ARG_INFO()
6644
6645 static const zend_function_entry reflection_property_functions[] = {
6646 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6647 ZEND_DEP_ME(reflection_property, export, arginfo_reflection_property_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6648 ZEND_ME(reflection_property, __construct, arginfo_reflection_property___construct, 0)
6649 ZEND_ME(reflection_property, __toString, arginfo_reflection__void, 0)
6650 ZEND_ME(reflection_property, getName, arginfo_reflection__void, 0)
6651 ZEND_ME(reflection_property, getValue, arginfo_reflection_property_getValue, 0)
6652 ZEND_ME(reflection_property, setValue, arginfo_reflection_property_setValue, 0)
6653 ZEND_ME(reflection_property, isInitialized, arginfo_reflection_property_isInitialized, 0)
6654 ZEND_ME(reflection_property, isPublic, arginfo_reflection__void, 0)
6655 ZEND_ME(reflection_property, isPrivate, arginfo_reflection__void, 0)
6656 ZEND_ME(reflection_property, isProtected, arginfo_reflection__void, 0)
6657 ZEND_ME(reflection_property, isStatic, arginfo_reflection__void, 0)
6658 ZEND_ME(reflection_property, isDefault, arginfo_reflection__void, 0)
6659 ZEND_ME(reflection_property, getModifiers, arginfo_reflection__void, 0)
6660 ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0)
6661 ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0)
6662 ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0)
6663 ZEND_ME(reflection_property, getType, arginfo_reflection__void, 0)
6664 ZEND_ME(reflection_property, hasType, arginfo_reflection__void, 0)
6665 PHP_FE_END
6666 };
6667
6668 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant_export, 0, 0, 2)
6669 ZEND_ARG_INFO(0, class)
6670 ZEND_ARG_INFO(0, name)
6671 ZEND_ARG_INFO(0, return)
6672 ZEND_END_ARG_INFO()
6673
6674 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant___construct, 0, 0, 2)
6675 ZEND_ARG_INFO(0, class)
6676 ZEND_ARG_INFO(0, name)
6677 ZEND_END_ARG_INFO()
6678
6679 static const zend_function_entry reflection_class_constant_functions[] = {
6680 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6681 ZEND_DEP_ME(reflection_class_constant, export, arginfo_reflection_class_constant_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6682 ZEND_ME(reflection_class_constant, __construct, arginfo_reflection_class_constant___construct, 0)
6683 ZEND_ME(reflection_class_constant, __toString, arginfo_reflection__void, 0)
6684 ZEND_ME(reflection_class_constant, getName, arginfo_reflection__void, 0)
6685 ZEND_ME(reflection_class_constant, getValue, arginfo_reflection__void, 0)
6686 ZEND_ME(reflection_class_constant, isPublic, arginfo_reflection__void, 0)
6687 ZEND_ME(reflection_class_constant, isPrivate, arginfo_reflection__void, 0)
6688 ZEND_ME(reflection_class_constant, isProtected, arginfo_reflection__void, 0)
6689 ZEND_ME(reflection_class_constant, getModifiers, arginfo_reflection__void, 0)
6690 ZEND_ME(reflection_class_constant, getDeclaringClass, arginfo_reflection__void, 0)
6691 ZEND_ME(reflection_class_constant, getDocComment, arginfo_reflection__void, 0)
6692 PHP_FE_END
6693 };
6694
6695 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
6696 ZEND_ARG_INFO(0, function)
6697 ZEND_ARG_INFO(0, parameter)
6698 ZEND_ARG_INFO(0, return)
6699 ZEND_END_ARG_INFO()
6700
6701 ZEND_BEGIN_ARG_INFO(arginfo_reflection_parameter___construct, 0)
6702 ZEND_ARG_INFO(0, function)
6703 ZEND_ARG_INFO(0, parameter)
6704 ZEND_END_ARG_INFO()
6705
6706 static const zend_function_entry reflection_parameter_functions[] = {
6707 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6708 ZEND_DEP_ME(reflection_parameter, export, arginfo_reflection_parameter_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6709 ZEND_ME(reflection_parameter, __construct, arginfo_reflection_parameter___construct, 0)
6710 ZEND_ME(reflection_parameter, __toString, arginfo_reflection__void, 0)
6711 ZEND_ME(reflection_parameter, getName, arginfo_reflection__void, 0)
6712 ZEND_ME(reflection_parameter, isPassedByReference, arginfo_reflection__void, 0)
6713 ZEND_ME(reflection_parameter, canBePassedByValue, arginfo_reflection__void, 0)
6714 ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
6715 ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
6716 ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
6717 ZEND_ME(reflection_parameter, hasType, arginfo_reflection__void, 0)
6718 ZEND_ME(reflection_parameter, getType, arginfo_reflection__void, 0)
6719 ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
6720 ZEND_ME(reflection_parameter, isCallable, arginfo_reflection__void, 0)
6721 ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
6722 ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
6723 ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
6724 ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0)
6725 ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0)
6726 ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0)
6727 ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0)
6728 ZEND_ME(reflection_parameter, isVariadic, arginfo_reflection__void, 0)
6729 PHP_FE_END
6730 };
6731
6732 static const zend_function_entry reflection_type_functions[] = {
6733 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6734 ZEND_ME(reflection_type, allowsNull, arginfo_reflection__void, 0)
6735 ZEND_ME(reflection_type, isBuiltin, arginfo_reflection__void, 0)
6736 ZEND_ME(reflection_type, __toString, arginfo_reflection__void, ZEND_ACC_DEPRECATED)
6737 PHP_FE_END
6738 };
6739
6740 static const zend_function_entry reflection_named_type_functions[] = {
6741 ZEND_ME(reflection_named_type, getName, arginfo_reflection__void, 0)
6742 PHP_FE_END
6743 };
6744
6745 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
6746 ZEND_ARG_INFO(0, name)
6747 ZEND_ARG_INFO(0, return)
6748 ZEND_END_ARG_INFO()
6749
6750 ZEND_BEGIN_ARG_INFO(arginfo_reflection_extension___construct, 0)
6751 ZEND_ARG_INFO(0, name)
6752 ZEND_END_ARG_INFO()
6753
6754 static const zend_function_entry reflection_extension_functions[] = {
6755 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6756 ZEND_DEP_ME(reflection_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6757 ZEND_ME(reflection_extension, __construct, arginfo_reflection_extension___construct, 0)
6758 ZEND_ME(reflection_extension, __toString, arginfo_reflection__void, 0)
6759 ZEND_ME(reflection_extension, getName, arginfo_reflection__void, 0)
6760 ZEND_ME(reflection_extension, getVersion, arginfo_reflection__void, 0)
6761 ZEND_ME(reflection_extension, getFunctions, arginfo_reflection__void, 0)
6762 ZEND_ME(reflection_extension, getConstants, arginfo_reflection__void, 0)
6763 ZEND_ME(reflection_extension, getINIEntries, arginfo_reflection__void, 0)
6764 ZEND_ME(reflection_extension, getClasses, arginfo_reflection__void, 0)
6765 ZEND_ME(reflection_extension, getClassNames, arginfo_reflection__void, 0)
6766 ZEND_ME(reflection_extension, getDependencies, arginfo_reflection__void, 0)
6767 ZEND_ME(reflection_extension, info, arginfo_reflection__void, 0)
6768 ZEND_ME(reflection_extension, isPersistent, arginfo_reflection__void, 0)
6769 ZEND_ME(reflection_extension, isTemporary, arginfo_reflection__void, 0)
6770 PHP_FE_END
6771 };
6772
6773 ZEND_BEGIN_ARG_INFO(arginfo_reflection_zend_extension___construct, 0)
6774 ZEND_ARG_INFO(0, name)
6775 ZEND_END_ARG_INFO()
6776
6777 static const zend_function_entry reflection_zend_extension_functions[] = {
6778 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6779 ZEND_DEP_ME(reflection_zend_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6780 ZEND_ME(reflection_zend_extension, __construct, arginfo_reflection_zend_extension___construct, 0)
6781 ZEND_ME(reflection_zend_extension, __toString, arginfo_reflection__void, 0)
6782 ZEND_ME(reflection_zend_extension, getName, arginfo_reflection__void, 0)
6783 ZEND_ME(reflection_zend_extension, getVersion, arginfo_reflection__void, 0)
6784 ZEND_ME(reflection_zend_extension, getAuthor, arginfo_reflection__void, 0)
6785 ZEND_ME(reflection_zend_extension, getURL, arginfo_reflection__void, 0)
6786 ZEND_ME(reflection_zend_extension, getCopyright, arginfo_reflection__void, 0)
6787 PHP_FE_END
6788 };
6789
6790 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_reference_fromArrayElement, 0, 0, 2)
6791 ZEND_ARG_INFO(0, array)
6792 ZEND_ARG_INFO(0, key)
6793 ZEND_END_ARG_INFO()
6794
6795 static const zend_function_entry reflection_reference_functions[] = {
6796 ZEND_ME(reflection_reference, fromArrayElement, arginfo_reflection_reference_fromArrayElement, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6797 ZEND_ME(reflection_reference, getId, arginfo_reflection__void, ZEND_ACC_PUBLIC)
6798
6799 /* Always throwing dummy methods */
6800 ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE)
6801 ZEND_ME(reflection_reference, __construct, arginfo_reflection__void, ZEND_ACC_PRIVATE)
6802 PHP_FE_END
6803 };
6804 /* }}} */
6805
6806 static const zend_function_entry reflection_ext_functions[] = { /* {{{ */
6807 PHP_FE_END
6808 }; /* }}} */
6809
6810 /* {{{ _reflection_write_property */
_reflection_write_property(zval * object,zval * member,zval * value,void ** cache_slot)6811 static zval *_reflection_write_property(zval *object, zval *member, zval *value, void **cache_slot)
6812 {
6813 if ((Z_TYPE_P(member) == IS_STRING)
6814 && zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STR_P(member))
6815 && ((Z_STRLEN_P(member) == sizeof("name") - 1 && !memcmp(Z_STRVAL_P(member), "name", sizeof("name")))
6816 || (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
6817 {
6818 zend_throw_exception_ex(reflection_exception_ptr, 0,
6819 "Cannot set read-only property %s::$%s", ZSTR_VAL(Z_OBJCE_P(object)->name), Z_STRVAL_P(member));
6820 return &EG(uninitialized_zval);
6821 }
6822 else
6823 {
6824 return zend_std_write_property(object, member, value, cache_slot);
6825 }
6826 }
6827 /* }}} */
6828
reflection_init_class_handlers(zend_class_entry * ce)6829 static void reflection_init_class_handlers(zend_class_entry *ce) {
6830 ce->create_object = reflection_objects_new;
6831 ce->serialize = zend_class_serialize_deny;
6832 ce->unserialize = zend_class_unserialize_deny;
6833 }
6834
PHP_MINIT_FUNCTION(reflection)6835 PHP_MINIT_FUNCTION(reflection) /* {{{ */
6836 {
6837 zend_class_entry _reflection_entry;
6838
6839 memcpy(&reflection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
6840 reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
6841 reflection_object_handlers.free_obj = reflection_free_objects_storage;
6842 reflection_object_handlers.clone_obj = NULL;
6843 reflection_object_handlers.write_property = _reflection_write_property;
6844 reflection_object_handlers.get_gc = reflection_get_gc;
6845
6846 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions);
6847 reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_ce_exception);
6848
6849 INIT_CLASS_ENTRY(_reflection_entry, "Reflection", reflection_functions);
6850 reflection_ptr = zend_register_internal_class(&_reflection_entry);
6851
6852 INIT_CLASS_ENTRY(_reflection_entry, "Reflector", reflector_functions);
6853 reflector_ptr = zend_register_internal_interface(&_reflection_entry);
6854
6855 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions);
6856 reflection_init_class_handlers(&_reflection_entry);
6857 reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry);
6858 zend_class_implements(reflection_function_abstract_ptr, 1, reflector_ptr);
6859 zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT);
6860
6861 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", reflection_function_functions);
6862 reflection_init_class_handlers(&_reflection_entry);
6863 reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6864 zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6865
6866 REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
6867
6868 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionGenerator", reflection_generator_functions);
6869 reflection_init_class_handlers(&_reflection_entry);
6870 reflection_generator_ptr = zend_register_internal_class(&_reflection_entry);
6871
6872 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions);
6873 reflection_init_class_handlers(&_reflection_entry);
6874 reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry);
6875 zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
6876 zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6877
6878 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
6879 reflection_init_class_handlers(&_reflection_entry);
6880 reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
6881
6882 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", reflection_named_type_functions);
6883 reflection_init_class_handlers(&_reflection_entry);
6884 reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
6885
6886 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
6887 reflection_init_class_handlers(&_reflection_entry);
6888 reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6889 zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6890 zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6891
6892 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
6893 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6894 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6895 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6896 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
6897 REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
6898
6899 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions);
6900 reflection_init_class_handlers(&_reflection_entry);
6901 reflection_class_ptr = zend_register_internal_class(&_reflection_entry);
6902 zend_class_implements(reflection_class_ptr, 1, reflector_ptr);
6903 zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6904
6905 /* IS_IMPLICIT_ABSTRACT is not longer used */
6906 REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
6907 REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
6908 REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL);
6909
6910 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions);
6911 reflection_init_class_handlers(&_reflection_entry);
6912 reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr);
6913
6914 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", reflection_property_functions);
6915 reflection_init_class_handlers(&_reflection_entry);
6916 reflection_property_ptr = zend_register_internal_class(&_reflection_entry);
6917 zend_class_implements(reflection_property_ptr, 1, reflector_ptr);
6918 zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6919 zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6920
6921 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", reflection_class_constant_functions);
6922 reflection_init_class_handlers(&_reflection_entry);
6923 reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
6924 zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
6925 zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6926 zend_declare_property_string(reflection_class_constant_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6927
6928 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
6929 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6930 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6931 REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6932
6933 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions);
6934 reflection_init_class_handlers(&_reflection_entry);
6935 reflection_extension_ptr = zend_register_internal_class(&_reflection_entry);
6936 zend_class_implements(reflection_extension_ptr, 1, reflector_ptr);
6937 zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6938
6939 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", reflection_zend_extension_functions);
6940 reflection_init_class_handlers(&_reflection_entry);
6941 reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry);
6942 zend_class_implements(reflection_zend_extension_ptr, 1, reflector_ptr);
6943 zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6944
6945 INIT_CLASS_ENTRY(_reflection_entry, "ReflectionReference", reflection_reference_functions);
6946 reflection_init_class_handlers(&_reflection_entry);
6947 _reflection_entry.ce_flags |= ZEND_ACC_FINAL;
6948 reflection_reference_ptr = zend_register_internal_class(&_reflection_entry);
6949
6950 REFLECTION_G(key_initialized) = 0;
6951
6952 return SUCCESS;
6953 } /* }}} */
6954
PHP_MINFO_FUNCTION(reflection)6955 PHP_MINFO_FUNCTION(reflection) /* {{{ */
6956 {
6957 php_info_print_table_start();
6958 php_info_print_table_row(2, "Reflection", "enabled");
6959 php_info_print_table_end();
6960 } /* }}} */
6961
6962 zend_module_entry reflection_module_entry = { /* {{{ */
6963 STANDARD_MODULE_HEADER,
6964 "Reflection",
6965 reflection_ext_functions,
6966 PHP_MINIT(reflection),
6967 NULL,
6968 NULL,
6969 NULL,
6970 PHP_MINFO(reflection),
6971 PHP_REFLECTION_VERSION,
6972 ZEND_MODULE_GLOBALS(reflection),
6973 NULL,
6974 NULL,
6975 NULL,
6976 STANDARD_MODULE_PROPERTIES_EX
6977 }; /* }}} */
6978