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