1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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: Christian Stocker <chregu@php.net> |
16 | Rob Richards <rrichards@php.net> |
17 +----------------------------------------------------------------------+
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "php.h"
25 #include "php_xsl.h"
26 #include "ext/libxml/php_libxml.h"
27
28 /* {{{ arginfo */
29 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_import_stylesheet, 0, 0, 1)
30 ZEND_ARG_INFO(0, doc)
31 ZEND_END_ARG_INFO();
32
33 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_doc, 0, 0, 1)
34 ZEND_ARG_INFO(0, doc)
35 ZEND_END_ARG_INFO();
36
37 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_uri, 0, 0, 2)
38 ZEND_ARG_INFO(0, doc)
39 ZEND_ARG_INFO(0, uri)
40 ZEND_END_ARG_INFO();
41
42 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_transform_to_xml, 0, 0, 1)
43 ZEND_ARG_INFO(0, doc)
44 ZEND_END_ARG_INFO();
45
46 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_parameter, 0, 0, 2)
47 ZEND_ARG_INFO(0, namespace)
48 ZEND_ARG_INFO(0, name)
49 ZEND_ARG_INFO(0, value)
50 ZEND_END_ARG_INFO();
51
52 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_get_parameter, 0, 0, 2)
53 ZEND_ARG_INFO(0, namespace)
54 ZEND_ARG_INFO(0, name)
55 ZEND_END_ARG_INFO();
56
57 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_remove_parameter, 0, 0, 2)
58 ZEND_ARG_INFO(0, namespace)
59 ZEND_ARG_INFO(0, name)
60 ZEND_END_ARG_INFO();
61
62 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_has_exslt_support, 0, 0, 0)
63 ZEND_END_ARG_INFO();
64
65 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_register_php_functions, 0, 0, 0)
66 ZEND_ARG_INFO(0, restrict)
67 ZEND_END_ARG_INFO();
68
69 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_profiling, 0, 0, 1)
70 ZEND_ARG_INFO(0, filename)
71 ZEND_END_ARG_INFO();
72
73 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_set_security_prefs, 0, 0, 1)
74 ZEND_ARG_INFO(0, securityPrefs)
75 ZEND_END_ARG_INFO();
76
77 ZEND_BEGIN_ARG_INFO_EX(arginfo_xsl_xsltprocessor_get_security_prefs, 0, 0, 0)
78 ZEND_END_ARG_INFO();
79 /* }}} */
80
81 /*
82 * class xsl_xsltprocessor
83 *
84 * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
85 * Since:
86 */
87
88 const zend_function_entry php_xsl_xsltprocessor_class_functions[] = {
89 PHP_FALIAS(importStylesheet, xsl_xsltprocessor_import_stylesheet, arginfo_xsl_xsltprocessor_import_stylesheet)
90 PHP_FALIAS(transformToDoc, xsl_xsltprocessor_transform_to_doc, arginfo_xsl_xsltprocessor_transform_to_doc)
91 PHP_FALIAS(transformToUri, xsl_xsltprocessor_transform_to_uri, arginfo_xsl_xsltprocessor_transform_to_uri)
92 PHP_FALIAS(transformToXml, xsl_xsltprocessor_transform_to_xml, arginfo_xsl_xsltprocessor_transform_to_xml)
93 PHP_FALIAS(setParameter, xsl_xsltprocessor_set_parameter, arginfo_xsl_xsltprocessor_set_parameter)
94 PHP_FALIAS(getParameter, xsl_xsltprocessor_get_parameter, arginfo_xsl_xsltprocessor_get_parameter)
95 PHP_FALIAS(removeParameter, xsl_xsltprocessor_remove_parameter, arginfo_xsl_xsltprocessor_remove_parameter)
96 PHP_FALIAS(hasExsltSupport, xsl_xsltprocessor_has_exslt_support, arginfo_xsl_xsltprocessor_has_exslt_support)
97 PHP_FALIAS(registerPHPFunctions, xsl_xsltprocessor_register_php_functions, arginfo_xsl_xsltprocessor_register_php_functions)
98 PHP_FALIAS(setProfiling, xsl_xsltprocessor_set_profiling, arginfo_xsl_xsltprocessor_set_profiling)
99 PHP_FALIAS(setSecurityPrefs, xsl_xsltprocessor_set_security_prefs, arginfo_xsl_xsltprocessor_set_security_prefs)
100 PHP_FALIAS(getSecurityPrefs, xsl_xsltprocessor_get_security_prefs, arginfo_xsl_xsltprocessor_get_security_prefs)
101 PHP_FE_END
102 };
103
104 /* {{{ php_xsl_xslt_string_to_xpathexpr()
105 Translates a string to a XPath Expression */
php_xsl_xslt_string_to_xpathexpr(const char * str)106 static char *php_xsl_xslt_string_to_xpathexpr(const char *str)
107 {
108 const xmlChar *string = (const xmlChar *)str;
109
110 xmlChar *value;
111 int str_len;
112
113 str_len = xmlStrlen(string) + 3;
114
115 if (xmlStrchr(string, '"')) {
116 if (xmlStrchr(string, '\'')) {
117 php_error_docref(NULL, E_WARNING, "Cannot create XPath expression (string contains both quote and double-quotes)");
118 return NULL;
119 }
120 value = (xmlChar*) safe_emalloc (str_len, sizeof(xmlChar), 0);
121 snprintf((char*)value, str_len, "'%s'", string);
122 } else {
123 value = (xmlChar*) safe_emalloc (str_len, sizeof(xmlChar), 0);
124 snprintf((char *)value, str_len, "\"%s\"", string);
125 }
126 return (char *) value;
127 }
128 /* }}} */
129
130 /* {{{ php_xsl_xslt_make_params()
131 Translates a PHP array to a libxslt parameters array */
php_xsl_xslt_make_params(HashTable * parht,int xpath_params)132 static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params)
133 {
134
135 int parsize;
136 zval *value;
137 char *xpath_expr;
138 zend_string *string_key;
139 char **params = NULL;
140 int i = 0;
141
142 parsize = (2 * zend_hash_num_elements(parht) + 1) * sizeof(char *);
143 params = (char **)safe_emalloc((2 * zend_hash_num_elements(parht) + 1), sizeof(char *), 0);
144 memset((char *)params, 0, parsize);
145
146 ZEND_HASH_FOREACH_STR_KEY_VAL(parht, string_key, value) {
147 if (string_key == NULL) {
148 php_error_docref(NULL, E_WARNING, "Invalid argument or parameter array");
149 efree(params);
150 return NULL;
151 } else {
152 if (Z_TYPE_P(value) != IS_STRING) {
153 if (!try_convert_to_string(value)) {
154 efree(params);
155 return NULL;
156 }
157 }
158
159 if (!xpath_params) {
160 xpath_expr = php_xsl_xslt_string_to_xpathexpr(Z_STRVAL_P(value));
161 } else {
162 xpath_expr = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value));
163 }
164 if (xpath_expr) {
165 params[i++] = estrndup(ZSTR_VAL(string_key), ZSTR_LEN(string_key));
166 params[i++] = xpath_expr;
167 }
168 }
169 } ZEND_HASH_FOREACH_END();
170
171 params[i++] = NULL;
172
173 return params;
174 }
175 /* }}} */
176
xsl_ext_function_php(xmlXPathParserContextPtr ctxt,int nargs,int type)177 static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
178 {
179 xsltTransformContextPtr tctxt;
180 zval *args = NULL;
181 zval retval;
182 int result, i;
183 int error = 0;
184 zend_fcall_info fci;
185 zval handler;
186 xmlXPathObjectPtr obj;
187 char *str;
188 xsl_object *intern;
189 zend_string *callable = NULL;
190
191
192 if (! zend_is_executing()) {
193 xsltGenericError(xsltGenericErrorContext,
194 "xsltExtFunctionTest: Function called from outside of PHP\n");
195 error = 1;
196 } else {
197 tctxt = xsltXPathGetTransformContext(ctxt);
198 if (tctxt == NULL) {
199 xsltGenericError(xsltGenericErrorContext,
200 "xsltExtFunctionTest: failed to get the transformation context\n");
201 error = 1;
202 } else {
203 intern = (xsl_object*)tctxt->_private;
204 if (intern == NULL) {
205 xsltGenericError(xsltGenericErrorContext,
206 "xsltExtFunctionTest: failed to get the internal object\n");
207 error = 1;
208 }
209 else if (intern->registerPhpFunctions == 0) {
210 xsltGenericError(xsltGenericErrorContext,
211 "xsltExtFunctionTest: PHP Object did not register PHP functions\n");
212 error = 1;
213 }
214 }
215 }
216
217 if (error == 1) {
218 for (i = nargs - 1; i >= 0; i--) {
219 obj = valuePop(ctxt);
220 if (obj) {
221 xmlXPathFreeObject(obj);
222 }
223 }
224 return;
225 }
226
227 fci.param_count = nargs - 1;
228 if (fci.param_count > 0) {
229 args = safe_emalloc(fci.param_count, sizeof(zval), 0);
230 }
231 /* Reverse order to pop values off ctxt stack */
232 for (i = nargs - 2; i >= 0; i--) {
233 obj = valuePop(ctxt);
234 if (obj == NULL) {
235 ZVAL_NULL(&args[i]);
236 continue;
237 }
238 switch (obj->type) {
239 case XPATH_STRING:
240 ZVAL_STRING(&args[i], (char *)obj->stringval);
241 break;
242 case XPATH_BOOLEAN:
243 ZVAL_BOOL(&args[i], obj->boolval);
244 break;
245 case XPATH_NUMBER:
246 ZVAL_DOUBLE(&args[i], obj->floatval);
247 break;
248 case XPATH_NODESET:
249 if (type == 1) {
250 str = (char*)xmlXPathCastToString(obj);
251 ZVAL_STRING(&args[i], str);
252 xmlFree(str);
253 } else if (type == 2) {
254 int j;
255 dom_object *domintern = (dom_object *)intern->doc;
256 if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
257 array_init(&args[i]);
258 for (j = 0; j < obj->nodesetval->nodeNr; j++) {
259 xmlNodePtr node = obj->nodesetval->nodeTab[j];
260 zval child;
261 /* not sure, if we need this... it's copied from xpath.c */
262 if (node->type == XML_NAMESPACE_DECL) {
263 xmlNsPtr curns;
264 xmlNodePtr nsparent;
265
266 nsparent = node->_private;
267 curns = xmlNewNs(NULL, node->name, NULL);
268 if (node->children) {
269 curns->prefix = xmlStrdup((xmlChar *)node->children);
270 }
271 if (node->children) {
272 node = xmlNewDocNode(node->doc, NULL, (xmlChar *) node->children, node->name);
273 } else {
274 node = xmlNewDocNode(node->doc, NULL, (const xmlChar *) "xmlns", node->name);
275 }
276 node->type = XML_NAMESPACE_DECL;
277 node->parent = nsparent;
278 node->ns = curns;
279 } else {
280 node = xmlDocCopyNode(node, domintern->document->ptr, 1);
281 }
282
283 php_dom_create_object(node, &child, domintern);
284 add_next_index_zval(&args[i], &child);
285 }
286 } else {
287 ZVAL_EMPTY_ARRAY(&args[i]);
288 }
289 }
290 break;
291 default:
292 str = (char *) xmlXPathCastToString(obj);
293 ZVAL_STRING(&args[i], str);
294 xmlFree(str);
295 }
296 xmlXPathFreeObject(obj);
297 }
298
299 fci.size = sizeof(fci);
300 if (fci.param_count > 0) {
301 fci.params = args;
302 } else {
303 fci.params = NULL;
304 }
305
306
307 obj = valuePop(ctxt);
308 if (obj == NULL || obj->stringval == NULL) {
309 php_error_docref(NULL, E_WARNING, "Handler name must be a string");
310 xmlXPathFreeObject(obj);
311 valuePush(ctxt, xmlXPathNewString((const xmlChar *) ""));
312 if (fci.param_count > 0) {
313 for (i = 0; i < nargs - 1; i++) {
314 zval_ptr_dtor(&args[i]);
315 }
316 efree(args);
317 }
318 return;
319 }
320 ZVAL_STRING(&handler, (char *) obj->stringval);
321 xmlXPathFreeObject(obj);
322
323 ZVAL_COPY_VALUE(&fci.function_name, &handler);
324 fci.object = NULL;
325 fci.retval = &retval;
326 fci.no_separation = 0;
327 /*fci.function_handler_cache = &function_ptr;*/
328 if (!zend_make_callable(&handler, &callable)) {
329 php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", ZSTR_VAL(callable));
330 valuePush(ctxt, xmlXPathNewString((const xmlChar *) ""));
331 } else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable) == 0) {
332 php_error_docref(NULL, E_WARNING, "Not allowed to call handler '%s()'", ZSTR_VAL(callable));
333 /* Push an empty string, so that we at least have an xslt result... */
334 valuePush(ctxt, xmlXPathNewString((const xmlChar *) ""));
335 } else {
336 result = zend_call_function(&fci, NULL);
337 if (result == FAILURE) {
338 if (Z_TYPE(handler) == IS_STRING) {
339 php_error_docref(NULL, E_WARNING, "Unable to call handler %s()", Z_STRVAL(handler));
340 valuePush(ctxt, xmlXPathNewString((const xmlChar *) ""));
341 }
342 /* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */
343 } else if (Z_ISUNDEF(retval)) {
344 } else {
345 if (Z_TYPE(retval) == IS_OBJECT && instanceof_function(Z_OBJCE(retval), dom_node_class_entry)) {
346 xmlNode *nodep;
347 dom_object *obj;
348 if (intern->node_list == NULL) {
349 intern->node_list = zend_new_array(0);
350 }
351 Z_ADDREF(retval);
352 zend_hash_next_index_insert(intern->node_list, &retval);
353 obj = Z_DOMOBJ_P(&retval);
354 nodep = dom_object_get_node(obj);
355 valuePush(ctxt, xmlXPathNewNodeSet(nodep));
356 } else if (Z_TYPE(retval) == IS_TRUE || Z_TYPE(retval) == IS_FALSE) {
357 valuePush(ctxt, xmlXPathNewBoolean(Z_TYPE(retval) == IS_TRUE));
358 } else if (Z_TYPE(retval) == IS_OBJECT) {
359 php_error_docref(NULL, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
360 valuePush(ctxt, xmlXPathNewString((const xmlChar *) ""));
361 } else {
362 convert_to_string_ex(&retval);
363 valuePush(ctxt, xmlXPathNewString((xmlChar *) Z_STRVAL(retval)));
364 }
365 zval_ptr_dtor(&retval);
366 }
367 }
368 zend_string_release_ex(callable, 0);
369 zval_ptr_dtor(&handler);
370 if (fci.param_count > 0) {
371 for (i = 0; i < nargs - 1; i++) {
372 zval_ptr_dtor(&args[i]);
373 }
374 efree(args);
375 }
376 }
377 /* }}} */
378
xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt,int nargs)379 void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
380 {
381 xsl_ext_function_php(ctxt, nargs, 1);
382 }
383 /* }}} */
384
xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt,int nargs)385 void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
386 {
387 xsl_ext_function_php(ctxt, nargs, 2);
388 }
389 /* }}} */
390
391 /* {{{ proto void xsl_xsltprocessor_import_stylesheet(domdocument doc)
392 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
393 Since:
394 */
PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)395 PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
396 {
397 zval *id, *docp = NULL;
398 xmlDoc *doc = NULL, *newdoc = NULL;
399 xsltStylesheetPtr sheetp, oldsheetp;
400 xsl_object *intern;
401 int prevSubstValue, prevExtDtdValue, clone_docu = 0;
402 xmlNode *nodep = NULL;
403 zval *cloneDocu, member, rv;
404
405 id = ZEND_THIS;
406 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &docp) == FAILURE) {
407 RETURN_FALSE;
408 }
409
410 nodep = php_libxml_import_node(docp);
411
412 if (nodep) {
413 doc = nodep->doc;
414 }
415 if (doc == NULL) {
416 php_error(E_WARNING, "Invalid Document");
417 RETURN_FALSE;
418 }
419
420 /* libxslt uses _private, so we must copy the imported
421 stylesheet document otherwise the node proxies will be a mess */
422 newdoc = xmlCopyDoc(doc, 1);
423 xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
424 prevSubstValue = xmlSubstituteEntitiesDefault(1);
425 prevExtDtdValue = xmlLoadExtDtdDefaultValue;
426 xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
427
428 sheetp = xsltParseStylesheetDoc(newdoc);
429 xmlSubstituteEntitiesDefault(prevSubstValue);
430 xmlLoadExtDtdDefaultValue = prevExtDtdValue;
431
432 if (!sheetp) {
433 xmlFreeDoc(newdoc);
434 RETURN_FALSE;
435 }
436
437 intern = Z_XSL_P(id);
438
439 ZVAL_STRING(&member, "cloneDocument");
440 cloneDocu = zend_std_read_property(id, &member, BP_VAR_IS, NULL, &rv);
441 if (Z_TYPE_P(cloneDocu) != IS_NULL) {
442 convert_to_long(cloneDocu);
443 clone_docu = Z_LVAL_P(cloneDocu);
444 }
445 zval_ptr_dtor(&member);
446 if (clone_docu == 0) {
447 /* check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation */
448 nodep = xmlDocGetRootElement(sheetp->doc);
449 if (nodep && (nodep = nodep->children)) {
450 while (nodep) {
451 if (nodep->type == XML_ELEMENT_NODE && xmlStrEqual(nodep->name, (const xmlChar *) "key") && xmlStrEqual(nodep->ns->href, XSLT_NAMESPACE)) {
452 intern->hasKeys = 1;
453 break;
454 }
455 nodep = nodep->next;
456 }
457 }
458 } else {
459 intern->hasKeys = clone_docu;
460 }
461
462 if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) {
463 /* free wrapper */
464 if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) {
465 ((xsltStylesheetPtr) intern->ptr)->_private = NULL;
466 }
467 xsltFreeStylesheet((xsltStylesheetPtr) intern->ptr);
468 intern->ptr = NULL;
469 }
470
471 php_xsl_set_object(id, sheetp);
472 RETVAL_TRUE;
473 }
474 /* }}} end xsl_xsltprocessor_import_stylesheet */
475
php_xsl_apply_stylesheet(zval * id,xsl_object * intern,xsltStylesheetPtr style,zval * docp)476 static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStylesheetPtr style, zval *docp) /* {{{ */
477 {
478 xmlDocPtr newdocp = NULL;
479 xmlDocPtr doc = NULL;
480 xmlNodePtr node = NULL;
481 xsltTransformContextPtr ctxt;
482 php_libxml_node_object *object;
483 char **params = NULL;
484 int clone;
485 zval *doXInclude, member, rv;
486 FILE *f;
487 int secPrefsError = 0;
488 int secPrefsValue;
489 xsltSecurityPrefsPtr secPrefs = NULL;
490
491 node = php_libxml_import_node(docp);
492
493 if (node) {
494 doc = node->doc;
495 }
496 if (doc == NULL) {
497 php_error_docref(NULL, E_WARNING, "Invalid Document");
498 return NULL;
499 }
500
501 if (style == NULL) {
502 php_error_docref(NULL, E_WARNING, "No stylesheet associated to this object");
503 return NULL;
504 }
505
506 if (intern->profiling) {
507 if (php_check_open_basedir(intern->profiling)) {
508 f = NULL;
509 } else {
510 f = VCWD_FOPEN(intern->profiling, "w");
511 }
512 } else {
513 f = NULL;
514 }
515
516 if (intern->parameter) {
517 params = php_xsl_xslt_make_params(intern->parameter, 0);
518 }
519
520 intern->doc = emalloc(sizeof(php_libxml_node_object));
521 memset(intern->doc, 0, sizeof(php_libxml_node_object));
522
523 if (intern->hasKeys == 1) {
524 doc = xmlCopyDoc(doc, 1);
525 } else {
526 object = Z_LIBXML_NODE_P(docp);
527 intern->doc->document = object->document;
528 }
529
530 php_libxml_increment_doc_ref(intern->doc, doc);
531
532 ctxt = xsltNewTransformContext(style, doc);
533 ctxt->_private = (void *) intern;
534
535 ZVAL_STRING(&member, "doXInclude");
536 doXInclude = zend_std_read_property(id, &member, BP_VAR_IS, NULL, &rv);
537 if (Z_TYPE_P(doXInclude) != IS_NULL) {
538 convert_to_long(doXInclude);
539 ctxt->xinclude = Z_LVAL_P(doXInclude);
540 }
541 zval_ptr_dtor(&member);
542
543 secPrefsValue = intern->securityPrefs;
544
545 /* if securityPrefs is set to NONE, we don't have to do any checks, but otherwise... */
546 if (secPrefsValue != XSL_SECPREF_NONE) {
547 secPrefs = xsltNewSecurityPrefs();
548 if (secPrefsValue & XSL_SECPREF_READ_FILE ) {
549 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid)) {
550 secPrefsError = 1;
551 }
552 }
553 if (secPrefsValue & XSL_SECPREF_WRITE_FILE ) {
554 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid)) {
555 secPrefsError = 1;
556 }
557 }
558 if (secPrefsValue & XSL_SECPREF_CREATE_DIRECTORY ) {
559 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid)) {
560 secPrefsError = 1;
561 }
562 }
563 if (secPrefsValue & XSL_SECPREF_READ_NETWORK) {
564 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid)) {
565 secPrefsError = 1;
566 }
567 }
568 if (secPrefsValue & XSL_SECPREF_WRITE_NETWORK) {
569 if (0 != xsltSetSecurityPrefs(secPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid)) {
570 secPrefsError = 1;
571 }
572 }
573
574 if (0 != xsltSetCtxtSecurityPrefs(secPrefs, ctxt)) {
575 secPrefsError = 1;
576 }
577 }
578
579 if (secPrefsError == 1) {
580 php_error_docref(NULL, E_WARNING, "Can't set libxslt security properties, not doing transformation for security reasons");
581 } else {
582 newdocp = xsltApplyStylesheetUser(style, doc, (const char**) params, NULL, f, ctxt);
583 }
584 if (f) {
585 fclose(f);
586 }
587
588 xsltFreeTransformContext(ctxt);
589 if (secPrefs) {
590 xsltFreeSecurityPrefs(secPrefs);
591 }
592
593 if (intern->node_list != NULL) {
594 zend_hash_destroy(intern->node_list);
595 FREE_HASHTABLE(intern->node_list);
596 intern->node_list = NULL;
597 }
598
599 php_libxml_decrement_doc_ref(intern->doc);
600 efree(intern->doc);
601 intern->doc = NULL;
602
603 if (params) {
604 clone = 0;
605 while(params[clone]) {
606 efree(params[clone++]);
607 }
608 efree(params);
609 }
610
611 return newdocp;
612
613 }
614 /* }}} */
615
616 /* {{{ proto domdocument xsl_xsltprocessor_transform_to_doc(domnode doc)
617 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#
618 Since:
619 */
PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)620 PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
621 {
622 zval *id, *docp = NULL;
623 xmlDoc *newdocp;
624 xsltStylesheetPtr sheetp;
625 zend_string *ret_class = NULL;
626 xsl_object *intern;
627
628 id = ZEND_THIS;
629 intern = Z_XSL_P(id);
630 sheetp = (xsltStylesheetPtr) intern->ptr;
631
632 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|S!", &docp, &ret_class) == FAILURE) {
633 RETURN_FALSE;
634 }
635
636 newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp);
637
638 if (newdocp) {
639 if (ret_class) {
640 zend_string *curclass_name;
641 zend_class_entry *curce, *ce;
642 php_libxml_node_object *interndoc;
643
644 curce = Z_OBJCE_P(docp);
645 curclass_name = curce->name;
646 while (curce->parent != NULL) {
647 curce = curce->parent;
648 }
649
650 ce = zend_lookup_class(ret_class);
651 if (ce == NULL || !instanceof_function(ce, curce)) {
652 xmlFreeDoc(newdocp);
653 php_error_docref(NULL, E_WARNING,
654 "Expecting class compatible with %s, '%s' given", ZSTR_VAL(curclass_name), ZSTR_VAL(ret_class));
655 RETURN_FALSE;
656 }
657
658 object_init_ex(return_value, ce);
659
660 interndoc = Z_LIBXML_NODE_P(return_value);
661 php_libxml_increment_doc_ref(interndoc, newdocp);
662 php_libxml_increment_node_ptr(interndoc, (xmlNodePtr)newdocp, (void *)interndoc);
663 } else {
664 php_dom_create_object((xmlNodePtr) newdocp, return_value, NULL);
665 }
666 } else {
667 RETURN_FALSE;
668 }
669
670 }
671 /* }}} end xsl_xsltprocessor_transform_to_doc */
672
673 /* {{{ proto int xsl_xsltprocessor_transform_to_uri(domdocument doc, string uri)
674 */
PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)675 PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
676 {
677 zval *id, *docp = NULL;
678 xmlDoc *newdocp;
679 xsltStylesheetPtr sheetp;
680 int ret;
681 size_t uri_len;
682 char *uri;
683 xsl_object *intern;
684
685 id = ZEND_THIS;
686 intern = Z_XSL_P(id);
687 sheetp = (xsltStylesheetPtr) intern->ptr;
688
689 if (zend_parse_parameters(ZEND_NUM_ARGS(), "op", &docp, &uri, &uri_len) == FAILURE) {
690 RETURN_FALSE;
691 }
692
693 newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp);
694
695 ret = -1;
696 if (newdocp) {
697 ret = xsltSaveResultToFilename(uri, newdocp, sheetp, 0);
698 xmlFreeDoc(newdocp);
699 }
700
701 RETVAL_LONG(ret);
702 }
703 /* }}} end xsl_xsltprocessor_transform_to_uri */
704
705 /* {{{ proto string xsl_xsltprocessor_transform_to_xml(domdocument doc)
706 */
PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)707 PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
708 {
709 zval *id, *docp = NULL;
710 xmlDoc *newdocp;
711 xsltStylesheetPtr sheetp;
712 int ret;
713 xmlChar *doc_txt_ptr;
714 int doc_txt_len;
715 xsl_object *intern;
716
717 id = ZEND_THIS;
718 intern = Z_XSL_P(id);
719 sheetp = (xsltStylesheetPtr) intern->ptr;
720
721 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &docp) == FAILURE) {
722 RETURN_FALSE;
723 }
724
725 newdocp = php_xsl_apply_stylesheet(id, intern, sheetp, docp);
726
727 ret = -1;
728 if (newdocp) {
729 ret = xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, newdocp, sheetp);
730 if (doc_txt_ptr && doc_txt_len) {
731 RETVAL_STRINGL((char *) doc_txt_ptr, doc_txt_len);
732 xmlFree(doc_txt_ptr);
733 }
734 xmlFreeDoc(newdocp);
735 }
736
737 if (ret < 0) {
738 RETURN_FALSE;
739 }
740 }
741 /* }}} end xsl_xsltprocessor_transform_to_xml */
742
743 /* {{{ proto bool xsl_xsltprocessor_set_parameter(string namespace, mixed name [, string value])
744 */
PHP_FUNCTION(xsl_xsltprocessor_set_parameter)745 PHP_FUNCTION(xsl_xsltprocessor_set_parameter)
746 {
747
748 zval *id;
749 zval *array_value, *entry, new_string;
750 xsl_object *intern;
751 char *namespace;
752 size_t namespace_len;
753 zend_string *string_key, *name, *value;
754 DOM_GET_THIS(id);
755
756 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "sa", &namespace, &namespace_len, &array_value) == SUCCESS) {
757 intern = Z_XSL_P(id);
758 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(array_value), string_key, entry) {
759 zval tmp;
760 zend_string *str;
761
762 if (string_key == NULL) {
763 php_error_docref(NULL, E_WARNING, "Invalid parameter array");
764 RETURN_FALSE;
765 }
766 str = zval_try_get_string(entry);
767 if (UNEXPECTED(!str)) {
768 return;
769 }
770 ZVAL_STR(&tmp, str);
771 zend_hash_update(intern->parameter, string_key, &tmp);
772 } ZEND_HASH_FOREACH_END();
773 RETURN_TRUE;
774 } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "sSS", &namespace, &namespace_len, &name, &value) == SUCCESS) {
775
776 intern = Z_XSL_P(id);
777
778 ZVAL_STR_COPY(&new_string, value);
779
780 zend_hash_update(intern->parameter, name, &new_string);
781 RETURN_TRUE;
782 } else {
783 WRONG_PARAM_COUNT;
784 }
785
786 }
787 /* }}} end xsl_xsltprocessor_set_parameter */
788
789 /* {{{ proto string xsl_xsltprocessor_get_parameter(string namespace, string name)
790 */
PHP_FUNCTION(xsl_xsltprocessor_get_parameter)791 PHP_FUNCTION(xsl_xsltprocessor_get_parameter)
792 {
793 zval *id;
794 char *namespace;
795 size_t namespace_len = 0;
796 zval *value;
797 zend_string *name;
798 xsl_object *intern;
799
800 DOM_GET_THIS(id);
801
802 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS", &namespace, &namespace_len, &name) == FAILURE) {
803 RETURN_FALSE;
804 }
805 intern = Z_XSL_P(id);
806 if ((value = zend_hash_find(intern->parameter, name)) != NULL) {
807 RETURN_STR(zval_get_string(value));
808 } else {
809 RETURN_FALSE;
810 }
811 }
812 /* }}} end xsl_xsltprocessor_get_parameter */
813
814 /* {{{ proto bool xsl_xsltprocessor_remove_parameter(string namespace, string name)
815 */
PHP_FUNCTION(xsl_xsltprocessor_remove_parameter)816 PHP_FUNCTION(xsl_xsltprocessor_remove_parameter)
817 {
818 zval *id;
819 size_t namespace_len = 0;
820 char *namespace;
821 zend_string *name;
822 xsl_object *intern;
823
824 DOM_GET_THIS(id);
825
826 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS", &namespace, &namespace_len, &name) == FAILURE) {
827 RETURN_FALSE;
828 }
829 intern = Z_XSL_P(id);
830 if (zend_hash_del(intern->parameter, name) == SUCCESS) {
831 RETURN_TRUE;
832 } else {
833 RETURN_FALSE;
834 }
835 }
836 /* }}} end xsl_xsltprocessor_remove_parameter */
837
838 /* {{{ proto void xsl_xsltprocessor_register_php_functions([mixed $restrict])
839 */
PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)840 PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)
841 {
842 zval *id;
843 xsl_object *intern;
844 zval *array_value, *entry, new_string;
845 zend_string *name;
846
847 DOM_GET_THIS(id);
848
849 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "a", &array_value) == SUCCESS) {
850 intern = Z_XSL_P(id);
851
852 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array_value), entry) {
853 zend_string *str = zval_try_get_string(entry);
854 if (UNEXPECTED(!str)) {
855 return;
856 }
857 ZVAL_LONG(&new_string, 1);
858 zend_hash_update(intern->registered_phpfunctions, str, &new_string);
859 zend_string_release(str);
860 } ZEND_HASH_FOREACH_END();
861
862 intern->registerPhpFunctions = 2;
863 } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "S", &name) == SUCCESS) {
864 intern = Z_XSL_P(id);
865
866 ZVAL_LONG(&new_string,1);
867 zend_hash_update(intern->registered_phpfunctions, name, &new_string);
868 intern->registerPhpFunctions = 2;
869
870 } else {
871 intern = Z_XSL_P(id);
872 intern->registerPhpFunctions = 1;
873 }
874
875 }
876 /* }}} end xsl_xsltprocessor_register_php_functions(); */
877
878 /* {{{ proto bool xsl_xsltprocessor_set_profiling(string filename) */
PHP_FUNCTION(xsl_xsltprocessor_set_profiling)879 PHP_FUNCTION(xsl_xsltprocessor_set_profiling)
880 {
881 zval *id;
882 xsl_object *intern;
883 char *filename = NULL;
884 size_t filename_len;
885 DOM_GET_THIS(id);
886
887 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p!", &filename, &filename_len) == SUCCESS) {
888 intern = Z_XSL_P(id);
889 if (intern->profiling) {
890 efree(intern->profiling);
891 }
892 if (filename != NULL) {
893 intern->profiling = estrndup(filename, filename_len);
894 } else {
895 intern->profiling = NULL;
896 }
897 RETURN_TRUE;
898 } else {
899 WRONG_PARAM_COUNT;
900 }
901 }
902 /* }}} end xsl_xsltprocessor_set_profiling */
903
904 /* {{{ proto int xsl_xsltprocessor_set_security_prefs(int securityPrefs) */
PHP_FUNCTION(xsl_xsltprocessor_set_security_prefs)905 PHP_FUNCTION(xsl_xsltprocessor_set_security_prefs)
906 {
907 zval *id;
908 xsl_object *intern;
909 zend_long securityPrefs, oldSecurityPrefs;
910
911 DOM_GET_THIS(id);
912 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &securityPrefs) == FAILURE) {
913 return;
914 }
915 intern = Z_XSL_P(id);
916 oldSecurityPrefs = intern->securityPrefs;
917 intern->securityPrefs = securityPrefs;
918 /* set this to 1 so that we know, it was set through this method. Can be removed, when we remove the ini setting */
919 intern->securityPrefsSet = 1;
920 RETURN_LONG(oldSecurityPrefs);
921 }
922 /* }}} end xsl_xsltprocessor_set_security_prefs */
923
924 /* {{{ proto int xsl_xsltprocessor_get_security_prefs() */
PHP_FUNCTION(xsl_xsltprocessor_get_security_prefs)925 PHP_FUNCTION(xsl_xsltprocessor_get_security_prefs)
926 {
927 zval *id;
928 xsl_object *intern;
929
930 DOM_GET_THIS(id);
931 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "") == SUCCESS) {
932 intern = Z_XSL_P(id);
933 RETURN_LONG(intern->securityPrefs);
934 } else {
935 WRONG_PARAM_COUNT;
936 }
937 }
938 /* }}} end xsl_xsltprocessor_get_security_prefs */
939
940 /* {{{ proto bool xsl_xsltprocessor_has_exslt_support()
941 */
PHP_FUNCTION(xsl_xsltprocessor_has_exslt_support)942 PHP_FUNCTION(xsl_xsltprocessor_has_exslt_support)
943 {
944 #if HAVE_XSL_EXSLT
945 RETURN_TRUE;
946 #else
947 RETURN_FALSE;
948 #endif
949 }
950 /* }}} end xsl_xsltprocessor_has_exslt_support(); */
951