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