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