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