root/ext/xsl/xsltprocessor.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_xsl_xslt_string_to_xpathexpr
  2. php_xsl_xslt_make_params
  3. xsl_ext_function_php
  4. xsl_ext_function_string_php
  5. xsl_ext_function_object_php
  6. PHP_FUNCTION
  7. php_xsl_apply_stylesheet
  8. PHP_FUNCTION
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. PHP_FUNCTION
  12. PHP_FUNCTION
  13. PHP_FUNCTION
  14. PHP_FUNCTION
  15. PHP_FUNCTION
  16. PHP_FUNCTION
  17. PHP_FUNCTION
  18. PHP_FUNCTION

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

/* [<][>][^][v][top][bottom][index][help] */