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