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