1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 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 | | Author: Sascha Schumann <sascha@schumann.cx> | |
16 | +----------------------------------------------------------------------+ |
17 | */ |
18 | |
19 | /* $Id$ */ |
20 | |
21 | #include "php.h" |
22 | #include "basic_functions.h" |
23 | #include "php_incomplete_class.h" |
24 | |
25 | #define INCOMPLETE_CLASS_MSG \ |
26 | "The script tried to execute a method or " \ |
27 | "access a property of an incomplete object. " \ |
28 | "Please ensure that the class definition \"%s\" of the object " \ |
29 | "you are trying to operate on was loaded _before_ " \ |
30 | "unserialize() gets called or provide a __autoload() function " \ |
31 | "to load the class definition " |
32 | |
33 | static zend_object_handlers php_incomplete_object_handlers; |
34 | |
35 | /* {{{ incomplete_class_message |
36 | */ |
37 | static void incomplete_class_message(zval *object, int error_type TSRMLS_DC) |
38 | { |
39 | char *class_name; |
40 | zend_bool class_name_alloced = 1; |
41 | |
42 | class_name = php_lookup_class_name(object, NULL); |
43 | |
44 | if (!class_name) { |
45 | class_name_alloced = 0; |
46 | class_name = "unknown" ; |
47 | } |
48 | |
49 | php_error_docref(NULL TSRMLS_CC, error_type, INCOMPLETE_CLASS_MSG, class_name); |
50 | |
51 | if (class_name_alloced) { |
52 | efree(class_name); |
53 | } |
54 | } |
55 | /* }}} */ |
56 | |
57 | static zval *incomplete_class_get_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ |
58 | { |
59 | incomplete_class_message(object, E_NOTICE TSRMLS_CC); |
60 | |
61 | if (type == BP_VAR_W || type == BP_VAR_RW) { |
62 | return EG(error_zval_ptr); |
63 | } else { |
64 | return EG(uninitialized_zval_ptr); |
65 | } |
66 | } |
67 | /* }}} */ |
68 | |
69 | static void incomplete_class_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */ |
70 | { |
71 | incomplete_class_message(object, E_NOTICE TSRMLS_CC); |
72 | } |
73 | /* }}} */ |
74 | |
75 | static zval **incomplete_class_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ |
76 | { |
77 | incomplete_class_message(object, E_NOTICE TSRMLS_CC); |
78 | return &EG(error_zval_ptr); |
79 | } |
80 | /* }}} */ |
81 | |
82 | static void incomplete_class_unset_property(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */ |
83 | { |
84 | incomplete_class_message(object, E_NOTICE TSRMLS_CC); |
85 | } |
86 | /* }}} */ |
87 | |
88 | static int incomplete_class_has_property(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC) /* {{{ */ |
89 | { |
90 | incomplete_class_message(object, E_NOTICE TSRMLS_CC); |
91 | return 0; |
92 | } |
93 | /* }}} */ |
94 | |
95 | static union _zend_function *incomplete_class_get_method(zval **object, char *method, int method_len, const zend_literal *key TSRMLS_DC) /* {{{ */ |
96 | { |
97 | incomplete_class_message(*object, E_ERROR TSRMLS_CC); |
98 | return NULL; |
99 | } |
100 | /* }}} */ |
101 | |
102 | /* {{{ php_create_incomplete_class |
103 | */ |
104 | static zend_object_value php_create_incomplete_object(zend_class_entry *class_type TSRMLS_DC) |
105 | { |
106 | zend_object *object; |
107 | zend_object_value value; |
108 | |
109 | value = zend_objects_new(&object, class_type TSRMLS_CC); |
110 | value.handlers = &php_incomplete_object_handlers; |
111 | |
112 | object_properties_init(object, class_type); |
113 | |
114 | return value; |
115 | } |
116 | |
117 | PHPAPI zend_class_entry *php_create_incomplete_class(TSRMLS_D) |
118 | { |
119 | zend_class_entry incomplete_class; |
120 | |
121 | INIT_CLASS_ENTRY(incomplete_class, INCOMPLETE_CLASS, NULL); |
122 | incomplete_class.create_object = php_create_incomplete_object; |
123 | |
124 | memcpy(&php_incomplete_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); |
125 | php_incomplete_object_handlers.read_property = incomplete_class_get_property; |
126 | php_incomplete_object_handlers.has_property = incomplete_class_has_property; |
127 | php_incomplete_object_handlers.unset_property = incomplete_class_unset_property; |
128 | php_incomplete_object_handlers.write_property = incomplete_class_write_property; |
129 | php_incomplete_object_handlers.get_property_ptr_ptr = incomplete_class_get_property_ptr_ptr; |
130 | php_incomplete_object_handlers.get_method = incomplete_class_get_method; |
131 | |
132 | return zend_register_internal_class(&incomplete_class TSRMLS_CC); |
133 | } |
134 | /* }}} */ |
135 | |
136 | /* {{{ php_lookup_class_name |
137 | */ |
138 | PHPAPI char *php_lookup_class_name(zval *object, zend_uint *nlen) |
139 | { |
140 | zval **val; |
141 | char *retval = NULL; |
142 | HashTable *object_properties; |
143 | TSRMLS_FETCH(); |
144 | |
145 | object_properties = Z_OBJPROP_P(object); |
146 | |
147 | if (zend_hash_find(object_properties, MAGIC_MEMBER, sizeof(MAGIC_MEMBER), (void **) &val) == SUCCESS && Z_TYPE_PP(val) == IS_STRING) { |
148 | retval = estrndup(Z_STRVAL_PP(val), Z_STRLEN_PP(val)); |
149 | |
150 | if (nlen) { |
151 | *nlen = Z_STRLEN_PP(val); |
152 | } |
153 | } |
154 | |
155 | return retval; |
156 | } |
157 | /* }}} */ |
158 | |
159 | /* {{{ php_store_class_name |
160 | */ |
161 | PHPAPI void php_store_class_name(zval *object, const char *name, zend_uint len) |
162 | { |
163 | zval *val; |
164 | TSRMLS_FETCH(); |
165 | |
166 | MAKE_STD_ZVAL(val); |
167 | |
168 | Z_TYPE_P(val) = IS_STRING; |
169 | Z_STRVAL_P(val) = estrndup(name, len); |
170 | Z_STRLEN_P(val) = len; |
171 | |
172 | zend_hash_update(Z_OBJPROP_P(object), MAGIC_MEMBER, sizeof(MAGIC_MEMBER), &val, sizeof(val), NULL); |
173 | } |
174 | /* }}} */ |
175 | |
176 | /* |
177 | * Local variables: |
178 | * tab-width: 4 |
179 | * c-basic-offset: 4 |
180 | * End: |
181 | * vim600: sw=4 ts=4 fdm=marker |
182 | * vim<600: sw=4 ts=4 |
183 | */ |
184 | |