Return to xsltprocessor.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / xsl |
1.1 ! misho 1: /* ! 2: +----------------------------------------------------------------------+ ! 3: | PHP Version 5 | ! 4: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 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: xsltprocessor.c 321634 2012-01-01 13:15:04Z felipe $ */ ! 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: ! 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: ! 83: const 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 */ ! 99: static 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 */ ! 125: static 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: ! 173: static 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: ! 367: void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */ ! 368: { ! 369: xsl_ext_function_php(ctxt, nargs, 1); ! 370: } ! 371: /* }}} */ ! 372: ! 373: void 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); ! 380: URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# ! 381: Since: ! 382: */ ! 383: PHP_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: ! 466: static 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); ! 612: URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# ! 613: Since: ! 614: */ ! 615: PHP_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: */ ! 672: PHP_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: */ ! 707: PHP_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: */ ! 745: PHP_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: */ ! 796: PHP_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: */ ! 821: PHP_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: */ ! 844: PHP_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) */ ! 887: PHP_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: */ ! 914: PHP_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: */