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(¶m_indent);
890 string_printf(¶m_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(¶m_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, "*", ¶ms, &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", ¶m_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, ¶ms 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, ¶meter) == 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, "+", ¶ms, &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, ¶m_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, ¶ms 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, "*", ¶ms, &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, ¶ms 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