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