xref: /PHP-7.2/ext/reflection/php_reflection.c (revision bea2ff88)
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(&param_indent, "%s  ", indent);
833 	smart_str_0(&param_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(&param_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(&params[0], argument_ptr);
1345 		ZVAL_NULL(&params[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(&params[0], argument_ptr);
1351 		ZVAL_COPY_VALUE(&params[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(&params[0], &reflector);
1390 	ZVAL_BOOL(&params[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(), "*", &params, &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", &param_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(&params[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(&params[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 			&parameter
2070 		);
2071 		add_next_index_zval(return_value, &parameter);
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(&current->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, &parameter) == 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(&param->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(&param->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(&param->fptr->op_array, precv->op2)) == IS_CONSTANT) {
2868 		RETURN_STR_COPY(Z_STR_P(RT_CONSTANT(&param->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, &params, &argc) == FAILURE) {
3165 			return;
3166 		}
3167 	} else {
3168 		if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, &param_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(&params[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(&params[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(), "*", &params, &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(&params[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(&params[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(&params[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