File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / xsl / xsltprocessor.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:48:05 2012 UTC (12 years, 4 months ago) by misho
Branches: php, MAIN
CVS tags: v5_3_10, HEAD
php

    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,v 1.1.1.1 2012/02/21 23:48:05 misho Exp $ */
   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:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>