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