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