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

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