php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
php_xsl.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Christian Stocker <chregu@php.net> |
14 +----------------------------------------------------------------------+
15*/
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "php.h"
22#include "ext/standard/info.h"
23#include "php_xsl.h"
24#include "php_xsl_arginfo.h"
25
27static zend_object_handlers xsl_object_handlers;
28
29static const zend_module_dep xsl_deps[] = {
30 ZEND_MOD_REQUIRED("libxml")
33};
34
35/* {{{ xsl_module_entry */
49/* }}} */
50
51#ifdef COMPILE_DL_XSL
53#endif
54
55static HashTable *xsl_objects_get_gc(zend_object *object, zval **table, int *n)
56{
57 xsl_object *intern = php_xsl_fetch_object(object);
59}
60
62{
63 if (intern->ptr) {
64 xsltStylesheetPtr sheet = intern->ptr;
65
66 /* Free wrapper */
67 if (sheet->_private != NULL) {
68 sheet->_private = NULL;
69 }
70
71 xsltFreeStylesheet(sheet);
72 intern->ptr = NULL;
73 }
74}
75
76/* {{{ xsl_objects_free_storage */
78{
79 xsl_object *intern = php_xsl_fetch_object(object);
80
81 zend_object_std_dtor(&intern->std);
82
83 if (intern->parameter) {
86 }
87
89
90 xsl_free_sheet(intern);
91
92 if (intern->doc) {
93 php_libxml_decrement_doc_ref(intern->doc);
94 efree(intern->doc);
95 }
96
97 if (intern->sheet_ref_obj) {
98 php_libxml_decrement_doc_ref_directly(intern->sheet_ref_obj);
99 }
100
101 if (intern->profiling) {
102 zend_string_release(intern->profiling);
103 }
104}
105/* }}} */
106
107/* {{{ xsl_objects_new */
109{
110 xsl_object *intern;
111
112 intern = zend_object_alloc(sizeof(xsl_object), class_type);
114
115 zend_object_std_init(&intern->std, class_type);
116 object_properties_init(&intern->std, class_type);
117 intern->parameter = zend_new_array(0);
119
120 /* Default initialize properties that could not be default initialized at the stub because they depend on library
121 * configuration parameters. */
122 ZVAL_LONG(xsl_prop_max_template_depth(&intern->std), xsltMaxDepth);
123 ZVAL_LONG(xsl_prop_max_template_vars(&intern->std), xsltMaxVars);
124
125 return &intern->std;
126}
127/* }}} */
128
129#if ZEND_DEBUG
130# define XSL_DEFINE_PROP_ACCESSOR(c_name, php_name, prop_index) \
131 zval *xsl_prop_##c_name(zend_object *object) \
132 { \
133 zend_string *prop_name = ZSTR_INIT_LITERAL(php_name, false); \
134 const zend_property_info *prop_info = zend_get_property_info(xsl_xsltprocessor_class_entry, prop_name, 0); \
135 zend_string_release_ex(prop_name, false); \
136 ZEND_ASSERT(OBJ_PROP_TO_NUM(prop_info->offset) == (prop_index)); \
137 return OBJ_PROP_NUM(object, (prop_index)); \
138 }
139#else
140# define XSL_DEFINE_PROP_ACCESSOR(c_name, php_name, prop_index) \
141 zval *xsl_prop_##c_name(zend_object *object) \
142 { \
143 return OBJ_PROP_NUM(object, (prop_index)); \
144 }
145#endif
146
147XSL_DEFINE_PROP_ACCESSOR(max_template_depth, "maxTemplateDepth", 2)
148XSL_DEFINE_PROP_ACCESSOR(max_template_vars, "maxTemplateVars", 3)
149
150static zval *xsl_objects_write_property_with_validation(zend_object *object, zend_string *member, zval *value, void **cache_slot, zval *property)
151{
152 /* Read old value so we can restore it if necessary. The value is not refcounted as its type is IS_LONG. */
154 zend_long old_property_value = Z_LVAL_P(property);
155
156 /* Write new property, which will also potentially perform coercions. */
157 zend_std_write_property(object, member, value, NULL);
158
159 /* Validate value *after* coercions have been performed, and restore the old value if necessary. */
160 if (UNEXPECTED(Z_LVAL_P(property) < 0)) {
161 Z_LVAL_P(property) = old_property_value;
162 zend_value_error("%s::$%s must be greater than or equal to 0", ZSTR_VAL(object->ce->name), ZSTR_VAL(member));
163 return &EG(error_zval);
164 }
165
166 return property;
167}
168
169static zval *xsl_objects_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot)
170{
171 /* Extra validation for maxTemplateDepth and maxTemplateVars */
172 if (zend_string_equals_literal(member, "maxTemplateDepth")) {
173 zval *property = xsl_prop_max_template_depth(object);
174 return xsl_objects_write_property_with_validation(object, member, value, cache_slot, property);
175 } else if (zend_string_equals_literal(member, "maxTemplateVars")) {
176 zval *property = xsl_prop_max_template_vars(object);
177 return xsl_objects_write_property_with_validation(object, member, value, cache_slot, property);
178 } else {
179 return zend_std_write_property(object, member, value, cache_slot);
180 }
181}
182
183static bool xsl_is_validated_property(const zend_string *member)
184{
185 return zend_string_equals_literal(member, "maxTemplateDepth") || zend_string_equals_literal(member, "maxTemplateVars");
186}
187
188static zval *xsl_objects_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot)
189{
190 if (xsl_is_validated_property(member)) {
191 return NULL;
192 }
193
194 return zend_std_get_property_ptr_ptr(object, member, type, cache_slot);
195}
196
197static zval *xsl_objects_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv)
198{
199 /* read handler is being called as a fallback after get_property_ptr_ptr returned NULL */
200 if (type != BP_VAR_IS && type != BP_VAR_R && xsl_is_validated_property(member)) {
201 zend_throw_error(NULL, "Indirect modification of %s::$%s is not allowed", ZSTR_VAL(object->ce->name), ZSTR_VAL(member));
202 return &EG(uninitialized_zval);
203 }
204
205 return zend_std_read_property(object, member, type, cache_slot, rv);
206}
207
208static void xsl_objects_unset_property(zend_object *object, zend_string *member, void **cache_slot)
209{
210 if (xsl_is_validated_property(member)) {
211 zend_throw_error(NULL, "Cannot unset %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(member));
212 return;
213 }
214
215 zend_std_unset_property(object, member, cache_slot);
216}
217
218/* Tries to output an error message where a part was replaced by another string.
219 * Returns true if the search string was found and the error message with replacement was outputted.
220 * Return false otherwise. */
221static bool xsl_try_output_replaced_error_message(
222 void *ctx,
223 const char *msg,
224 const char *search,
225 size_t search_len,
226 const char *replace
227)
228{
229 const char *msg_replace_location = strstr(msg, search);
230 if (msg_replace_location != NULL) {
231 php_libxml_ctx_error(ctx, "%.*s%s%s", (int) (msg_replace_location - msg), msg, replace, msg_replace_location + search_len);
232 return true;
233 }
234 return false;
235}
236
237/* Helper macro so the string length doesn't need to be passed separately.
238 * Only allows literal strings for `search` and `replace`. */
239#define XSL_TRY_OUTPUT_REPLACED_ERROR_MESSAGE(ctx, msg, search, replace) \
240 xsl_try_output_replaced_error_message(ctx, msg, "" search, sizeof("" search) - 1, "" replace)
241
242/* We want to output PHP-tailored error messages for some libxslt error messages, such that
243 * the errors refer to PHP properties instead of libxslt-specific fields. */
244static void xsl_libxslt_error_handler(void *ctx, const char *msg, ...)
245{
246 va_list args;
247 va_start(args, msg);
248
249 if (strcmp(msg, "%s") == 0) {
250 /* Adjust error message to be more descriptive */
251 const char *msg_arg = va_arg(args, const char *);
252 bool output = XSL_TRY_OUTPUT_REPLACED_ERROR_MESSAGE(ctx, msg_arg, "xsltMaxDepth (--maxdepth)", "$maxTemplateDepth")
253 || XSL_TRY_OUTPUT_REPLACED_ERROR_MESSAGE(ctx, msg_arg, "maxTemplateVars (--maxvars)", "$maxTemplateVars");
254
255 if (!output) {
256 php_libxml_ctx_error(ctx, "%s", msg_arg);
257 }
258 } else {
259 php_libxml_error_handler_va(PHP_LIBXML_ERROR, ctx, msg, args);
260 }
261
262 va_end(args);
263}
264
265/* {{{ PHP_MINIT_FUNCTION */
267{
268 memcpy(&xsl_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
269 xsl_object_handlers.offset = XtOffsetOf(xsl_object, std);
270 xsl_object_handlers.clone_obj = NULL;
271 xsl_object_handlers.free_obj = xsl_objects_free_storage;
272 xsl_object_handlers.get_gc = xsl_objects_get_gc;
273 xsl_object_handlers.write_property = xsl_objects_write_property;
274 xsl_object_handlers.get_property_ptr_ptr = xsl_objects_get_property_ptr_ptr;
275 xsl_object_handlers.read_property = xsl_objects_read_property;
276 xsl_object_handlers.unset_property = xsl_objects_unset_property;
277
278 xsl_xsltprocessor_class_entry = register_class_XSLTProcessor();
280 xsl_xsltprocessor_class_entry->default_object_handlers = &xsl_object_handlers;
281
282#ifdef HAVE_XSL_EXSLT
283 exsltRegisterAll();
284#endif
285
286 xsltRegisterExtModuleFunction ((const xmlChar *) "functionString",
287 (const xmlChar *) "http://php.net/xsl",
289 xsltRegisterExtModuleFunction ((const xmlChar *) "function",
290 (const xmlChar *) "http://php.net/xsl",
292 xsltSetGenericErrorFunc(NULL, xsl_libxslt_error_handler);
293
294 register_php_xsl_symbols(module_number);
295
296 return SUCCESS;
297}
298/* }}} */
299
300/* {{{ xsl_object_set_data */
301static void xsl_object_set_data(void *obj, zval *wrapper)
302{
303 ((xsltStylesheetPtr) obj)->_private = wrapper;
304}
305/* }}} */
306
307/* {{{ php_xsl_set_object */
308void php_xsl_set_object(zval *wrapper, void *obj)
309{
311
312 object = Z_XSL_P(wrapper);
313 object->ptr = obj;
314 xsl_object_set_data(obj, wrapper);
315}
316/* }}} */
317
318/* {{{ PHP_MSHUTDOWN_FUNCTION */
320{
321 xsltUnregisterExtModuleFunction ((const xmlChar *) "functionString",
322 (const xmlChar *) "http://php.net/xsl");
323 xsltUnregisterExtModuleFunction ((const xmlChar *) "function",
324 (const xmlChar *) "http://php.net/xsl");
325 xsltSetGenericErrorFunc(NULL, NULL);
326 xsltCleanupGlobals();
327
328 return SUCCESS;
329}
330/* }}} */
331
332/* {{{ PHP_MINFO_FUNCTION */
334{
336 {
337 char buffer[128];
338 int major, minor, subminor;
339
340 php_info_print_table_row(2, "XSL", "enabled");
341 major = xsltLibxsltVersion/10000;
342 minor = (xsltLibxsltVersion - major * 10000) / 100;
343 subminor = (xsltLibxsltVersion - major * 10000 - minor * 100);
344 snprintf(buffer, 128, "%d.%d.%d", major, minor, subminor);
345 php_info_print_table_row(2, "libxslt Version", buffer);
346 major = xsltLibxmlVersion/10000;
347 minor = (xsltLibxmlVersion - major * 10000) / 100;
348 subminor = (xsltLibxmlVersion - major * 10000 - minor * 100);
349 snprintf(buffer, 128, "%d.%d.%d", major, minor, subminor);
350 php_info_print_table_row(2, "libxslt compiled against libxml Version", buffer);
351 }
352#ifdef HAVE_XSL_EXSLT
353 php_info_print_table_row(2, "EXSLT", "enabled");
355#endif
357}
358/* }}} */
strstr(string $haystack, string $needle, bool $before_needle=false)
zend_ffi_type * type
Definition ffi.c:3812
zend_long n
Definition ffi.c:4979
memcpy(ptr1, ptr2, size)
#define minor(dev)
Definition fsmagic.c:66
#define major(dev)
Definition fsmagic.c:65
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MSHUTDOWN
Definition php.h:393
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_MINIT
Definition php.h:392
#define XSL_DEFINE_PROP_ACCESSOR(c_name, php_name, prop_index)
Definition php_xsl.c:140
zend_object * xsl_objects_new(zend_class_entry *class_type)
Definition php_xsl.c:108
void xsl_objects_free_storage(zend_object *object)
Definition php_xsl.c:77
zend_class_entry * xsl_xsltprocessor_class_entry
Definition php_xsl.c:26
void xsl_free_sheet(xsl_object *intern)
Definition php_xsl.c:61
#define XSL_TRY_OUTPUT_REPLACED_ERROR_MESSAGE(ctx, msg, search, replace)
Definition php_xsl.c:239
void php_xsl_set_object(zval *wrapper, void *obj)
Definition php_xsl.c:308
zend_module_entry xsl_module_entry
Definition php_xsl.c:36
#define Z_XSL_P(zv)
Definition php_xsl.h:71
zval * xsl_prop_max_template_vars(zend_object *object)
void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs)
#define XSL_SECPREF_DEFAULT
Definition php_xsl.h:53
#define PHP_XSL_VERSION
Definition php_xsl.h:24
zval * xsl_prop_max_template_depth(zend_object *object)
void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs)
const LIBEXSLT_DOTTED_VERSION
char * msg
Definition phpdbg.h:289
zval rv
Definition session.c:1024
Definition file.h:177
HashTable * parameter
Definition php_xsl.h:57
php_libxml_node_object * doc
Definition php_xsl.h:62
zend_object std
Definition php_xsl.h:64
zend_string * profiling
Definition php_xsl.h:63
php_libxml_ref_obj * sheet_ref_obj
Definition php_xsl.h:59
php_dom_xpath_callbacks xpath_callbacks
Definition php_xsl.h:61
void * ptr
Definition php_xsl.h:56
zend_long securityPrefs
Definition php_xsl.h:60
PHP_DOM_EXPORT void php_dom_xpath_callbacks_dtor(php_dom_xpath_callbacks *registry)
PHP_DOM_EXPORT void php_dom_xpath_callbacks_ctor(php_dom_xpath_callbacks *registry)
PHP_DOM_EXPORT HashTable * php_dom_xpath_callbacks_get_gc_for_whole_object(php_dom_xpath_callbacks *registry, zend_object *object, zval **table, int *n)
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
Definition zend.c:1849
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define efree(ptr)
Definition zend_alloc.h:155
#define FREE_HASHTABLE(ht)
Definition zend_alloc.h:234
struct _zval_struct zval
strcmp(string $string1, string $string2)
zval * args
#define BP_VAR_R
#define BP_VAR_IS
#define snprintf
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
#define zend_new_array(size)
Definition zend_hash.h:338
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define ZEND_MOD_END
struct _zend_module_dep zend_module_dep
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES
#define ZEND_MOD_REQUIRED(name)
#define STANDARD_MODULE_HEADER_EX
ZEND_API zval * zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API zval * zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot)
ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void **cache_slot)
ZEND_API zval * zend_std_read_property(zend_object *zobj, zend_string *name, int type, void **cache_slot, zval *rv)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define zend_string_equals_literal(str, literal)
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define ZVAL_LONG(z, l)
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_LONG
Definition zend_types.h:604
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
object
value
property