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 | Authors: Christian Stocker <chregu@php.net> |
14 | Rob Richards <rrichards@php.net> |
15 +----------------------------------------------------------------------+
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "php.h"
23 #include "php_xsl.h"
24 #include <libxslt/variables.h>
25 #include "ext/libxml/php_libxml.h"
26
27
php_xsl_xslt_apply_params(xsltTransformContextPtr ctxt,HashTable * params)28 static zend_result php_xsl_xslt_apply_params(xsltTransformContextPtr ctxt, HashTable *params)
29 {
30 zend_string *string_key;
31 zval *value;
32
33 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(params, string_key, value) {
34 ZEND_ASSERT(string_key != NULL);
35 /* Already a string because of setParameter() */
36 ZEND_ASSERT(Z_TYPE_P(value) == IS_STRING);
37
38 int result = xsltQuoteOneUserParam(ctxt, (const xmlChar *) ZSTR_VAL(string_key), (const xmlChar *) Z_STRVAL_P(value));
39 if (result < 0) {
40 php_error_docref(NULL, E_WARNING, "Could not apply parameter \"%s\"", ZSTR_VAL(string_key));
41 return FAILURE;
42 }
43 } ZEND_HASH_FOREACH_END();
44
45 return SUCCESS;
46 }
47
xsl_proxy_factory(xmlNodePtr node,zval * child,dom_object * intern,xmlXPathParserContextPtr ctxt)48 static void xsl_proxy_factory(xmlNodePtr node, zval *child, dom_object *intern, xmlXPathParserContextPtr ctxt)
49 {
50 ZEND_ASSERT(node->type != XML_NAMESPACE_DECL);
51
52 /**
53 * Upon freeing libxslt's context, every document that is not the *main* document will be freed by libxslt.
54 * If a node of a document that is *not the main* document gets returned to userland, we'd free the node twice:
55 * first by the cleanup of the xslt context, and then by our own refcounting mechanism.
56 * To prevent this, we'll take a copy if the node is not from the main document.
57 * It is important that we do not copy the node unconditionally, because that means that:
58 * - modifications to the node will only modify the copy, and not the original
59 * - accesses to the parent, path, ... will not work
60 */
61 xsltTransformContextPtr transform_ctxt = (xsltTransformContextPtr) ctxt->context->extra;
62 if (node->doc != transform_ctxt->document->doc) {
63 node = xmlDocCopyNode(node, intern->document->ptr, 1);
64 }
65 php_dom_create_object(node, child, intern);
66 }
67
xsl_ext_fetch_intern(xmlXPathParserContextPtr ctxt)68 static xsl_object *xsl_ext_fetch_intern(xmlXPathParserContextPtr ctxt)
69 {
70 if (UNEXPECTED(!zend_is_executing())) {
71 xsltGenericError(xsltGenericErrorContext,
72 "xsltExtFunctionTest: Function called from outside of PHP\n");
73 return NULL;
74 }
75
76 xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
77 if (UNEXPECTED(tctxt == NULL)) {
78 xsltGenericError(xsltGenericErrorContext,
79 "xsltExtFunctionTest: failed to get the transformation context\n");
80 return NULL;
81 }
82
83 xsl_object *intern = (xsl_object *) tctxt->_private;
84 if (UNEXPECTED(intern == NULL)) {
85 xsltGenericError(xsltGenericErrorContext,
86 "xsltExtFunctionTest: failed to get the internal object\n");
87 return NULL;
88 }
89 return intern;
90 }
91
xsl_ext_function_php(xmlXPathParserContextPtr ctxt,int nargs,php_dom_xpath_nodeset_evaluation_mode evaluation_mode)92 static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, php_dom_xpath_nodeset_evaluation_mode evaluation_mode) /* {{{ */
93 {
94 xsl_object *intern = xsl_ext_fetch_intern(ctxt);
95 if (!intern) {
96 php_dom_xpath_callbacks_clean_argument_stack(ctxt, nargs);
97 } else {
98 php_dom_xpath_callbacks_call_php_ns(&intern->xpath_callbacks, ctxt, nargs, evaluation_mode, (dom_object *) intern->doc, xsl_proxy_factory);
99 }
100 }
101 /* }}} */
102
xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt,int nargs)103 void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
104 {
105 xsl_ext_function_php(ctxt, nargs, PHP_DOM_XPATH_EVALUATE_NODESET_TO_STRING);
106 }
107 /* }}} */
108
xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt,int nargs)109 void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
110 {
111 xsl_ext_function_php(ctxt, nargs, PHP_DOM_XPATH_EVALUATE_NODESET_TO_NODESET);
112 }
113 /* }}} */
114
xsl_ext_function_trampoline(xmlXPathParserContextPtr ctxt,int nargs)115 static void xsl_ext_function_trampoline(xmlXPathParserContextPtr ctxt, int nargs)
116 {
117 xsl_object *intern = xsl_ext_fetch_intern(ctxt);
118 if (!intern) {
119 php_dom_xpath_callbacks_clean_argument_stack(ctxt, nargs);
120 } else {
121 php_dom_xpath_callbacks_call_custom_ns(&intern->xpath_callbacks, ctxt, nargs, PHP_DOM_XPATH_EVALUATE_NODESET_TO_NODESET, (dom_object *) intern->doc, xsl_proxy_factory);
122 }
123 }
124
125 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
126 Since:
127 */
PHP_METHOD(XSLTProcessor,importStylesheet)128 PHP_METHOD(XSLTProcessor, importStylesheet)
129 {
130 zval *id, *docp = NULL;
131 xmlDoc *doc = NULL, *newdoc = NULL;
132 xsltStylesheetPtr sheetp, oldsheetp;
133 xsl_object *intern;
134 int clone_docu = 0;
135 xmlNode *nodep = NULL;
136 zval *cloneDocu, rv;
137 zend_string *member;
138
139 id = ZEND_THIS;
140 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &docp) == FAILURE) {
141 RETURN_THROWS();
142 }
143
144 nodep = php_libxml_import_node(docp);
145
146 if (nodep) {
147 doc = nodep->doc;
148 }
149 if (doc == NULL) {
150 zend_argument_type_error(1, "must be a valid XML node");
151 RETURN_THROWS();
152 }
153
154 /* libxslt uses _private, so we must copy the imported
155 stylesheet document otherwise the node proxies will be a mess */
156 newdoc = xmlCopyDoc(doc, 1);
157 xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
158 PHP_LIBXML_SANITIZE_GLOBALS(parse);
159 ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations")
160 xmlSubstituteEntitiesDefault(1);
161 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
162 ZEND_DIAGNOSTIC_IGNORED_END
163
164 sheetp = xsltParseStylesheetDoc(newdoc);
165 PHP_LIBXML_RESTORE_GLOBALS(parse);
166
167 if (!sheetp) {
168 xmlFreeDoc(newdoc);
169 RETURN_FALSE;
170 }
171
172 intern = Z_XSL_P(id);
173
174 member = ZSTR_INIT_LITERAL("cloneDocument", 0);
175 cloneDocu = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_R, NULL, &rv);
176 clone_docu = zend_is_true(cloneDocu);
177 zend_string_release_ex(member, 0);
178 if (clone_docu == 0) {
179 /* check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation */
180 nodep = xmlDocGetRootElement(sheetp->doc);
181 if (nodep && (nodep = nodep->children)) {
182 while (nodep) {
183 if (nodep->type == XML_ELEMENT_NODE && xmlStrEqual(nodep->name, (const xmlChar *) "key") && xmlStrEqual(nodep->ns->href, XSLT_NAMESPACE)) {
184 intern->hasKeys = true;
185 break;
186 }
187 nodep = nodep->next;
188 }
189 }
190 } else {
191 intern->hasKeys = true;
192 }
193
194 if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) {
195 /* free wrapper */
196 if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) {
197 ((xsltStylesheetPtr) intern->ptr)->_private = NULL;
198 }
199 xsltFreeStylesheet((xsltStylesheetPtr) intern->ptr);
200 intern->ptr = NULL;
201 }
202
203 php_xsl_set_object(id, sheetp);
204 RETVAL_TRUE;
205 }
206 /* }}} end XSLTProcessor::importStylesheet */
207
php_xsl_delayed_lib_registration(void * ctxt,const zend_string * ns,const zend_string * name)208 static void php_xsl_delayed_lib_registration(void *ctxt, const zend_string *ns, const zend_string *name)
209 {
210 xsltTransformContextPtr xsl = (xsltTransformContextPtr) ctxt;
211 xsltRegisterExtFunction(xsl, (const xmlChar *) ZSTR_VAL(name), (const xmlChar *) ZSTR_VAL(ns), xsl_ext_function_trampoline);
212 }
213
php_xsl_apply_stylesheet(zval * id,xsl_object * intern,xsltStylesheetPtr style,zval * docp)214 static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStylesheetPtr style, zval *docp) /* {{{ */
215 {
216 xmlDocPtr newdocp = NULL;
217 xmlDocPtr doc = NULL;
218 xmlNodePtr node = NULL;
219 xsltTransformContextPtr ctxt;
220 php_libxml_node_object *object;
221 zval *doXInclude, rv;
222 zend_string *member;
223 FILE *f;
224 int secPrefsError = 0;
225 int secPrefsValue;
226 xsltSecurityPrefsPtr secPrefs = NULL;
227
228 node = php_libxml_import_node(docp);
229
230 if (node) {
231 doc = node->doc;
232 }
233
234 if (doc == NULL) {
235 zend_argument_type_error(1, "must be a valid XML node");
236 return NULL;
237 }
238
239 if (style == NULL) {
240 zend_string *name = get_active_function_or_method_name();
241 zend_throw_error(NULL, "%s() can only be called after a stylesheet has been imported",
242 ZSTR_VAL(name));
243 zend_string_release(name);
244 return NULL;
245 }
246
247 if (intern->profiling) {
248 if (php_check_open_basedir(intern->profiling)) {
249 f = NULL;
250 } else {
251 f = VCWD_FOPEN(intern->profiling, "w");
252 }
253 } else {
254 f = NULL;
255 }
256
257 intern->doc = emalloc(sizeof(php_libxml_node_object));
258 memset(intern->doc, 0, sizeof(php_libxml_node_object));
259
260 if (intern->hasKeys) {
261 doc = xmlCopyDoc(doc, 1);
262 } else {
263 object = Z_LIBXML_NODE_P(docp);
264 intern->doc->document = object->document;
265 }
266
267 php_libxml_increment_doc_ref(intern->doc, doc);
268
269 ctxt = xsltNewTransformContext(style, doc);
270 ctxt->_private = (void *) intern;
271
272 if (intern->parameter) {
273 zend_result status = php_xsl_xslt_apply_params(ctxt, intern->parameter);
274 if (UNEXPECTED(status != SUCCESS) && EG(exception)) {
275 goto out;
276 }
277 }
278
279 member = ZSTR_INIT_LITERAL("doXInclude", 0);
280 doXInclude = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_R, NULL, &rv);
281 ctxt->xinclude = zend_is_true(doXInclude);
282 zend_string_release_ex(member, 0);
283
284 secPrefsValue = intern->securityPrefs;
285
286 /* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */
287 if (secPrefsValue != XSL_SECPREF_NONE) {
288 secPrefs = xsltNewSecurityPrefs();
289 if (secPrefsValue & XSL_SECPREF_READ_FILE ) {
290 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) {
291 secPrefsError = 1;
292 }
293 }
294 if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) {
295 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) {
296 secPrefsError = 1;
297 }
298 }
299 if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) {
300 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) {
301 secPrefsError = 1;
302 }
303 }
304 if (secPrefsValue & XSL_SECPREF_READ_NETWORK) {
305 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) {
306 secPrefsError = 1;
307 }
308 }
309 if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) {
310 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) {
311 secPrefsError = 1;
312 }
313 }
314
315 if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) {
316 secPrefsError = 1;
317 }
318 }
319
320 php_dom_xpath_callbacks_delayed_lib_registration(&intern->xpath_callbacks, ctxt, php_xsl_delayed_lib_registration);
321
322 if (secPrefsError == 1) {
323 php_error_docref(NULL, E_WARNING, "Can't set libxslt security properties, not doing transformation for security reasons");
324 } else {
325 newdocp = xsltApplyStylesheetUser(style, doc, /* params (handled manually) */ NULL, /* output */ NULL, f, ctxt);
326 }
327
328 out:
329 if (f) {
330 fclose(f);
331 }
332
333 xsltFreeTransformContext(ctxt);
334 if (secPrefs) {
335 xsltFreeSecurityPrefs(secPrefs);
336 }
337
338 php_dom_xpath_callbacks_clean_node_list(&intern->xpath_callbacks);
339
340 php_libxml_decrement_doc_ref(intern->doc);
341 efree(intern->doc);
342 intern->doc = NULL;
343
344 return newdocp;
345
346 }
347 /* }}} */
348
349 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
350 Since:
351 */
PHP_METHOD(XSLTProcessor,transformToDoc)352 PHP_METHOD(XSLTProcessor, transformToDoc)
353 {
354 zval *id, *docp = NULL;
355 xmlDoc *newdocp;
356 xsltStylesheetPtr sheetp;
357 zend_class_entry *ret_class = NULL;
358 xsl_object *intern;
359
360 id = ZEND_THIS;
361 intern = Z_XSL_P(id);
362 sheetp = (xsltStylesheetPtr) intern->ptr;
363
364 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|C!", &docp, &ret_class) == FAILURE) {
365 RETURN_THROWS();
366 }
367
368 newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp);
369
370 if (newdocp) {
371 if (ret_class) {
372 zend_string *curclass_name;
373 zend_class_entry *curce;
374 php_libxml_node_object *interndoc;
375
376 curce = Z_OBJCE_P(docp);
377 curclass_name = curce->name;
378 while (curce->parent != NULL) {
379 curce = curce->parent;
380 }
381
382 if (!instanceof_function(ret_class, curce)) {
383 xmlFreeDoc(newdocp);
384 zend_argument_type_error(2, "must be a class name compatible with %s, %s given",
385 ZSTR_VAL(curclass_name), ZSTR_VAL(ret_class->name)
386 );
387 RETURN_THROWS();
388 }
389
390 object_init_ex(return_value, ret_class);
391
392 interndoc = Z_LIBXML_NODE_P(return_value);
393 php_libxml_increment_doc_ref(interndoc, newdocp);
394 php_libxml_increment_node_ptr(interndoc, (xmlNodePtr)newdocp, (void *)interndoc);
395 } else {
396 php_dom_create_object((xmlNodePtr) newdocp, return_value, NULL);
397 }
398 } else {
399 RETURN_FALSE;
400 }
401 }
402 /* }}} end XSLTProcessor::transformToDoc */
403
404 /* {{{ */
PHP_METHOD(XSLTProcessor,transformToUri)405 PHP_METHOD(XSLTProcessor, transformToUri)
406 {
407 zval *id, *docp = NULL;
408 xmlDoc *newdocp;
409 xsltStylesheetPtr sheetp;
410 int ret;
411 size_t uri_len;
412 char *uri;
413 xsl_object *intern;
414
415 id = ZEND_THIS;
416 intern = Z_XSL_P(id);
417 sheetp = (xsltStylesheetPtr) intern->ptr;
418
419 if (zend_parse_parameters(ZEND_NUM_ARGS(), "op", &docp, &uri, &uri_len) == FAILURE) {
420 RETURN_THROWS();
421 }
422
423 newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp);
424
425 ret = -1;
426 if (newdocp) {
427 ret = xsltSaveResultToFilename(uri, newdocp, sheetp, 0);
428 xmlFreeDoc(newdocp);
429 }
430
431 RETVAL_LONG(ret);
432 }
433 /* }}} end XSLTProcessor::transformToUri */
434
435 /* {{{ */
PHP_METHOD(XSLTProcessor,transformToXml)436 PHP_METHOD(XSLTProcessor, transformToXml)
437 {
438 zval *id, *docp = NULL;
439 xmlDoc *newdocp;
440 xsltStylesheetPtr sheetp;
441 int ret;
442 xmlChar *doc_txt_ptr;
443 int doc_txt_len;
444 xsl_object *intern;
445
446 id = ZEND_THIS;
447 intern = Z_XSL_P(id);
448 sheetp = (xsltStylesheetPtr) intern->ptr;
449
450 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &docp) == FAILURE) {
451 RETURN_THROWS();
452 }
453
454 newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp);
455
456 ret = -1;
457 if (newdocp) {
458 ret = xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, newdocp, sheetp);
459 if (doc_txt_ptr && doc_txt_len) {
460 RETVAL_STRINGL((char *) doc_txt_ptr, doc_txt_len);
461 xmlFree(doc_txt_ptr);
462 }
463 xmlFreeDoc(newdocp);
464 }
465
466 if (ret < 0) {
467 RETURN_FALSE;
468 }
469 }
470 /* }}} end XSLTProcessor::transformToXml */
471
472 /* {{{ */
PHP_METHOD(XSLTProcessor,setParameter)473 PHP_METHOD(XSLTProcessor, setParameter)
474 {
475
476 zval *id = ZEND_THIS;
477 zval *entry, new_string;
478 HashTable *array_value;
479 xsl_object *intern;
480 char *namespace;
481 size_t namespace_len;
482 zend_string *string_key, *name, *value = NULL;
483
484 ZEND_PARSE_PARAMETERS_START(2, 3)
485 Z_PARAM_STRING(namespace, namespace_len)
486 Z_PARAM_ARRAY_HT_OR_STR(array_value, name)
487 Z_PARAM_OPTIONAL
488 Z_PARAM_PATH_STR_OR_NULL(value)
489 ZEND_PARSE_PARAMETERS_END();
490
491 intern = Z_XSL_P(id);
492
493 if (array_value) {
494 if (value) {
495 zend_argument_value_error(3, "must be null when argument #2 ($name) is an array");
496 RETURN_THROWS();
497 }
498
499 ZEND_HASH_FOREACH_STR_KEY_VAL(array_value, string_key, entry) {
500 zval tmp;
501 zend_string *str;
502
503 if (string_key == NULL) {
504 zend_argument_type_error(2, "must contain only string keys");
505 RETURN_THROWS();
506 }
507
508 if (UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(string_key), ZSTR_LEN(string_key)))) {
509 zend_argument_value_error(3, "must not contain keys with any null bytes");
510 RETURN_THROWS();
511 }
512
513 str = zval_try_get_string(entry);
514 if (UNEXPECTED(!str)) {
515 RETURN_THROWS();
516 }
517
518 if (UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(str), ZSTR_LEN(str)))) {
519 zend_string_release(str);
520 zend_argument_value_error(3, "must not contain values with any null bytes");
521 RETURN_THROWS();
522 }
523
524 ZVAL_STR(&tmp, str);
525 zend_hash_update(intern->parameter, string_key, &tmp);
526 } ZEND_HASH_FOREACH_END();
527 RETURN_TRUE;
528 } else {
529 if (!value) {
530 zend_argument_value_error(3, "cannot be null when argument #2 ($name) is a string");
531 RETURN_THROWS();
532 }
533
534 if (UNEXPECTED(CHECK_NULL_PATH(ZSTR_VAL(name), ZSTR_LEN(name)))) {
535 zend_argument_value_error(2, "must not contain any null bytes");
536 RETURN_THROWS();
537 }
538
539 ZVAL_STR_COPY(&new_string, value);
540
541 zend_hash_update(intern->parameter, name, &new_string);
542 RETURN_TRUE;
543 }
544 }
545 /* }}} end XSLTProcessor::setParameter */
546
547 /* {{{ */
PHP_METHOD(XSLTProcessor,getParameter)548 PHP_METHOD(XSLTProcessor, getParameter)
549 {
550 zval *id = ZEND_THIS;
551 char *namespace;
552 size_t namespace_len = 0;
553 zval *value;
554 zend_string *name;
555 xsl_object *intern;
556
557 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS", &namespace, &namespace_len, &name) == FAILURE) {
558 RETURN_THROWS();
559 }
560 intern = Z_XSL_P(id);
561 if ((value = zend_hash_find(intern->parameter, name)) != NULL) {
562 RETURN_STR_COPY(Z_STR_P(value));
563 } else {
564 RETURN_FALSE;
565 }
566 }
567 /* }}} end XSLTProcessor::getParameter */
568
569 /* {{{ */
PHP_METHOD(XSLTProcessor,removeParameter)570 PHP_METHOD(XSLTProcessor, removeParameter)
571 {
572 zval *id = ZEND_THIS;
573 size_t namespace_len = 0;
574 char *namespace;
575 zend_string *name;
576 xsl_object *intern;
577
578 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS", &namespace, &namespace_len, &name) == FAILURE) {
579 RETURN_THROWS();
580 }
581 intern = Z_XSL_P(id);
582 if (zend_hash_del(intern->parameter, name) == SUCCESS) {
583 RETURN_TRUE;
584 } else {
585 RETURN_FALSE;
586 }
587 }
588 /* }}} end XSLTProcessor::removeParameter */
589
590 /* {{{ */
PHP_METHOD(XSLTProcessor,registerPHPFunctions)591 PHP_METHOD(XSLTProcessor, registerPHPFunctions)
592 {
593 xsl_object *intern = Z_XSL_P(ZEND_THIS);
594
595 zend_string *name = NULL;
596 HashTable *callable_ht = NULL;
597
598 ZEND_PARSE_PARAMETERS_START(0, 1)
599 Z_PARAM_OPTIONAL
600 Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(callable_ht, name)
601 ZEND_PARSE_PARAMETERS_END();
602
603 php_dom_xpath_callbacks_update_method_handler(
604 &intern->xpath_callbacks,
605 NULL,
606 NULL,
607 name,
608 callable_ht,
609 PHP_DOM_XPATH_CALLBACK_NAME_VALIDATE_NULLS,
610 NULL
611 );
612 }
613 /* }}} end XSLTProcessor::registerPHPFunctions(); */
614
PHP_METHOD(XSLTProcessor,registerPHPFunctionNS)615 PHP_METHOD(XSLTProcessor, registerPHPFunctionNS)
616 {
617 xsl_object *intern = Z_XSL_P(ZEND_THIS);
618
619 zend_string *namespace, *name;
620 zend_fcall_info fci;
621 zend_fcall_info_cache fcc;
622
623 ZEND_PARSE_PARAMETERS_START(3, 3)
624 Z_PARAM_PATH_STR(namespace)
625 Z_PARAM_PATH_STR(name)
626 Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc)
627 ZEND_PARSE_PARAMETERS_END();
628
629 if (zend_string_equals_literal(namespace, "http://php.net/xsl")) {
630 zend_argument_value_error(1, "must not be \"http://php.net/xsl\" because it is reserved by PHP");
631 RETURN_THROWS();
632 }
633
634 php_dom_xpath_callbacks_update_single_method_handler(
635 &intern->xpath_callbacks,
636 NULL,
637 namespace,
638 name,
639 &fcc,
640 PHP_DOM_XPATH_CALLBACK_NAME_VALIDATE_NCNAME,
641 NULL
642 );
643 }
644
645 /* {{{ */
PHP_METHOD(XSLTProcessor,setProfiling)646 PHP_METHOD(XSLTProcessor, setProfiling)
647 {
648 zval *id = ZEND_THIS;
649 xsl_object *intern;
650 char *filename = NULL;
651 size_t filename_len;
652
653 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &filename, &filename_len) == FAILURE) {
654 RETURN_THROWS();
655 }
656
657 intern = Z_XSL_P(id);
658 if (intern->profiling) {
659 efree(intern->profiling);
660 }
661 if (filename != NULL) {
662 intern->profiling = estrndup(filename, filename_len);
663 } else {
664 intern->profiling = NULL;
665 }
666
667 RETURN_TRUE;
668 }
669 /* }}} end XSLTProcessor::setProfiling */
670
671 /* {{{ */
PHP_METHOD(XSLTProcessor,setSecurityPrefs)672 PHP_METHOD(XSLTProcessor, setSecurityPrefs)
673 {
674 zval *id = ZEND_THIS;
675 xsl_object *intern;
676 zend_long securityPrefs, oldSecurityPrefs;
677
678 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &securityPrefs) == FAILURE) {
679 RETURN_THROWS();
680 }
681 intern = Z_XSL_P(id);
682 oldSecurityPrefs = intern->securityPrefs;
683 intern->securityPrefs = securityPrefs;
684 RETURN_LONG(oldSecurityPrefs);
685 }
686 /* }}} end XSLTProcessor::setSecurityPrefs */
687
688 /* {{{ */
PHP_METHOD(XSLTProcessor,getSecurityPrefs)689 PHP_METHOD(XSLTProcessor, getSecurityPrefs)
690 {
691 zval *id = ZEND_THIS;
692 xsl_object *intern;
693
694 if (zend_parse_parameters_none() == FAILURE) {
695 RETURN_THROWS();
696 }
697
698 intern = Z_XSL_P(id);
699
700 RETURN_LONG(intern->securityPrefs);
701 }
702 /* }}} end XSLTProcessor::getSecurityPrefs */
703
704 /* {{{ */
PHP_METHOD(XSLTProcessor,hasExsltSupport)705 PHP_METHOD(XSLTProcessor, hasExsltSupport)
706 {
707 if (zend_parse_parameters_none() == FAILURE) {
708 RETURN_THROWS();
709 }
710
711 #ifdef HAVE_XSL_EXSLT
712 RETURN_TRUE;
713 #else
714 RETURN_FALSE;
715 #endif
716 }
717 /* }}} end XSLTProcessor::hasExsltSupport(); */
718