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