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