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