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