1 /**********************************************************************
2 * $Id: php_mapscript.c 9765 2010-01-28 15:32:10Z aboudreault $
3 *
4 * Project: MapServer
5 * Purpose: PHP/MapScript extension for MapServer. External interface
6 * functions
7 * Author: Daniel Morissette, DM Solutions Group (dmorissette@dmsolutions.ca)
8 * Alan Boudreault, Mapgears
9 *
10 **********************************************************************
11 * Copyright (c) 2000-2010, Daniel Morissette, DM Solutions Group Inc.
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies of this Software or works derived from this Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 * DEALINGS IN THE SOFTWARE.
30 **********************************************************************/
31
32 #include "php_mapscript.h"
33
34 #if PHP_VERSION_ID >= 50625 && PHP_VERSION_ID < 70000
35 #undef ZVAL_STRING
36 #define ZVAL_STRING(z, s, duplicate) do { \
37 const char *__s=(s); \
38 zval *__z = (z); \
39 Z_STRLEN_P(__z) = strlen(__s); \
40 Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\
41 Z_TYPE_P(__z) = IS_STRING; \
42 } while (0)
43 #endif
44
45 #undef ZVAL_STRING
46 #define ZVAL_STRING(z, s, duplicate) do { \
47 const char *__s=(s); \
48 zval *__z = (z); \
49 Z_STRLEN_P(__z) = strlen(__s); \
50 Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\
51 Z_TYPE_P(__z) = IS_STRING; \
52 } while (0)
53
54 zend_class_entry *mapscript_ce_error;
55 #if PHP_VERSION_ID >= 70000
56 zend_object_handlers mapscript_error_object_handlers;
57 #endif
58
59 ZEND_BEGIN_ARG_INFO_EX(error___get_args, 0, 0, 1)
60 ZEND_ARG_INFO(0, property)
ZEND_END_ARG_INFO()61 ZEND_END_ARG_INFO()
62
63 ZEND_BEGIN_ARG_INFO_EX(error___set_args, 0, 0, 2)
64 ZEND_ARG_INFO(0, property)
65 ZEND_ARG_INFO(0, value)
66 ZEND_END_ARG_INFO()
67
68 /* {{{ proto error __construct()
69 errorObj CANNOT be instanciated, this will throw an exception on use */
70 PHP_METHOD(errorObj, __construct)
71 {
72 mapscript_throw_exception("errorObj cannot be constructed" TSRMLS_CC);
73 }
74 /* }}} */
75
PHP_METHOD(errorObj,__get)76 PHP_METHOD(errorObj, __get)
77 {
78 char *property;
79 long property_len = 0;
80 zval *zobj = getThis();
81 /* php_error is in PHP7 defined in php.h, so we use php_errobj instead */
82 php_error_object *php_errobj;
83
84 PHP_MAPSCRIPT_ERROR_HANDLING(TRUE);
85 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
86 &property, &property_len) == FAILURE) {
87 PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
88 return;
89 }
90 PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
91
92 php_errobj = MAPSCRIPT_OBJ_P(php_error_object, zobj);
93
94 IF_GET_LONG("code", php_errobj->error->code)
95 else IF_GET_STRING("routine", php_errobj->error->routine)
96 else IF_GET_STRING("message", php_errobj->error->message)
97 else IF_GET_LONG("isreported", php_errobj->error->isreported)
98 else {
99 mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property);
100 }
101 }
102
PHP_METHOD(errorObj,__set)103 PHP_METHOD(errorObj, __set)
104 {
105 char *property;
106 long property_len = 0;
107 zval *value;
108 /* zval *zobj = getThis(); */
109 /* php_error_object *php_errobj; */
110
111 PHP_MAPSCRIPT_ERROR_HANDLING(TRUE);
112 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz",
113 &property, &property_len, &value) == FAILURE) {
114 PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
115 return;
116 }
117 PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
118
119 /* php_errobj = MAPSCRIPT_OBJ_P(php_error_object, zobj); */
120
121 if ( (STRING_EQUAL("code", property)) ||
122 (STRING_EQUAL("routine", property)) ||
123 (STRING_EQUAL("isreported", property)) ||
124 (STRING_EQUAL("message", property))) {
125 mapscript_throw_exception("Property '%s' is read-only and cannot be set." TSRMLS_CC, property);
126 } else {
127 mapscript_throw_exception("Property '%s' does not exist in this object." TSRMLS_CC, property);
128 }
129 }
130
131 /* {{{ proto int error.next()
132 Returns a ref to the next errorObj in the list, or NULL if we reached the last one */
PHP_METHOD(errorObj,next)133 PHP_METHOD(errorObj, next)
134 {
135 zval *zobj = getThis();
136 php_error_object *php_errobj;
137 errorObj *error = NULL;
138
139 PHP_MAPSCRIPT_ERROR_HANDLING(TRUE);
140 if (zend_parse_parameters_none() == FAILURE) {
141 PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
142 return;
143 }
144 PHP_MAPSCRIPT_RESTORE_ERRORS(TRUE);
145
146 php_errobj = MAPSCRIPT_OBJ_P(php_error_object, zobj);
147
148 if (php_errobj->error->next == NULL)
149 RETURN_NULL();
150
151 /* Make sure 'self' is still valid. It may have been deleted by
152 * msResetErrorList() */
153 error = msGetErrorObj();
154 while(error != php_errobj->error) {
155 if (error->next == NULL) {
156 mapscript_throw_exception("Trying to access an errorObj that has expired." TSRMLS_CC);
157 return;
158 }
159 error = error->next;
160 }
161
162 php_errobj->error = php_errobj->error->next;
163 *return_value = *zobj;
164 zval_copy_ctor(return_value);
165 INIT_PZVAL(return_value);
166 }
167 /* }}} */
168
169 zend_function_entry error_functions[] = {
170 PHP_ME(errorObj, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
171 PHP_ME(errorObj, __get, error___get_args, ZEND_ACC_PUBLIC)
172 PHP_ME(errorObj, __set, error___set_args, ZEND_ACC_PUBLIC)
173 PHP_ME(errorObj, next, NULL, ZEND_ACC_PUBLIC) {
174 NULL, NULL, NULL
175 }
176 };
177
mapscript_create_error(errorObj * error,zval * return_value TSRMLS_DC)178 void mapscript_create_error(errorObj *error, zval *return_value TSRMLS_DC)
179 {
180 php_error_object * php_errobj;
181 object_init_ex(return_value, mapscript_ce_error);
182 php_errobj = MAPSCRIPT_OBJ_P(php_error_object, return_value);
183 php_errobj->error = error;
184 }
185
186 #if PHP_VERSION_ID >= 70000
187 /* PHP7 - Modification by Bjoern Boldt <mapscript@pixaweb.net> */
mapscript_error_create_object(zend_class_entry * ce TSRMLS_DC)188 static zend_object *mapscript_error_create_object(zend_class_entry *ce TSRMLS_DC)
189 {
190 php_error_object *php_errobj;
191
192 php_errobj = ecalloc(1, sizeof(*php_errobj) + zend_object_properties_size(ce));
193
194 zend_object_std_init(&php_errobj->zobj, ce TSRMLS_CC);
195 object_properties_init(&php_errobj->zobj, ce);
196
197 php_errobj->zobj.handlers = &mapscript_error_object_handlers;
198
199 return &php_errobj->zobj;
200 }
201
202 /*
203 static void mapscript_error_free_object(zend_object *object)
204 {
205 php_error_object *php_errobj;
206
207 php_errobj = (php_error_object *)((char *)object - XtOffsetOf(php_error_object, zobj));
208
209 zend_object_std_dtor(object);
210 }
211 */
212
PHP_MINIT_FUNCTION(error)213 PHP_MINIT_FUNCTION(error)
214 {
215 zend_class_entry ce;
216
217 INIT_CLASS_ENTRY(ce, "errorObj", error_functions);
218 mapscript_ce_error = zend_register_internal_class(&ce TSRMLS_CC);
219
220 mapscript_ce_error->create_object = mapscript_error_create_object;
221 mapscript_ce_error->ce_flags |= ZEND_ACC_FINAL;
222
223 memcpy(&mapscript_error_object_handlers, &mapscript_std_object_handlers, sizeof(mapscript_error_object_handlers));
224 /* mapscript_error_object_handlers.free_obj = mapscript_error_free_object; // nothing to do here -> use standard handler */
225 mapscript_error_object_handlers.offset = XtOffsetOf(php_error_object, zobj);
226
227 return SUCCESS;
228 }
229 #else
230 /* PHP5 */
mapscript_error_object_destroy(void * object TSRMLS_DC)231 static void mapscript_error_object_destroy(void *object TSRMLS_DC)
232 {
233 php_error_object *php_errobj = (php_error_object *)object;
234
235 MAPSCRIPT_FREE_OBJECT(php_errobj);
236
237 /* We don't need to free the errorObj */
238
239 efree(object);
240 }
241
mapscript_error_object_new(zend_class_entry * ce TSRMLS_DC)242 static zend_object_value mapscript_error_object_new(zend_class_entry *ce TSRMLS_DC)
243 {
244 zend_object_value retval;
245 php_error_object *php_errobj;
246
247 MAPSCRIPT_ALLOC_OBJECT(php_errobj, php_error_object);
248
249 retval = mapscript_object_new(&php_errobj->std, ce,
250 &mapscript_error_object_destroy TSRMLS_CC);
251
252 return retval;
253 }
254
PHP_MINIT_FUNCTION(error)255 PHP_MINIT_FUNCTION(error)
256 {
257 zend_class_entry ce;
258
259 MAPSCRIPT_REGISTER_CLASS("errorObj",
260 error_functions,
261 mapscript_ce_error,
262 mapscript_error_object_new);
263
264 mapscript_ce_error->ce_flags |= ZEND_ACC_FINAL_CLASS;
265
266 return SUCCESS;
267 }
268 #endif
269