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