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