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